I'm designing a Automated Acceptance Test using Python Selenium to fill in web form and check for the errors that are shown on the webpage then compared to my expected results to give me some sort of "Success" and "Fail" type of result.
Currently, I am testing on a website with only 3 fields. Here is the url: https://familydrive.aia.com.my/V1/index.jsp
It only requires IC, Postcode and Vehicle Registration Number. However, let's say if there was another field "Name". I'd have to add these repetitive code into my code
# Enter Name
input_Name = driver.find_element(By.ID, "name")
input_Name.send_keys(entry['Name'])
time.sleep(1)
and to test the "error". It varies between testing if the button is working or if the element is visible, etc.
So, how can I do this without having to repeat this process over and over, every time a new field is added? I was thinking of adding the fields into an excel sheet and use a for loop on it but I can't really figure out where to place it in my code.
Here is my code:
import datetime
import os.path
import time
import numpy as np
import openpyxl
import pandas as pd
import selenium
from selenium import webdriver
from selenium.common.exceptions import (ElementClickInterceptedException,
ElementNotInteractableException,
NoSuchElementException)
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
ProjectName = 'Automated UAT'
# Excel Path
ExcelPath = 'C:/Users/TaE/Desktop/Python Selenium Project/testPA.xlsx'
# Convert Excel Data Type
ExcelConverters = {'IC':str, 'Postcode':str, 'VehRegNum':str}
# Web Form url
url = 'https://familydrive.aia.com.my/V1/index.jsp'
# Set ChromeDriver path
DriverPath = 'C:/Users/TaE/Desktop/Python Selenium Project/driver/chromedriver.exe'
driver = webdriver.Chrome(executable_path=DriverPath)
# Empty Result Data Frame
result_df = pd.DataFrame(columns = ['e1', 'e2', 'e3', 'e4'])
try:
try:
df1 = pd.read_excel (ExcelPath, header = 0, converters = ExcelConverters)
df = df1.replace(np.nan, '', regex= True)
data = df.iloc[:,0]
time.sleep(1)
wb = openpyxl.load_workbook(ExcelPath)
ws = wb.worksheets[0]
maxrow = ws.max_row
# for loop
for i in range(0, maxrow 1):
print("attempt row " str(i))
# Get Website
driver.get(url)
# Maximize Window
driver.maximize_window()
entry = df.loc[i]
# Enter IC Number
input_IC = driver.find_element(By.ID, "icno")
input_IC.send_keys(entry['IC'])
time.sleep(1)
# Enter Postcode
input_Postcode = driver.find_element(By.ID, "postcode")
input_Postcode.send_keys(entry['Postcode'])
time.sleep(1)
# Enter Vehicle Registration Number
input_VehRegNum = driver.find_element(By.ID, "registerno")
input_VehRegNum.send_keys(entry['VehRegNum'])
time.sleep(1)
# Click on Button
button = driver.find_element(By.NAME, 'btnGenQuote')
button.click()
time.sleep(5)
# Error Messages/ Results and Locating errors
### Problem: Error must be in order for it to work ###
try:
try:
try:
try:
IC_error1 = driver.find_element(By.XPATH, "//*[contains(text(), 'IC number is mandatory')]")
e1 = ["T"]
print("IC_error1 found")
except NoSuchElementException:
e1 = ["F"]
print("IC_error1 not found")
IC_error2 = driver.find_element(By.XPATH, "//*[contains(text(), 'Invalid IC format')]")
e2 = ["T"]
print("IC_error2 found")
except NoSuchElementException:
e2 = ["F"]
print("IC_error2 not found")
Postcode_error = driver.find_element(By.XPATH, "//*[contains(text(), 'Postcode number is mandatory')]")
e3 = ["T"]
print("Postcode_error found")
except NoSuchElementException:
e3 = ["F"]
print("Postcode_error not found")
RegNo_error = driver.find_element(By.XPATH, "//*[contains(text(), 'Vehicle Registration Number is mandatory')]")
e4 = ["T"]
print("RegNo_error found")
except NoSuchElementException:
e4 = ["F"]
print("RegNo_error not found")
time.sleep(3)
new_result = pd.DataFrame(zip(e1,e2,e3,e4), columns = ['e1', 'e2', 'e3', 'e4'])
result_df = pd.concat([result_df, new_result])
result_df.reset_index(drop=True, inplace=True)
print(result_df)
# For screenshot
# timestamp = datetime.datetime.now().strftime('%d%m%Y_%H%M%S')
# driver.get_screenshot_as_file(ProjectName '_' timestamp '.png')
driver.get_screenshot_as_file(ProjectName '_' str(i) '.png')
time.sleep(2)
except KeyError:
print("If the number of attempts is lesser than the number of data rows, it could be caused by the Excel Column Row don't match with the code.")
print("Process is COMPLETED")
result_df.to_excel('Result.xlsx', sheet_name= 'result') # Ensure "Result" workbook is closed to update
pass # to skip KeyError when there isn't any data afterwards
finally:
driver.quit()
If you have any ideas on how to enhance my code even more. I'm open to suggestions :")
CodePudding user response:
You can put it into a function to remove the repeating code. The function can have two parameters.
An enum coresponding to the search type (i.e if you want to search element by name or by id)
The search value
Example:
import enum
class idOrName(enum.Enum):
id: Id
name: Name
def findAndSendKey(searchType, searchString, entryValue):
element = ''
if searchType == idOrName.id:
element = driver.find_element(By.ID, searchString)
if searchType == idOrName.name:
element = driver.find_element(By.NAME, searchString)
element.send_keys(entry[entryValue])
time.sleep(1)
Now you can run it as:
findAndSendKey(idOrName.id, "registerno", "VehRegNum")
And call this function where ever required