Pytest UI自动化测试实战实例,2024年最新小白看完都会了

58 阅读17分钟

8 ------------------------------------ 9 """ 10 import win32con 11 import win32clipboard as WC 12 13 14 class ClipBoard(object): 15 '''设置剪切板内容和获取剪切板内容''' 16 17 @staticmethod 18 def getText(): 19 '''获取剪切板的内容''' 20 WC.OpenClipboard() 21 value = WC.GetClipboardData(win32con.CF_TEXT) 22 WC.CloseClipboard() 23 return value 24 25 @staticmethod 26 def setText(value): 27 '''设置剪切板的内容''' 28 WC.OpenClipboard() 29 WC.EmptyClipboard() 30 WC.SetClipboardData(win32con.CF_UNICODETEXT, value) 31 WC.CloseClipboard() 32 33 34 if name == 'main': 35 from selenium import webdriver 36 37 value = 'python' 38 driver = webdriver.Firefox() 39 driver.get('www.baidu.com') 40 query = driver.find_element_by_id('kw') 41 ClipBoard.setText(value) 42 clValue = ClipBoard.getText() 43 query.send_keys(clValue.decode('utf-8'))




1 """ 2 ------------------------------------ 3 @Time : 2019/4/15 12:05 4 @Auth : linux超 5 @File : keyboard.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 11 # 模拟按键 12 import win32api 13 import win32con 14 import time 15 16 17 class KeyBoard(object): 18 """模拟按键""" 19 # 键盘码 20 vk_code = { 21 'enter' : 0x0D, 22 'tab' : 0x09, 23 'ctrl' : 0x11, 24 'v' : 0x56, 25 'a' : 0x41, 26 'x' : 0x58 27 } 28 29 @staticmethod 30 def keyDown(key_name): 31 """按下键""" 32 key_name = key_name.lower() 33 try: 34 win32api.keybd_event(KeyBoard.vk_code[key_name], 0, 0, 0) 35 except Exception as e: 36 print('未按下enter键') 37 print(e) 38 39 @staticmethod 40 def keyUp(key_name): 41 """抬起键""" 42 key_name = key_name.lower() 43 win32api.keybd_event(KeyBoard.vk_code[key_name], 0, win32con.KEYEVENTF_KEYUP, 0) 44 45 @staticmethod 46 def oneKey(key): 47 """模拟单个按键""" 48 key = key.lower() 49 KeyBoard.keyDown(key) 50 time.sleep(2) 51 KeyBoard.keyUp(key) 52 53 @staticmethod 54 def twoKeys(key1, key2): 55 """模拟组合按键""" 56 key1 = key1.lower() 57 key2 = key2.lower() 58 KeyBoard.keyDown(key1) 59 KeyBoard.keyDown(key2) 60 KeyBoard.keyUp(key1) 61 KeyBoard.keyUp(key2) 62 63 64 if name == 'main': 65 from selenium import webdriver 66 driver = webdriver.Firefox() 67 driver.get('www.baidu.com') 68 driver.find_element_by_id('kw').send_keys('python') 69 KeyBoard.twoKeys('ctrl', 'a') 70 KeyBoard.twoKeys('ctrl', 'x')


通过测试项目设计,我们需要把测试数据存放在Excel文件中,把页面操作元素存在UI对象库中也就是一个配置文件,那么我们需要对Excel 和 ini文件解析,因此我们开始编写这两个方法,设计UI对象库和测试数据文件



