How to build a keyword-driven automated testing framework?

foreword

Then in this article we will understand how keyword-driven testing drives automated testing to complete the entire testing process. Keyword-driven framework is a functional automation testing framework, it is also known as form-driven testing or action word-based testing. The basic job of the keyword-driven framework is to divide the test case into four distinct 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 (Action) performed by the test object, and the fourth is the data required by the test object (Test Data).

In fact, our idea of ​​keyword-driven is to separate coding from test cases and test steps, so that it is easier for people who do not know how to code to understand automation, so that manual testers can also write automatic scripts. (This does not mean that there is no need for automated testers. 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.

1. Project functions

The function we will implement today is to test the login of 126 mailboxes and send an email with attachments after login

test address

https://mail.126.com/

2. Project directory

Next, let's take a look at how our project directory is designed, and what is the function of each directory?

3. Framework construction

Next, let's consider step by step how to build the entire project and how to write each py code file?

3.1 Main functional modules of the framework

1. Create a new util folder, and create a new ObjectMap.py file under this folder, mainly to realize 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     查找单一元素
 7     :param driver:
 8     :param by:
 9     :param locator:
10     :return: 元素对象
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     获取一组元素
22     :param driver:
23     :param by:
24     :param locator:
25     :return: 一组元素对象
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 under 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         显示等待某个元素出现在dom中,不一定可见,存在返回元素对象
20         :param by:
21         :param locator:
22         :return:
23         '''
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('未找到定位方式,请确保定位方式正确')
29         except Exception as e:
30             raise e
31 
32     def frameToBeAvailableAndSwtichToIt(self, by, locator):
33         '''
34         检查frame是否存在,存在就切换到frame中
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('未找到定位方式,请确保定位方式正确')
44         except Exception as e:
45             raise e
46     def visibiltyOfElementLocated(self, by, locator):
47         '''
48         显示等待页面元素出现在dom中, 并且可见, 存在则返回该元素对象
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('未找到定位方式,请确保定位方式正确')
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 the clipboard operation (when we send emails, we need to add attachments, and use this function to upload attachments)

1 import win32clipboard as w
 2 import win32con
 3 
 4 class Clipboard(object):
 5 
 6     @staticmethod
 7     def getText():
 8         '''
 9         获取剪切板的内容
10         :return:
11         '''
12 
13         try:
14             # 打开剪切板
15             w.OpenClipboard()
16             # 读取数据
17             value = w.GetClipboardData(win32con.CF_TEXT)
18             # 关闭剪切板
19             w.CloseClipboard()
20         except Exception as e:
21             raise e
22         else:
23             return value
24 
25     @staticmethod
26     def setText(value):
27         '''
28         设置剪切板内容
29         :return:
30         '''
31         try:
32             w.OpenClipboard()# 打开剪切板
33             w.EmptyClipboard()# 清空剪切板
34             w.SetClipboardData(win32con.CF_UNICODETEXT, value) # 设置内容
35             w.CloseClipboard() # 关闭
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 realizes the operation of simulating the keyboard (cooperate with the function of the clipboard above, paste the path of the attachment, press enter, etc.)

1 import win32api
 2 import win32con
 3 
 4 class KeyBoardKeys(object):
 5     '''
 6     模拟键盘
 7     '''
 8     # 键盘编码
 9     vk_code ={
10         'enter':0x0D,
11         'tab' : 0x09,
12         'ctrl':0x11,
13         'v':0x56
14     }
15     @staticmethod
16     def keyDown(keyName):
17         '''
18         模拟按下键
19         :param keyName:
20         :return:
21         '''
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         释放键
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         模拟当个按键
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         模拟组合按键
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, mainly to obtain the current time and generate a special path, which is mainly used to generate the saved path and picture name of the screenshot

1 from datetime import datetime, date
 2 from config.VarConfig import *
 3 
 4 class DirAndTime(object):
 5     @staticmethod
 6     def getCurrentDate():
 7         '''
 8         获取当前日期
 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         获取当前时间
21         :return:
22         '''
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         创建图片存放路径路径
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) # 生成多级目录
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     解析excel文件的封装
 8     '''
 9     def __init__(self):
10         # 加载excel文件到内存
11         self.wb = load_workbook(excelPath)
12 
13     def getRowValue(self, sheetName, rawNo):
14         '''
15         获取某一行的数据
16         :param sheetName:
17         :param rawNo:
18         :return: 列表
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         获取某一列的数据
29         :param sheetName:
30         :param colNo:
31         :return: 列表
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         获取某一个单元格的数据
43         :param sheetName:
44         :param rowNo:
45         :param colNo:
46         :return: 字符串
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         向某个单元格写入数据
54         :param rowNo: 行号
55         :param colNo: 列号
56         :param value:
57         :return: 无
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         向某个单元格写入当前时间
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 the code running log

1 import logging
 2 import time
 3 from config.VarConfig import *
 4 
 5 class Logger(object):
 6     '''
 7     封装的日志模块
 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)  # 设置日志输出的默认级别
