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:
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!