1 """ 2 ------------------------------------ 3 @Time : 2019/4/22 16:12 4 @Auth : linux超 5 @File : parseExcelFile.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 from openpyxl import load_workbook 11 from config.conf import excelPath 12 13 14 class ParseExcel(object): 15 16 def init(self): 17 self.wk = load_workbook(excelPath) 18 self.excelFile = excelPath 19 20 def getSheetByName(self, sheetName): 21 """获取sheet对象""" 22 sheet = self.wk[sheetName] 23 return sheet 24 25 def getRowNum(self, sheet): 26 """获取有效数据的最大行号""" 27 return sheet.max_row 28 29 def getColsNum(self, sheet): 30 """获取有效数据的最大列号""" 31 return sheet.max_column 32 33 def getRowValues(self, sheet, rowNum): 34 """获取某一行的数据""" 35 maxColsNum = self.getColsNum(sheet) 36 rowValues = [] 37 for colsNum in range(1, maxColsNum + 1): 38 value = sheet.cell(rowNum, colsNum).value 39 if value is None: 40 value = '' 41 rowValues.append(value) 42 return tuple(rowValues) 43 44 def getColumnValues(self, sheet, columnNum): 45 """获取某一列的数据""" 46 maxRowNum = self.getRowNum(sheet) 47 columnValues = [] 48 for rowNum in range(2, maxRowNum + 1): 49 value = sheet.cell(rowNum, columnNum).value 50 if value is None: 51 value = '' 52 columnValues.append(value) 53 return tuple(columnValues) 54 55 def getValueOfCell(self, sheet, rowNum, columnNum): 56 """获取某一个单元格的数据""" 57 value = sheet.cell(rowNum, columnNum).value 58 if value is None: 59 value = '' 60 return value 61 62 def getAllValuesOfSheet(self, sheet): 63 """获取某一个sheet页的所有测试数据,返回一个元祖组成的列表""" 64 maxRowNum = self.getRowNum(sheet) 65 columnNum = self.getColsNum(sheet) 66 allValues = [] 67 for row in range(2, maxRowNum + 1): 68 rowValues = [] 69 for column in range(1, columnNum + 1): 70 value = sheet.cell(row, column).value 71 if value is None: 72 value = '' 73 rowValues.append(value) 74 allValues.append(tuple(rowValues)) 75 return allValues 76 77 78 if name == 'main': 79 # excel = ParseExcel() 80 # sheet = excel.getSheetByName('login') 81 # print('行号:', excel.getRowNum(sheet)) 82 # print('列号:', excel.getColsNum(sheet)) 83 # 84 # rowvalues = excel.getRowValues(sheet, 1) 85 # columnvalues = excel.getColumnValues(sheet, 2) 86 # valueofcell = excel.getValueOfCell(sheet, 1, 2) 87 # allvalues = excel.getAllValuesOfSheet(sheet) 88 # 89 # print('第{}行数据{}'.format(1, rowvalues)) 90 # print('第{}列数据{}'.format(2, columnvalues)) 91 # print('{}{}单元格的内容{}'.format(1, 2, valueofcell)) 92 # print('login{}'.format(allvalues)) 93 94 excel = ParseExcel() 95 sheet = excel.getSheetByName('mail') 96 print('行号:', excel.getRowNum(sheet)) 97 print('列号:', excel.getColsNum(sheet)) 98 99 allvalues = excel.getAllValuesOfSheet(sheet) 100 101 print('sendmail{}'.format(allvalues))




1 """ 2 ------------------------------------ 3 @Time : 2019/4/18 10:54 4 @Auth : linux超 5 @File : parseConFile.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 import configparser 11 from config.conf import configDir 12 13 14 class ParseConFile(object): 15 16 def init(self): 17 self.file = configDir 18 self.conf = configparser.ConfigParser() 19 self.conf.read(self.file, encoding='utf-8') 20 21 def getAllSections(self): 22 """获取所有的section,返回一个列表""" 23 return self.conf.sections() 24 25 def getAllOptions(self, section): 26 """获取指定section下所有的option, 返回列表""" 27 return self.conf.options(section) 28 29 def getLocatorsOrAccount(self, section, option): 30 """获取指定section, 指定option对应的数据, 返回元祖和字符串""" 31 try: 32 locator = self.conf.get(section, option) 33 if ('->' in locator): 34 locator = tuple(locator.split('->')) 35 return locator 36 except configparser.NoOptionError as e: 37 print('error:', e) 38 return 'error: No option "{}" in section: "{}"'.format(option, section) 39 40 def getOptionValue(self, section): 41 """获取指定section下所有的option和对应的数据,返回字典""" 42 value = dict(self.conf.items(section)) 43 return value 44 45 46 if name == 'main': 47 cf = ParseConFile() 48 print(cf.getAllSections()) 49 print(cf.getAllOptions('126LoginAccount')) 50 print(cf.getLocatorsOrAccount('126LoginAccount', 'username')) 51 print(cf.getOptionValue('126LoginAccount'))




