Preface
In the last article, we have learned how the data-driven automated testing framework builds and drives tests! So in this article we will learn how keyword-driven testing drives automated testing to complete the entire testing process. Keyword-driven framework is a functional automation testing framework, which is also known as table-driven testing or action word-based testing. The basic job of the keyword driven framework is to split the test cases into four different parts. The first is the test step (Test Step), the second is the object in the test step (Test Object), the third is the action performed by the test object (Action), and the fourth is the data required by the test object (Test Data).
In fact, our idea of being keyword-driven is to separate coding from test cases and test steps, so that it is easier for people who cannot code to understand automation, so that manual testers can also write automatic scripts. (This does not mean that automated testers are not needed. A technical person is required for the construction of automated frameworks, automated code updates, structural adjustments, etc.) For teams testing small projects, there can be two manual testers and one Automation testers.
Project function
The function we will implement today is to test the login of 126 mailbox and send an email with an attachment after logging in.
Test address
126 NetEase free postage-your professional electronic post office
Project directory
Next, let’s take a look at how our project directory is designed. What is the function of each directory?
Framework construction
Next, let’s consider step by step how to build the entire project and how to write each py code file?
Main functional modules of the framework
1. Create a new util folder, and create a new ObjectMap.py file under this folder, which mainly implements the encapsulation of the page element search function
1 from selenium.webdriver.support.wait import WebDriverWait 2 3 4 def getElement(driver, by, locator): 5 ''' 6 Find a single element 7 :param driver: 8 :param by: 9 :param locator: 10 :return: element object 11 ''' 12 try: 13 element = WebDriverWait(driver, 30).until(lambda x : x.find_element(by, locator)) 14 except Exception as e: 15 raise e 16 else: 17 return element 18 19 def getElements(driver, by, locator): 20 ''' 21 Get a set of elements 22 :param driver: 23 :param by: 24 :param locator: 25 :return: a set of element objects 26 ''' 27 try: 28 elements = WebDriverWait(driver, 30).until(lambda x : x.find_element(by, locator)) 29 except Exception as e: 30 raise e 31 else: 32 return elements 33 34 35 if __name__=="__main__": 36 from selenium import webdriver 37 import time 38 39 driver = webdriver.Firefox() 40 driver.get('https://mail.126.com') 41 time.sleep(5) 42 driver.switch_to.frame(getElement(driver, 'xpath', "//div[@id='loginDiv']/iframe")) 43 username = getElement(driver, 'xpath', "//input[@name='email']") 44 username.send_keys('linuxxiaochao') 45 driver.switch_to.default_content() 46 driver.quit()
2. Create a new WaitUntil.py file in the util folder, which mainly implements the encapsulation of the function of displaying waiting elements.
1 from selenium.webdriver.common.by import By 2 from selenium.webdriver.support.wait import WebDriverWait 3 from selenium.webdriver.support import expected_conditions as EC 4 5 class WaitUnit(object): 6 def __init__(self, driver): 7 self.byDic = { 8 'id': By.ID, 9 'name': By.NAME, 10 'class_name': By.CLASS_NAME, 11 'xpath': By.XPATH, 12 'link_text': By.LINK_TEXT 13} 14 self.driver = driver 15 self.wait = WebDriverWait(self.driver, 50) 16 17 def presenceOfElementLocated(self, by, locator): 18 ''' 19 Displays waiting for an element to appear in the dom, which may not be visible. There is an element object returned. 20 :param by: 21 :param locator: 22 :return: twenty three ''' 24 try: 25 if by.lower() in self.byDic: 26 self.wait.until(EC.presence_of_element_located((self.byDic[by.lower()], locator))) 27 else: 28 raise TypeError('No positioning method found, please make sure the positioning method is correct') 29 except Exception as e: 30 raise e 31 32 def frameToBeAvailableAndSwtichToIt(self, by, locator): 33 ''' 34 Check whether the frame exists, and switch to the frame if it exists. 35 :param by: 36 :param locator: 37 :return: 38 ''' 39 try: 40 if by.lower() in self.byDic: 41 self.wait.until(EC.frame_to_be_available_and_switch_to_it((self.byDic[by.lower()], locator))) 42 else: 43 raise TypeError('No positioning method found, please make sure the positioning method is correct') 44 except Exception as e: 45 raise e 46 def visibiltyOfElementLocated(self, by, locator): 47 ''' 48 Display waits for the page element to appear in the dom and be visible. If it exists, return the element object. 49 :param by: 50 :param locator: 51 :return: 52 ''' 53 try: 54 if by.lower() in self.byDic: 55 self.wait.until(EC.visibility_of_element_located((self.byDic[by.lower()], locator))) 56 else: 57 raise TypeError('No positioning method found, please make sure the positioning method is correct') 58 except Exception as e: 59 raise e 60 61 if __name__=='__main__': 62 from selenium import webdriver 63 from util.ObjectMap import * 64 driver = webdriver.Firefox() 65 driver.get('https://mail.126.com') 66 67 wait = WaitUnit(driver) 68 wait.frameToBeAvailableAndSwtichToIt('xpath', "//div[@id='loginDiv']/iframe") 69 wait.visibiltyOfElementLocated('xpath', "//input[@name='email']") 70 uname = getElement(driver, 'xpath', "//input[@name='email']") 71 uname.send_keys('python') 72 driver.quit()
3. Create a new ClipboardUtil.py file to implement clipping operations (when we send emails, we need to add attachments, and this function is used to upload attachments)
1 import win32clipboard as w 2 import win32con 3 4 class Clipboard(object): 5 6 @staticmethod 7 def getText(): 8 ''' 9 Get the contents of the clipboard 10 :return: 11 ''' 12 13 try: 14 # Open clipboard 15 w.OpenClipboard() 16 # Read data 17 value = w.GetClipboardData(win32con.CF_TEXT) 18 # Close clipboard 19 w.CloseClipboard() 20 except Exception as e: 21 raise e 22 else: 23 return value twenty four 25 @staticmethod 26 def setText(value): 27 ''' 28 Set clipboard content 29 :return: 30 ''' 31 try: 32 w.OpenClipboard()# Open the clipboard 33 w.EmptyClipboard()# Clear the clipboard 34 w.SetClipboardData(win32con.CF_UNICODETEXT, value) # Set content 35 w.CloseClipboard() # Close 36 except Exception as e: 37 raise e 38 39 if __name__=='__main__': 40 from selenium import webdriver 41 42 value = 'python' 43 driver = webdriver.Firefox() 44 driver.get('http://www.baidu.com') 45 query = driver.find_element_by_id('kw') 46 Clipboard.setText(value) 47 clValue = Clipboard.getText() 48 query.send_keys(clValue.decode('utf-8'))
4. Create a new KeyBoardUtil.py file, which mainly implements simulated keyboard operations (cooperating with the above clipboard function, pasting the path of attachments, pressing Enter, etc.)
1 import win32api 2 import win32con 3 4 class KeyBoardKeys(object): 5 ''' 6 simulated keyboard 7 ''' 8 # Keyboard encoding 9 vk_code ={ 10 'enter':0x0D, 11 'tab' : 0x09, 12 'ctrl':0x11, 13 'v':0x56 14} 15 @staticmethod 16 def keyDown(keyName): 17 ''' 18 Simulate key press 19 :param keyName: 20 :return: twenty one ''' 22 try: 23 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,0,0) 24 except Exception as e: 25 raise e 26 @staticmethod 27 def keyUp(keyName): 28 ''' 29 release button 30 :param keyName: 31 :return: 32 ''' 33 try: 34 win32api.keybd_event(KeyBoardKeys.vk_code[keyName],0,win32con.KEYEVENTF_KEYUP,0) 35 except Exception as e: 36 raise e 37 @staticmethod 38 def oneKey(key): 39 ''' 40 Simulates being a button 41 :param key: 42 :return: 43 ''' 44 try: 45 KeyBoardKeys.keyDown(key) 46 KeyBoardKeys.keyUp(key) 47 except Exception as e: 48 raise e 49 50 @staticmethod 51 def twoKeys(key1, key2): 52 ''' 53 Simulate key combinations 54 :param key1: 55 :param key2: 56 :return: 57 ''' 58 try: 59 KeyBoardKeys.keyDown(key1) 60 KeyBoardKeys.keyDown(key2) 61 KeyBoardKeys.keyUp(key1) 62 KeyBoardKeys.keyUp(key2) 63 except Exception as e: 64 raise e 65 66 if __name__=='__main__': 67 from selenium import webdriver 68 69 driver = webdriver.Firefox() 70 driver.get('http://www.baidu.com') 71 driver.find_element_by_id('kw').send_keys('python') 72 KeyBoardKeys.oneKey('enter')
5. Create a new DirAndTime.py file, which is mainly used to obtain the current time and generate a special path. It is mainly used to generate the path and image name for saving screenshots.
1 from datetime import datetime, date 2 from config.VarConfig import * 3 4 class DirAndTime(object): 5 @staticmethod 6 def getCurrentDate(): 7 ''' 8 Get current date 9 :return: 10 ''' 11 try: 12 currentDate = date.today() 13 except Exception as e: 14 raise e 15 else: 16 return str(currentDate) 17 @staticmethod 18 def getCurrentTime(): 19 ''' 20 Get the current time 21 :return: twenty two ''' 23 try: 24 Time = datetime.now() 25 currentTime = Time.strftime('%H_%M_%S') 26 except Exception as e: 27 raise e 28 else: 29 return currentTime 30 @staticmethod 31 def CreatePicturePath(): 32 ''' 33 Create image storage path path 34 :return: 35 ''' 36 try: 37 38 picturePath = os.path.join(exceptionPath, DirAndTime.getCurrentDate()) 39 if not os.path.exists(picturePath): 40 os.makedirs(picturePath) # Generate multi-level directories 41 except Exception as e: 42 raise e 43 else: 44 return picturePath 45 46 if __name__=='__main__': 47 print(DirAndTime.getCurrentDate()) 48 print(DirAndTime.getCurrentTime()) 49 print(DirAndTime.CreatePicturePath())
6. Create a new ParseExcel.py to parse excel files
1 from openpyxl import load_workbook 2 from config.VarConfig import * 3 from datetime import datetime, date 4 5 class ParseExcel(object): 6 ''' 7 Parse the package of excel file 8 ''' 9 def __init__(self): 10 #Load excel file into memory 11 self.wb = load_workbook(excelPath) 12 13 def getRowValue(self, sheetName, rawNo): 14 ''' 15 Get the data of a certain row 16 :param sheetName: 17 :param rawNo: 18 :return: list 19 ''' 20 sh = self.wb[sheetName] 21 rowValueList = [] 22 for y in range(2, sh.max_column + 1): 23 value = sh.cell(rawNo,y).value 24 rowValueList.append(value) 25 return rowValueList 26 def getColumnValue(self, sheetName, colNo): 27 ''' 28 Get data of a certain column 29 :param sheetName: 30 :param colNo: 31 :return: list 32 ''' 33 sh = self.wb[sheetName] 34 colValueList = [] 35 for x in range(2, sh.max_row + 1): 36 value = sh.cell(x, colNo).value 37 colValueList.append(value) 38 return colValueList 39 40 def getCellOfValue(self, sheetName, rowNo, colNo): 41 ''' 42 Get the data of a certain cell 43 :param sheetName: 44 :param rowNo: 45 :param colNo: 46 :return: string 47 ''' 48 sh = self.wb[sheetName] 49 value = sh.cell(rowNo, colNo).value 50 return value 51 def writeCell(self, sheetName, rowNo, colNo, value): 52 ''' 53 Write data to a cell 54 :param rowNo: row number 55 :param colNo: column number 56 :param value: 57 :return: None 58 ''' 59 sh = self.wb[sheetName] 60 sh.cell(rowNo, colNo).value = value 61 self.wb.save(excelPath) 62 def writeCurrentTime(self, sheetName, rowNo, colNo): 63 ''' 64 Write the current time to a cell 65 :return: 66 ''' 67 sh = self.wb[sheetName] 68 Time = datetime.now() 69 currentTime = Time.strftime('%Y:%m:%d %H:%M:%S') 70 sh.cell(rowNo, colNo).value = currentTime 71 self.wb.save(excelPath) 72 73 def writeTestResult(self, sheetName, rowNo, result, errorInfo = None, errorPic = None): 74 ParseExcel().writeCurrentTime(sheetName, rowNo, testStep_testRunTime) 75 ParseExcel().writeCell(sheetName, rowNo, testStep_testResult, result) 76 if errorInfo and errorInfo: 77 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorInfo, errorInfo) 78 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorPic, errorPic) 79 else: 80 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorInfo, '') 81 ParseExcel().writeCell(sheetName, rowNo, testStep_testErrorPic, '') 82 if __name__=='__main__': 83 p = ParseExcel() 84 print(p.getRowValue('126account',2)) 85 print(p.getColumnValue('126account',3)) 86 print(p.getCellOfValue('126account', 2, 3))
7. Create a new Log.py file to record code execution logs
1 import logging 2 import time 3 from config.VarConfig import * 4 5 class Logger(object): 6 ''' 7 encapsulated log module 8 ''' 9 def __init__(self, logger, CmdLevel=logging.INFO, FileLevel=logging.INFO): 10 """ 11 12 :param logger: 13 :param CmdLevel: 14 :param FileLevel: 15 """ 16 try: 17 self.logger = logging.getLogger(logger) 18 self.logger.setLevel(logging.DEBUG) # Set the default level of log output 19 # Log output format 20 fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s') 21 # Log file name 22 # self.LogFileName = os.path.join(conf.log_path, "{0}.log.txt".format(time.strftime("%Y-%m-%d")))# %H_%M_%S 23 currTime = time.strftime("%Y-%m-%d") 24 self.LogFileName = logPath + currTime + '.txt' 25 # Set console output 26 # sh = logging.StreamHandler() 27 # sh.setFormatter(fmt) 28 # sh.setLevel(CmdLevel)# Log level 29 30 # Set file output 31 fh = logging.FileHandler(self.LogFileName) 32 fh.setFormatter(fmt) 33 fh.setLevel(FileLevel)# Log level 34 35 # self.logger.addHandler(sh) 36 self.logger.addHandler(fh) 37 except Exception as e: 38 raise e 39 40 if __name__ == '__main__': 41 logger = Logger("fox",CmdLevel=logging.DEBUG, FileLevel=logging.DEBUG) 42 logger.logger.debug("debug") 43 logger.logger.log(logging.ERROR,'%(module)s %(info)s',{'module':'log log','info':'error\ '}) #ERROR,log error
Business operation function module
Create a new action folder, which mainly stores various operations on the page, such as click operations, input operations, etc. 1. Create a new PageAction.py file under the folder
1 from util.ObjectMap import * 2 from util.ClipboardUtil import Clipboard 3 from util.KeyBoardUtil import KeyBoardKeys 4 from util.WaitUntil import WaitUnit 5 from util.DirAndTime import * 6 from selenium import webdriver 7 8 driver=None 9 waitUtil = None 10 # Open browser 11 def openBrowser(browser): 12 global driver, waitUtil 13 try: 14 if browser.lower() =='ie': 15 driver = webdriver.Ie(executable_path=iePath) 16 elif browser.lower() == 'chrome': 17 driver = webdriver.Chrome(executable_path=chromePath) 18 else: 19 # driver = webdriver.Firefox(executable_path=fireFox) 20 driver = webdriver.Firefox() 21 except Exception as e: 22 raise e 23 else: 24 waitUtil = WaitUnit(driver) # After driver is created, create wait class instance object 25 26 # Maximize browser window 27 def maximize_browser(): 28 try: 29 driver.maximize_window() 30 except Exception as e: 31 raise e 32 # Load URL 33 def loadUrl(url): 34 try: 35 driver.get(url) 36 except Exception as e: 37 raise e 38 39 # Forced wait 40 def sleep(sleepSeconds): 41 try: 42 import time 43 time.sleep(sleepSeconds) 44 except Exception as e: 45 raise e 46 # Clear the content of the input box 47 def clear(by, locator): 48 try: 49 getElement(driver, by, locator).clear() 50 except Exception as e: 51 raise e 52 # Enter content in the input box 53 def inputValue(by, locator, value): 54 try: 55 element = getElement(driver, by, locator) 56 #element.click() 57 element.send_keys(value) 58 except Exception as e: 59 raise e 60 # Click operation 61 def clickBtn(by, locator): 62 try: 63 getElement(driver, by, locator).click() 64 except Exception as e: 65 raise e 66 # Assert the title of the page 67 def assertTitle(titleStr): 68 try: 69 assert titleStr in driver.title, "%s not found in title!" % titleStr 70 except AssertionError as e: 71 raise AssertionError(e) 72 except Exception as e: 73 raise e 74 75 # Assert whether the target string is included in the page source code 76 def assert_string_in_page_source(assertString): 77 try: 78 assert assertString in driver.page_source, "%s not found in page source!" % assertString 79 except AssertionError as e: 80 raise AssertionError(e) 81 except Exception as e: 82 raise e 83 84 # Get the title of the current page 85 def getTitle(): 86 try: 87 return driver.title 88 except Exception as e: 89 raise e 90 91 # Get page source code 92 def getPageSource(): 93 try: 94 return driver.page_source 95 except Exception as e: 96 raise e 97 # Switch to frame 98 def switchToFrame(by, locator): 99 try: 100 driver.switch_to.frame(getElement(driver, by, locator)) 101 except Exception as e: 102 raise e 103 104 # Jump to the default frame 105 def switchToDefault(): 106 try: 107 driver.switch_to.default_content() 108 except Exception as e: 109 raise e 110 111 # Simulate ctrl + v key 112 def ctrlV(value): 113 try: 114 Clipboard.setText(value) 115 sleep(2) 116 KeyBoardKeys.twoKeys('ctrl', 'v') 117 except Exception as e: 118 raise e 119 120 # Simulate tab key 121 def tabKey(): 122 try: 123 KeyBoardKeys.oneKey('tab') 124 except Exception as e: 125 raise e 126 127 # Simulate enter key 128 def enterKey(): 129 try: 130 KeyBoardKeys.oneKey('enter') 131 except Exception as e: 132 raise e 133 134 # Screenshot 135 def saveScreenShot(): 136 pictureName = DirAndTime.CreatePicturePath() + '\' + DirAndTime.getCurrentTime() + '.png' 137 try: 138 driver.get_screenshot_as_file(pictureName) 139 except Exception as e: 140 raise e 141 else: 142 return pictureName 143 144 def waitPresenceOfElementLocated(by, locator): 145 ''' 146 Display waits for the page element to appear in the DOM, but it may not be visible 147 :param by: 148 :param locator: 149 :return: 150 ''' 151 waitUtil.presenceOfElementLocated(by, locator) 152 153 def waitFrameToBeAvailableAndSwitchToIt(by, locator): 154 ''' 155 Check whether the frame exists. If it exists, switch to the frame. 156 :param by: 157 :param locator: 158 :return: 159 ''' 160 waitUtil.frameToBeAvailableAndSwtichToIt(by, locator) 161 162 def waitVisibiltyOfElementLocated(by, locator): 163 ''' 164 Display waits for the page element to appear in the DOM and be visible 165 :param by: 166 :param locator: 167 :return: 168 ''' 169 waitUtil.visibiltyOfElementLocated(by, locator) 170 171 # Close browser 172 def quitBroswer(): 173 try: 174 driver.quit() 175 except Exception as e: 176 raise e 177 if __name__=='__main__': 178 openBrowser('firefox') 179 loadUrl('http://www.baidu.com') 180 # inputValue('id', 'kw','python') 181 # clear('id', 'kw') 182 # inputValue('id', 'kw', 'python') 183 # clickBtn('id', 'su') 184 #sleep(3) 185 # title = getTitle() 186 #print(title) 187 # assertTitle('python') 188 # assert_string_in_page_source('python') 189 ctrlV('python')
Project data file design
Since we want to implement keyword-driven testing, we will undoubtedly control the execution of the code through keyword data files.
Create a new testData folder and create a new 126mailSend.xlsx file. The file content includes 3 sheet pages, namely test cases, login, and sending emails.
Test case page
Login page
Send email Page
Note: The keywords in the table need to be consistent with the method names in PageAction.py
Project configuration module
Create a new config directory and create a VarConfig.py file to record the global directory and excel file partial information.
1 # Store global variables 2 import os 3 4 # Project root directory 5 projectPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 6 # Screenshot directory 7 exceptionPath = projectPath + r'\exceptionpictures' 8 9 # The driver storage path needs to be modified according to the driver of your own computer. 10 iePath = '' 11 chromePath = '' 12 fireFox = '' 13 14 # Excel file storage path 15 excelPath = projectPath + r'\testData\126mailSend.xlsx' 16 # loh file storage path 17 logPath = projectPath + '\\log\' 18 # Column number corresponding to the test case part column 19 testCase_testCaseName = 2 20 testCase_testStepName = 4 21 testCase_testIsExecute = 5 22 testCase_testRunEndTime = 6 23 testCase_testResult = 7 twenty four 25 # Column number corresponding to the use case step 26 testStep_testNum = 1 27 testStep_testStepDescribe = 2 28 testStep_keyWord = 3 29 testStep_elementBy = 4 30 testStep_elementLocator = 5 31 testStep_operateValue = 6 32 testStep_testRunTime = 7 33 testStep_testResult = 8 34 testStep_testErrorInfo = 9 35 testStep_testErrorPic = 10 36 37 38 if __name__=='__main__': 39 40 print(projectPath) 41 print(exceptionPath)
Test case writing
All the preliminary preparations have been completed, now we start writing test cases
Create a new testCases folder and create a new Test126SendMailWithAttachment.py to write the use case
1 from util.ParseExcel import ParseExcel 2 from config.VarConfig import * 3 from action.PageAction import * 4 import traceback 5 from util.log import Logger 6 import logging 7 8 log = Logger(__name__, CmdLevel=logging.INFO, FileLevel=logging.INFO) 9 p = ParseExcel() 10 sheetName = p.wb.sheetnames# Get all sheet names in excel 11 12 def Test126MailSendWithAtt(): 13 try: 14 testCasePassNum = 0 15 16 requiredCase = 0 17 isExecuteColumnValues = p.getColumnValue(sheetName[0], testCase_testIsExecute) 18 # print(columnValues) 19 for index, value in enumerate(isExecuteColumnValues): 20 # print(index, value) 21 # Get the corresponding step sheet name 22 stepSheetName = p.getCellOfValue(sheetName[0],index + 2, testCase_testStepName) 23 # print(stepSheetName) 24 if value.strip().lower() == 'y': 25 requiredCase + = 1 26 testStepPassNum = 0 27 print('Start executing test case"{}"'.format(stepSheetName)) 28 log.logger.info('Start executing test case"{}"'.format(stepSheetName)) 29 # If the use case is marked for execution y, switch to the corresponding sheet page 30 # Get the total number of steps, keywords, positioning methods, positioning expressions, and operation values in the corresponding sheet 31 # Total number of steps 32 values = p.getColumnValue(stepSheetName, testStep_testNum) #The first column of data 33 stepNum = len(values) 34 print(stepNum) 35 for step in range(2, stepNum + 2): 36 rawValue = p.getRowValue(stepSheetName, step) 37 #Execution step name 38 stepName = rawValue[testStep_testStepDescribe -2] 39 # Keywords 40 keyWord = rawValue[testStep_keyWord - 2] 41 # Positioning method 42 by = rawValue[testStep_elementBy - 2] 43 # Positioning expression 44 locator = rawValue[testStep_elementLocator - 2] 45 # Operation value 46 operateValue = rawValue[testStep_operateValue - 2] 47 48 if keyWord and by and locator and operateValue: 49 func = keyWord + '(' + '"' + by + '"' + ',' + '"' + locator + '"' + \ ',' + '"' + operateValue + '"' + ')' 50 elif keyWord and by and locator and operateValue is None: 51 func = keyWord + '(' + '"' + by + '"' + ',' + '"' + locator + '"' + \ ')' 52 53 elif keyWord and operateValue and type(operateValue) == str and by is None and locator is None: 54 func = keyWord + '(' + '"' + operateValue + '"' + ')' 55 56 elif keyWord and operateValue and type(operateValue) == int and by is None and locator is None: 57 func = keyWord + '(' + str(operateValue) + ')' 58 59 else: 60 func = keyWord + '(' + ')' 61 62 try: 63 # Execute test steps 64 eval(func) 65 exceptException: 66 # Screenshot 67 picPath = saveScreenShot() 68 # Write back test results 69 errorInfo = traceback.format_exc() 70 p.writeTestResult(stepSheetName, step, 'Failed', errorInfo, picPath) 71 print('Step"{}"Execution failed'.format(stepName)) 72 log.logger.info('Step"{}"Execution failed'.format(stepName)) 73 raise 74 else: 75 print('Step"{}" is executed through'.format(stepName)) 76 log.logger.info('Step"{}" is executed through'.format(stepName)) 77 # Mark the test step as pass 78 p.writeTestResult(stepSheetName, step, 'Pass') 79 testStepPassNum + = 1 80 # print('Number of steps through the use case:',testStepPassNum) 81 if testStepPassNum == stepNum: 82 # Mark the execution result of the test case sheet page as pass 83 p.writeCell(sheetName[0], index + 2, testCase_testResult, 'Pass') 84 testCasePassNum + = 1 85 else: 86 p.writeCell(sheetName[0], index + 2, testCase_testResult, 'Failed') 87 print('Total {} use cases, {} need to be executed, this execution passes {}'.format(len(isExecuteColumnValues), requiredCase, testCasePassNum)) 88 log.logger.info('Total {} use cases, {} need to be executed, this execution passes {}'.format(len(isExecuteColumnValues), requiredCase, testCasePassNum)) 89 except Exception as e: 90 print(traceback.format_exc(e)) 91 log.logger.info(traceback.format_exc(e)) 92 93 if __name__=='__main__': 94 Test126MailSendWithAtt()
Loading use cases
Create a new RunTest.py directly in the main directory of the project, and use the test case to run the test case
1 if __name__=='__main__': 2 from testCases.Test126SendMailWithAttachment import Test126MailSendWithAtt 3 Test126MailSendWithAtt()
Project summary
1. Use external test data files, use Excel to manage the collection of test cases and all test steps of each test case, and complete the maintenance of test cases in one file.
2. The test results of each test case are viewed and counted in a file
3. By defining keywords, positioning methods of operation elements, positioning expressions and operation values, the execution of each test case step can be realized, and the needs of automated testing can be realized more flexibly.
4. Realize the separation of positioning expressions and test code, and realize positioning expressions to be maintained directly in the test data file.
5. The framework provides a log function to facilitate debugging and monitoring the execution of automated test programs.
6. Based on the keyword testing framework, even testers who do not understand development technology can implement automated testing, which facilitates the promotion and use of automated testing technology throughout the entire testing team and lowers the technical threshold for automated testing implementation.
7. Based on the keyword method, any keyword can be expanded to meet the automated testing needs of more complex projects.
Run the framework
1. The operating environment requires the installation of python3.x + selenium2.x; third-party modules openpyxl, pypiwin32,
win32api, win32con
2. The chrome/firefox/ie browser and corresponding version driver have been configured locally.
3. Need to modify the corresponding user name and password in the Excel file
4. Directly run the RunTest.py file to execute the entire framework
Finally, I would like to thank everyone who read my article carefully. Reciprocity is always necessary. Although it is not a very valuable thing, if you can use it, you can just take it away:
How to obtain documents
Join my software testing exchange group: 632880530 to get it for free~ (Academic exchanges with fellow leaders, and there will be live broadcasts every night to share technical knowledge points)
This document should be the most comprehensive and complete preparation warehouse for friends who want to engage in [software testing]. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you!
All of the above can be shared. You only need to search the vx official account: Programmer Hugo to get it for free