19             # 日志输出格式
20             fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')
21             # 日志文件名称
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             # 设置控制台输出
26             # sh = logging.StreamHandler()
27             # sh.setFormatter(fmt)
28             # sh.setLevel(CmdLevel)# 日志级别
29 
30             # 设置文件输出
31             fh = logging.FileHandler(self.LogFileName)
32             fh.setFormatter(fmt)
33             fh.setLevel(FileLevel)# 日志级别
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日志','info':'error'}) #ERROR,log日志 error

3.2 Business operation function modules

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 # 打开浏览器
 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) # driver 创建之后, 创建等待类实例对象
 25 
 26 # 浏览器窗口最大化
 27 def maximize_browser():
 28     try:
 29         driver.maximize_window()
 30     except Exception as e:
 31         raise e
 32 # 加载网址
 33 def loadUrl(url):
 34     try:
 35         driver.get(url)
 36     except Exception as e:
 37         raise e
 38 
 39 # 强制等待
 40 def sleep(sleepSeconds):
 41     try:
 42         import time
 43         time.sleep(sleepSeconds)
 44     except Exception as e:
 45         raise e
 46 # 清除输入框的内容
 47 def clear(by, locator):
 48     try:
 49         getElement(driver, by, locator).clear()
 50     except Exception as e:
 51         raise e
 52 # 输入框中输入内容
 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 # 点击操作
 61 def clickBtn(by, locator):
 62     try:
 63         getElement(driver, by, locator).click()
 64     except Exception as e:
 65         raise e
 66 # 断言页面的title
 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 # 断言目标字符串是否包含在页面源码中
 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 # 获取当前页面的title
 85 def getTitle():
 86     try:
 87         return driver.title
 88     except Exception as e:
 89         raise e
 90 
 91 # 获取页面源码
 92 def getPageSource():
 93     try:
 94         return driver.page_source
 95     except Exception as e:
 96         raise e
 97 # 切换到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 # 跳到默认的frame