1 [126LoginAccount];126邮箱正确的登录账号和密码;运行用例时请更换正确的用户名和密码 2 username=linuxxiaochao 3 password=xiaochao11520 4 [HomePageElements];126邮箱首页菜单栏元素 5 homePage=id->_mail_tabitem_0_3text 6 mailList=id->_mail_tabitem_1_4text 7 applicationCenter=id->_mail_tabitem_2_5text 8 inBox=id->_mail_tabitem_3_6text 9 [LoginPageElements];126邮箱登录页面的元素 10 frame=xpath->//div[@id="loginDiv"]/iframe 11 username=xpath->//input[@name="email"] 12 password=xpath->//input[@name="password"] 13 loginBtn=xpath->//a[@id="dologin"] 14 ferrorHead=xpath->//div[@class="ferrorhead"] 15 [ContactPageElements];126邮箱添加联系人页面元素 16 new_contact=xpath->//span[text()="新建联系人"] 17 name=id->input_N 18 mail=xpath->//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"] 19 star=xpath->//span[@class="nui-chk-text"]/preceding-sibling::span/b 20 phone=xpath->//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input'] 21 comment=id->input_DETAIL 22 commit=xpath->//span[text()='确 定'] 23 tooltip=xpath->//span[text()='请正确填写邮件地址。'] 24 [SendMailPageElements];126邮箱发送邮件页面元素 25 writeMail=xpath->//div[@id='dvNavContainer']//span[text()='写 信'] 26 addressee=xpath->//input[@aria-label='收件人地址输入框,请输入邮件地址,多人时地址请以分号隔开'] 27 subject=xpath->//input[contains(@id, '_subjectInput')] 28 iframe=xpath->//iframe[@class="APP-editor-iframe"] 29 text=xpath->/html/body 30 sendBtn=xpath->//header//span[text()='发送'] 31 expect=xpath->//h1[contains(@id,'_succInfo')] 32 uploadAttachment=xpath->//div[@title="点击添加附件"] 33 delete=xpath->//a[text()='删除']



新建excel文件,分3个sheet,分别为:login,contact,mail #每个sheet中数据可自行填写,驱动测试用例执行不同的数据进行测试


login



![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/4e249dda95fc4be883e7948fea8675d3~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1771745252&x-signature=Ybz3ECFTgmTEXv%2B5xEQQbFrLOxE%3D)


contact



![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/e60e273bc1e64571a55b84361da19782~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1771745252&x-signature=OFeXZGRc7%2BEqEIhHghHsG8TNbOg%3D)


mail



![](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/2304e426067743edaf843806d4a8f6e6~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3MzIxMjA3NDIwNDUy:q75.awebp?rk3s=f64ab15b&x-expires=1771745252&x-signature=UZ8Ew%2B4ZUWc9yUr86k4daGoaeSM%3D)


数据,UI对象库,解析方法都已经有了,接下来通过PageObject模式设计编写每个页面的操作及封装126邮箱的功能,以便后续设计用例调用



1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 8:45 4 @Auth : linux超 5 @File : BasePage.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 import time 11 from selenium.webdriver.support import expected_conditions as EC 12 from selenium.webdriver.support.wait import WebDriverWait as wd 13 from selenium.webdriver.common.by import By 14 from selenium.common.exceptions import NoSuchWindowException, TimeoutException,
15 NoAlertPresentException, NoSuchFrameException 16 from selenium import webdriver 17 18 from util.clipboard import ClipBoard 19 from util.keyboard import KeyBoard 20 from util.parseConFile import ParseConFile 21 from util.parseExcelFile import ParseExcel 22 23 24 class BasePage(object): 25 """ 26 结合显示等待封装一些selenium 内置方法 27 """ 28 cf = ParseConFile() 29 excel = ParseExcel() 30 31 def init(self, driver, outTime=30): 32 self.byDic = { 33 'id': By.ID, 34 'name': By.NAME, 35 'class_name': By.CLASS_NAME, 36 'xpath': By.XPATH, 37 'link_text': By.LINK_TEXT 38 } 39 self.driver = driver 40 self.outTime = outTime 41 42 def findElement(self, by, locator): 43 """ 44 find alone element 45 :param by: eg: id, name, xpath, css..... 46 :param locator: id, name, xpath for str 47 :return: element object 48 """ 49 try: 50 print('[Info:Starting find the element "{}" by "{}"!]'.format(locator, by)) 51 element = wd(self.driver, self.outTime).until(lambda x : x.find_element(by, locator)) 52 except TimeoutException as t: 53 print('error: found "{}" timeout!'.format(locator), t) 54 except NoSuchWindowException as e: 55 print('error: no such "{}"'.format(locator), e) 56 except Exception as e: 57 raise e 58 else: 59 # print('[Info:Had found the element "{}" by "{}"!]'.format(locator, by)) 60 return element 61 62 def findElements(self, by, locator): 63 """ 64 find group elements 65 :param by: eg: id, name, xpath, css..... 66 :param locator: eg: id, name, xpath for str 67 :return: elements object 68 """ 69 try: 70 print('[Info:start find the elements "{}" by "{}"!]'.format(locator, by)) 71 elements = wd(self.driver, self.outTime).until(lambda x : x.find_element(by, locator)) 72 except TimeoutException as t: 73 print(t) 74 except NoSuchWindowException as e: 75 print(e) 76 except Exception as e: 77 raise e 78 else: 79 # print('[Info:Had found the elements "{}" by "{}"!]'.format(locator, by)) 80 return elements 81 82 def isElementExsit(self, by, locator): 83 """ 84 assert element if exist 85 :param by: eg: id, name, xpath, css..... 86 :param locator: eg: id, name, xpath for str 87 :return: if element return True else return false 88 """ 89 if by.lower() in self.byDic: 90 try: 91 wd(self.driver, self.outTime).
92 until(EC.visibility_of_element_located((self.byDic[by], locator))) 93 except TimeoutException: 94 print('Error: element "{}" time out!'.format(locator)) 95 return False 96 except NoSuchWindowException: 97 print('Error: element "{}" not exsit!'.format(locator)) 98 return False 99 return True 100 else: 101 print('the "{}" error!'.format(by)) 102 103 def isClick(self, by, locator): 104 """判断是否可点击,返回元素对象""" 105 if by.lower() in self.byDic: 106 try: 107 element = wd(self.driver, self.outTime).
108 until(EC.element_to_be_clickable((self.byDic[by], locator))) 109 except Exception: 110 return False 111 return element 112 else: 113 print('the "{}" error!'.format(by)) 114 115 def isAlertAndSwitchToIt(self): 116 """ 117 assert alert if exsit 118 :return: alert obj 119 """ 120 try: 121 re = wd(self.driver, self.outTime).until(EC.alert_is_present()) 122 except NoAlertPresentException: 123 return False 124 except Exception: 125 return False 126 return re 127 128 def switchToFrame(self, by, locator): 129 """判断frame是否存在,存在就跳到frame""" 130 print('info:switching to iframe "{}"'.format(locator)) 131 if by.lower() in self.byDic: 132 try: 133 wd(self.driver, self.outTime).
134 until(EC.frame_to_be_available_and_switch_to_it((self.byDic[by], locator))) 135 except TimeoutException as t: 136 print('error: found "{}" timeout!'.format(locator), t) 137 except NoSuchFrameException as e: 138 print('error: no such "{}"'.format(locator), e) 139 except Exception as e: 140 raise e 141 else: 142 print('the "{}" error!'.format(by)) 143 144 def switchToDefaultFrame(self): 145 """返回默认的frame""" 146 print('info:switch back to default iframe') 147 try: 148 self.driver.switch_to.default_content() 149 except Exception as e: 150 print(e) 151 152 def getAlertText(self): 153 """获取alert的提示信息""" 154 if self.isAlertAndSwitchToIt(): 155 alert = self.isAlertAndSwitchToIt() 156 return alert.text 157 else: 158 return None 159 160 def getElementText(self, by, locator, name=None): 161 """获取某一个元素的text信息""" 162 try: 163 element = self.findElement(by, locator) 164 if name: 165 return element.get_attribute(name) 166 else: 167 return element.text 168 except: 169 print('get "{}" text failed return None'.format(locator)) 170 return None 171 172 def loadUrl(self, url): 173 """加载url""" 174 print('info: string upload url "{}"'.format(url)) 175 self.driver.get(url) 176 177 def getSource(self): 178 """获取页面源码""" 179 return self.driver.page_source 180 181 def sendKeys(self, by, locator, value=''): 182 """写数据""" 183 print('info:input "{}"'.format(value)) 184 try: 185 element = self.findElement(by, locator) 186 element.send_keys(value) 187 except AttributeError as e: 188 print(e) 189 190 def clear(self, by, locator): 191 """清理数据""" 192 print('info:clearing value') 193 try: 194 element = self.findElement(by, locator) 195 element.clear() 196 except AttributeError as e: 197 print(e) 198 199 def click(self, by, locator): 200 """点击某个元素""" 201 print('info:click "{}"'.format(locator)) 202 element = self.isClick(by, locator) 203 if element: 204 element.click() 205 else: 206 print('the "{}" unclickable!') 207 208 def sleep(self, num=0): 209 """强制等待""" 210 print('info:sleep "{}" minutes'.format(num)) 211 time.sleep(num) 212 213 def ctrlV(self, value): 214 """ctrl + V 粘贴""" 215 print('info:pasting "{}"'.format(value)) 216 ClipBoard.setText(value) 217 self.sleep(3) 218 KeyBoard.twoKeys('ctrl', 'v') 219 220 def enterKey(self): 221 """enter 回车键""" 222 print('info:keydown enter') 223 KeyBoard.oneKey('enter') 224 225 def waitElementtobelocated(self, by, locator): 226 """显示等待某个元素出现,且可见""" 227 print('info:waiting "{}" to be located'.format(locator)) 228 try: 229 wd(self.driver, self.outTime).until(EC.visibility_of_element_located((self.byDic[by], locator))) 230 except TimeoutException as t: 231 print('error: found "{}" timeout!'.format(locator), t) 232 except NoSuchWindowException as e: 233 print('error: no such "{}"'.format(locator), e) 234 except Exception as e: 235 raise e 236 237 def assertValueInSource(self, value): 238 """断言某个关键字是否存在页面源码中""" 239 print('info:assert "{}" in page source'.format(value)) 240 source = self.getSource() 241 assert value in source, '关键字"{}"不存在源码中!'.format(value) 242 243 def assertStringContainsValue(self, String, value): 244 """断言某段字符串包含另一个字符串""" 245 print('info:assert "{}" contains "{}"'.format(String, value)) 246 assert value in String, '"{}"不包含"{}"!'.format(String, value) 247 248 249 @staticmethod 250 def getSheet(sheetName): 251 """获取某个sheet页的对象""" 252 sheet = BasePage.excel.getSheetByName(sheetName) 253 return sheet 254 255 256 if name == "main": 257 driver = webdriver.Firefox() 258 frame = ('xpath', '//div[@id="loginDiv"]/ifram') 259 wait = BasePage(driver) 260 driver.get('mail.126.com/') 261 wait.switchToFrame(*frame) 262 username = wait.findElement('xpath', '//input[@name="email"]') 263 username.send_keys('账号') 264 if wait.isElementExsit('xpath', '//input[@name="password"]'): 265 wait.findElement('xpath', '//input[@name="password"]').send_keys('xiaochao11520') 266 wait.click('xpath', '//a[@id="dologin"]')