105 def switchToDefault():
106     try:
107         driver.switch_to.default_content()
108     except Exception as e:
109         raise e
110 
111 # 模拟ctrl+v键
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 # 模拟tab键
121 def tabKey():
122     try:
123         KeyBoardKeys.oneKey('tab')
124     except Exception as e:
125         raise e
126 
127 # 模拟enter键
128 def enterKey():
129     try:
130         KeyBoardKeys.oneKey('enter')
131     except Exception as e:
132         raise e
133 
134 # 屏幕截图
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     显示等待页面元素出现在DOM中,单并不一定可见
147     :param by:
148     :param locator:
149     :return:
150     '''
151     waitUtil.presenceOfElementLocated(by, locator)
152 
153 def waitFrameToBeAvailableAndSwitchToIt(by, locator):
154     '''
155     检查frame是否存在,存在就切换到frame中
156     :param by:
157     :param locator:
158     :return:
159     '''
160     waitUtil.frameToBeAvailableAndSwtichToIt(by, locator)
161 
162 def waitVisibiltyOfElementLocated(by, locator):
163     '''
164     显示等待页面元素出现在DOM中,并且可见
165     :param by:
166     :param locator:
167     :return:
168     '''
169     waitUtil.visibiltyOfElementLocated(by, locator)
170 
171 # 关闭浏览器
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')

4. Project data file design

Since we want to implement keyword-driven testing, it is undoubtedly to control the execution of code through keyword data files

Create a new testData folder, and create a new 126mailSend.xlsx file. The content of the file includes 3 sheet pages, which are test cases, login, and sending emails

Test case page

login page

send mail page

Note: The keywords in the table need to be consistent with the method names in PageAction.py

5. Project configuration module

Create a new config directory, and create a new VarConfig.py file to record the global directory and some information about the excel file

1 # 存储全局的变量
 2 import os
 3 
 4 # 项目根目录
 5 projectPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 6 # 截图目录
 7 exceptionPath = projectPath +r'\exceptionpictures'
 8 
 9 # 驱动存放路径, 需要自己根据自己电脑的驱动为止修改
10 iePath = ''
11 chromePath = ''
12 fireFox = ''
13 
14 # excel文件存放路径
15 excelPath = projectPath + r'\testData\126mailSend.xlsx'
16 # loh文件存放路径
17 logPath = projectPath + '\\log\\'
18 # 测试用例部分列对应的列号
19 testCase_testCaseName = 2
20 testCase_testStepName = 4
21 testCase_testIsExecute = 5
22 testCase_testRunEndTime = 6
23 testCase_testResult = 7
24 
25 # 用例步骤对应的列号
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)

6. Writing test cases

All the preparations in the early stage have been completed, and then we start to write test cases

Create a new testCases folder, and create a new Test126SendMailWithAttachment.py to write a 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# 获取到excel的所有sheet名称
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             # 获取对应的步骤sheet名称
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('开始执行测试用例"{}"'.format(stepSheetName))
28                 log.logger.info('开始执行测试用例"{}"'.format(stepSheetName))
29                 # 如果用例被标记为执行y,切换到对应的sheet页
30                 # 获取对应的sheet表中的总步骤数,关键字,定位方式,定位表达式,操作值
31                 # 步骤总数
32                 values = p.getColumnValue(stepSheetName, testStep_testNum) # 第一列数据
33                 stepNum = len(values)
34                 print(stepNum)
35                 for step in range(2, stepNum+2):
36                     rawValue = p.getRowValue(stepSheetName, step)
37                     # 执行步骤名称
38                     stepName = rawValue[testStep_testStepDescribe -2]
39                     # 关键字
40                     keyWord = rawValue[testStep_keyWord - 2]
41                     # 定位方式
42                     by = rawValue[testStep_elementBy - 2]
43                     # 定位表达式
44                     locator = rawValue[testStep_elementLocator - 2]
45                     # 操作值
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                         # 执行测试步骤
64                         eval(func)
65                     except Exception:
66                         # 截图
67                         picPath = saveScreenShot()
68                         # 写回测试结果
69                         errorInfo = traceback.format_exc()
70                         p.writeTestResult(stepSheetName, step, 'Failed', errorInfo, picPath)
71                         print('步骤"{}"执行失败'.format(stepName))
72                         log.logger.info('步骤"{}"执行失败'.format(stepName))
73                         raise
74                     else:
75                         print('步骤"{}"执行通过'.format(stepName))
76                         log.logger.info('步骤"{}"执行通过'.format(stepName))
77                         # 标记测试步骤为pass
78                         p.writeTestResult(stepSheetName, step, 'Pass')
79                         testStepPassNum += 1
80                 # print('通过用例步数数:',testStepPassNum)
81                 if testStepPassNum == stepNum:
82                     # 标记测试用例sheet页的执行结果为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('共{}条用例,{}条需要被执行,本次执行通过{}条'.format(len(isExecuteColumnValues), requiredCase, testCasePassNum))
88         log.logger.info('共{}条用例,{}条需要被执行,本次执行通过{}条'.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()

7. 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()

8. 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 realize the maintenance of test cases in one file

2. The test results of each test case are viewed and counted in one file

3. By defining keywords, positioning methods of operating elements, positioning expressions and operating values, the execution of each test case step can be realized, and the requirements of automated testing can be realized more flexibly

4. Realize the separation of positioning expressions and test codes, and realize the maintenance of positioning expressions directly in test data files.

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 in the entire testing team and reduces the technical threshold for automated testing implementation

7. Based on the keyword method, any keyword can be expanded to meet the automated testing requirements of more complex projects

9. Operating framework

1. The operating environment needs to be installed with python3.x+selenium2.x; the third-party modules openpyxl, pypiwin32,
win32api, win32con
2. The chrome/firefox/ie browser and the corresponding version driver have been configured locally
3. Need to modify the corresponding in the Excel file User name and password
4. Run the RunTest.py file directly to execute the entire framework

Finally, I would like to thank everyone who has read my article carefully. Reciprocity is always necessary. Although it is not a very valuable thing, you can take it away if you need it:

insert image description here

Software testing interview applet

The software test question bank maxed out by millions of people! ! ! Who is who knows! ! ! The most comprehensive quiz mini program on the whole network, you can use your mobile phone to do the quizzes, on the subway or on the bus, roll it up!

The following interview question sections are covered:

1. Basic theory of software testing, 2. web, app, interface function testing, 3. network, 4. database, 5. linux

6. web, app, interface automation, 7. performance testing, 8. programming basics, 9. hr interview questions, 10. open test questions, 11. security testing, 12. computer basics

These materials should be the most comprehensive and complete preparation warehouse for [software testing] friends. This warehouse has also accompanied tens of thousands of test engineers through the most difficult journey. I hope it can help you too!  

Guess you like

Origin blog.csdn.net/2301_78276982/article/details/132429081