1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 12:28 4 @Auth : linux超 5 @File : HomePage.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 from Page.BasePage import BasePage 11 12 13 class HomePage(BasePage): 14 # 配置文件读取元素 15 homePage = BasePage.cf.getLocatorsOrAccount('HomePageElements', 'homePage') 16 mailList = BasePage.cf.getLocatorsOrAccount('HomePageElements', 'mailList') 17 applicationCenter = BasePage.cf.getLocatorsOrAccount('HomePageElements', 'applicationCenter') 18 inBox = BasePage.cf.getLocatorsOrAccount('HomePageElements', 'inBox') 19 '''首页菜单选项''' 20 def selectMenu(self, Menu='mailList'): 21 """邮箱首页选择菜单""" 22 if Menu == 'mailList': 23 self.click(*HomePage.mailList) 24 elif Menu == 'homePage': 25 self.click(*HomePage.homePage) 26 elif Menu == 'applicationCenter': 27 self.click(*HomePage.applicationCenter) 28 elif Menu == 'inBox': 29 self.click(*HomePage.inBox) 30 else: 31 raise ValueError(''' 32 菜单选择错误! 33 homePage->首页 34 mailList->通讯录 35 applicationCenter->应用中心 36 inBox->收件箱''') 37 38 if name=='main': 39 from selenium import webdriver 40 from Page.PageObject.LoginPage import LoginPage 41 driver = webdriver.Firefox() 42 login = LoginPage(driver) 43 login.login('账号', 'xiaochao11520') 44 45 home = HomePage(driver) 46 home.selectMenu()




1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 12:28 4 @Auth : linux超 5 @File : LoginPage.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 from Page.BasePage import BasePage 11 12 13 class LoginPage(BasePage): 14 15 # 配置文件读取元素 16 frame = BasePage.cf.getLocatorsOrAccount('LoginPageElements', 'frame') 17 username = BasePage.cf.getLocatorsOrAccount('LoginPageElements', 'username') 18 password = BasePage.cf.getLocatorsOrAccount('LoginPageElements', 'password') 19 loginBtn = BasePage.cf.getLocatorsOrAccount('LoginPageElements', 'loginBtn') 20 ferrorHead = BasePage.cf.getLocatorsOrAccount('LoginPageElements', 'ferrorHead') # 登录失败提示 21 22 def login(self, userName, passWord): 23 '''登录''' 24 print('-------staring login-------') 25 self.loadUrl('mail.126.com') 26 self.switchToFrame(*LoginPage.frame) 27 self.clear(*LoginPage.username) 28 self.sendKeys(*LoginPage.username, userName) 29 self.clear(*LoginPage.password) 30 self.sendKeys(*LoginPage.password, passWord) 31 self.click(*LoginPage.loginBtn) 32 self.switchToDefaultFrame() 33 print('---------end login---------') 34 35 # add at 2019/04/19 36 def assertTextEqString(self, expected, name = None): 37 '''断言提示信息是否与期望的值相等''' 38 self.switchToFrame(*LoginPage.frame) 39 text = self.getElementText(*LoginPage.ferrorHead, name) 40 self.switchToDefaultFrame() 41 print('info: assert "{}" == "{}"'.format(text, expected)) 42 assert text == expected, '{} != {}'.format(text, expected) 43 44 if name=="main": 45 from selenium import webdriver 46 driver = webdriver.Firefox() 47 login = LoginPage(driver, 30) 48 login.login('lin', '') 49 login.assertTextEqString('请输入密码')




1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 12:29 4 @Auth : linux超 5 @File : ContactPage.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 from Page.BasePage import BasePage 11 12 13 class ContactPage(BasePage): 14 # 配置文件读取元素 15 new_contact = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'new_contact') 16 name = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'name') 17 mail = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'mail') 18 star = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'star') 19 phone = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'phone') 20 comment = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'comment') 21 commit = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'commit') 22 errortip = BasePage.cf.getLocatorsOrAccount('ContactPageElements', 'tooltip') # 错误提示 23 24 def newContact(self, Name, Mail, Star, Phone, Comment): 25 """添加联系人""" 26 print('--------string add contact--------') 27 self.click(*ContactPage.new_contact) 28 self.sendKeys(*ContactPage.name, Name) 29 self.sendKeys(*ContactPage.mail, Mail) 30 if Star == '1': 31 self.click(*ContactPage.star) 32 self.sendKeys(*ContactPage.phone, Phone) 33 self.sendKeys(*ContactPage.comment, Comment) 34 self.click(*ContactPage.commit) 35 print('--------end add contact--------') 36 37 def assertErrorTip(self, excepted): 38 """断言联系人添加失败时是否有提示信息""" 39 text = self.getElementText(*ContactPage.errortip) 40 print('info: assert "{}"=="{}"'.format(text, excepted)) 41 assert text == excepted 42 43 if name == 'main': 44 from selenium import webdriver 45 from Page.PageObject.LoginPage import LoginPage 46 from Page.PageObject.HomePage import HomePage 47 driver = webdriver.Firefox() 48 home = HomePage(driver) 49 login = LoginPage(driver) 50 contact = ContactPage(driver) 51 52 login.login('账号', 'xiaochao11520') 53 home.selectMenu() 54 contact.newContact('281754041@qq.com')




1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 9:16 4 @Auth : linux超 5 @File : SendMailPage.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 from Page.BasePage import BasePage 11 12 13 class SendMailPage(BasePage): 14 # 配置文件读取元素 15 writeMail = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'writeMail') 16 addressee = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'addressee') 17 subject = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'subject') 18 iframe = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'iframe') 19 text = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'text') 20 sendBtn = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'sendBtn') 21 expect = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'expect') 22 uploadAttachment = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'uploadAttachment') 23 delete = BasePage.cf.getLocatorsOrAccount('SendMailPageElements', 'delete') 24 25 def sendMail(self, Address, Subject, Text, PFA=''): 26 """发送邮件功能""" 27 print('------------string send mail---------------------') 28 self.click(*SendMailPage.writeMail) 29 self.sendKeys(*SendMailPage.addressee, Address) 30 self.sendKeys(*SendMailPage.subject, Subject) 31 self.switchToFrame(*SendMailPage.iframe) 32 self.sendKeys(*SendMailPage.text, Text) 33 self.switchToDefaultFrame() 34 if PFA: 35 self.click(*SendMailPage.uploadAttachment) 36 self.ctrlV(PFA) 37 self.enterKey() 38 self.waitElementtobelocated(*SendMailPage.delete) 39 self.click(*SendMailPage.sendBtn) 40 print('------------end send mail---------------------') 41 42 if name=='main': 43 from Page.PageObject.LoginPage import LoginPage 44 from selenium import webdriver 45 driver = webdriver.Firefox() 46 47 login = LoginPage(driver) 48 login.login('账号', 'xiaochao11520') 49 sendMail = SendMailPage(driver) 50 sendMail.sendMail('281754043@qq.com', 'pytest', 'pytest实战实例', 1, 'D:\KeyWordDriverTestFrameWork\geckodriver.log')


所有的准备工作都已经做好了,还有一个问题,我们的添加联系人和发送邮件应该是否应该在已经登录的前提下测试呢?答案是肯定的。所以我们在用例同目录下新建conftest.py文件并调用登录功能



1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 15:10 4 @Auth : linux超 5 @File : conftest.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 import pytest 11 from Page.PageObject.LoginPage import LoginPage 12 13 14 # 从配置文件中获取正确的用户名和密码 15 userName = LoginPage.cf.getLocatorsOrAccount('126LoginAccount', 'username') 16 passWord = LoginPage.cf.getLocatorsOrAccount('126LoginAccount', 'password') 17 @pytest.fixture(scope='function') 18 def login(driver): 19 '''除登录用例,每一个用例的前置条件''' 20 print('------------staring login------------') 21 loginFunc = LoginPage(driver, 30) 22 loginFunc.login(userName, passWord) 23 yield 24 print('------------end login------------') 25 driver.delete_all_cookies()


ok,开始编写测试用例啦



1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 14:10 4 @Auth : linux超 5 @File : test_loginCase.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 import pytest 11 from Page.PageObject.LoginPage import LoginPage 12 13 14 @pytest.mark.loginTest 15 class TestLogin(object): 16 17 # 测试数据 18 loginSheet = LoginPage.getSheet('login') 19 data = LoginPage.excel.getAllValuesOfSheet(loginSheet) 20 21 # 正确的帐号和密码 22 userName = LoginPage.cf.getLocatorsOrAccount('126LoginAccount', 'username') 23 passWord = LoginPage.cf.getLocatorsOrAccount('126LoginAccount', 'password') 24 25 @pytest.fixture() 26 def teardown_func(self, driver): 27 """ 28 执行每个用例之后要清除一下cookie, 29 否则你第一个账号登录之后,重新加载网址还是登录状态,无法测试后面的账号 30 """ 31 yield 32 driver.delete_all_cookies() 33 34 @pytest.mark.parametrize('username, password, expect', data) 35 def test_login(self, teardown_func, driver, username, password, expect): 36 """测试登录""" 37 login = LoginPage(driver, 30) 38 login.login(username, password) 39 login.sleep(5) 40 # 增加登录失败时, 对提示信息的验证 41 if username == TestLogin.userName and password == TestLogin.passWord: 42 login.assertValueInSource(expect) 43 elif username == '': 44 login.assertTextEqString(expect) 45 elif username != '' and password == '': 46 login.assertTextEqString(expect) 47 elif username == '' and password == '': 48 login.assertTextEqString(expect) 49 else: 50 login.assertTextEqString(expect) 51 52 53 if name == "main": 54 pytest.main(['-v', 'test_loginCase.py'])




1 """ 2 ------------------------------------ 3 @Time : 2019/4/20 16:15 4 @Auth : linux超 5 @File : test_contactCase.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 ------------------------------------ 9 """ 10 import re 11 import pytest 12 from Page.PageObject.HomePage import HomePage 13 from Page.PageObject.ContactPage import ContactPage 14 15 16 @pytest.mark.conatctTest 17 class TestAddContact(object): 18 19 # 测试数据 20 contactSheet = ContactPage.getSheet('contact') 21 data = ContactPage.excel.getAllValuesOfSheet(contactSheet) 22 23 @pytest.mark.newcontact 24 @pytest.mark.parametrize('Name, Mail, Star, Phone, Comment, expect', data) 25 def test_NewContact(self, driver, login, Name, Mail, Star, Phone, Comment, expect): 26 """测试添加联系人""" 27 home_page = HomePage(driver) 28 contact_page = ContactPage(driver) 29 home_page.selectMenu() 30 contact_page.newContact(Name, Mail, Star, Phone, Comment) 31 home_page.sleep(5) 32 # 校验错误的邮箱是否提示信息正确 33 if re.match(r'^.{1,}@[0-9a-zA-Z]{1,13}..*$', Mail):

img img img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

开源项目:docs.qq.com/doc/DSlVlZExWQ0FRSE9H