当前位置: 首页 > news >正文

做时时的网站在线医疗 网站建设

做时时的网站,在线医疗 网站建设,当当网电子商务网站建设,中山网站制作套餐环境准备 序号库/插件/工具安装命令1确保您已经安装了python3.x2配置python3pycharmselenium2开发环境3安装pytest库 pip install pytest 4安装pytest -html 报告插件pip install pytest-html5安装pypiwin32库(用来模拟按键)pip install pypiwin32 6安装openpyxl解析excel文…环境准备 序号库/插件/工具安装命令1确保您已经安装了python3.x2配置python3pycharmselenium2开发环境3安装pytest库 pip install pytest 4安装pytest -html 报告插件pip install pytest-html5安装pypiwin32库(用来模拟按键)pip install pypiwin32 6安装openpyxl解析excel文件库pip install openpyxl7安装yagmail发送报告库pip install yagmail 8确保已配置火狐或谷歌浏览器及对应驱动9确保已经正确配置好发送邮件的邮箱 项目简介 测试地址 https://mail.126.com 测试范围 1.126电子邮箱登录功能测试-验证正确帐号密码登录成功-验证错误用户名密码登录失败有很多情况用例里面做了充分的校验 2.126电子邮箱添加联系人功能测试-验证正确填写必填项数据添加联系人成功-验证缺省必填项数据添加联系人失败-验证必填项字段数据格式错误添加联系人失败 3.126电子邮箱发送邮件功能测试-验证普通邮件发送成功-验证带附件邮件发送成功 项目设计 1.python编程语言设计测试脚本 2.webdriver驱动浏览器并操作页面元素 3.二次封装webdriver Api 操作方法 4.采用PageObject设计模式设计测试业务流程 5.通过UI对象库存储页面操作元素 6.通过数据文件存储数据读取数据参数化测试用例并驱动测试执行 7.通过第三方插件pytest-html生成测试报告 8.通过yagmail第三方库编写发送报告接口测试工作完成后自动发送测试报告 代码分析目录结构 1 PytestAutoTestFrameWork2 |—|config3 |——|__init__.py4 |——|conf.py5 |——|config.ini6 |—|data7 |——|__init__.py8 |——|tcData.xlsx9 |—Page 10 |——|PageObject.py 11 |———|__init__.py 12 |———|ContactPage.py 13 |———|HomePage.py 14 |———|LoginPage.py 15 |———|SendMailPage.py 16 |——|__init__.py 17 |——|BasePage.py 18 |—|report 19 |—|TestCases 20 |——|__init__.py 21 |——|conftest.py 22 |——|test_confactCase.py 23 |——|test_loginCase.py 24 |——|test_sendMailCase.py 25 |—|util 26 |——|__init__.py 27 |——|clipboard.py 28 |——|keyboard.py 29 |——|parseConFile.py 30 |——|parseExcelFile.py 31 |——|sendMailForReport.py 32 |—|conftest.py 33 |—|pytest.ini 34 |—|RunTestCase.py 代码实现 通过126邮箱测试范围分析我们需要通过设计剪切板模拟键盘完成附件上传操作因此我们首先来编写这两个方法 1 2 ------------------------------------3 Time : 2019/4/15 12:044 Auth : linux超5 File : clipboard.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!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(http://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:054 Auth : linux超5 File : keyboard.py6 IDE : PyCharm7 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(http://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:124 Auth : linux超5 File : parseExcelFile.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 from openpyxl import load_workbook11 from config.conf import excelPath12 13 14 class ParseExcel(object):15 16 def __init__(self):17 self.wk load_workbook(excelPath)18 self.excelFile excelPath19 20 def getSheetByName(self, sheetName):21 获取sheet对象22 sheet self.wk[sheetName]23 return sheet24 25 def getRowNum(self, sheet):26 获取有效数据的最大行号27 return sheet.max_row28 29 def getColsNum(self, sheet):30 获取有效数据的最大列号31 return sheet.max_column32 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).value39 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).value50 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).value58 if value is None:59 value 60 return value61 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).value71 if value is None:72 value 73 rowValues.append(value)74 allValues.append(tuple(rowValues))75 return allValues76 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:544 Auth : linux超5 File : parseConFile.py6 IDE : PyCharm7 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, encodingutf-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 usernamelinuxxiaochao3 passwordxiaochao115204 [HomePageElements];126邮箱首页菜单栏元素5 homePageid-_mail_tabitem_0_3text6 mailListid-_mail_tabitem_1_4text7 applicationCenterid-_mail_tabitem_2_5text8 inBoxid-_mail_tabitem_3_6text9 [LoginPageElements];126邮箱登录页面的元素 10 framexpath-//div[idloginDiv]/iframe 11 usernamexpath-//input[nameemail] 12 passwordxpath-//input[namepassword] 13 loginBtnxpath-//a[iddologin] 14 ferrorHeadxpath-//div[classferrorhead] 15 [ContactPageElements];126邮箱添加联系人页面元素 16 new_contactxpath-//span[text()新建联系人] 17 nameid-input_N 18 mailxpath-//div[idiaddress_MAIL_wrap]//input[classnui-ipt-input] 19 starxpath-//span[classnui-chk-text]/preceding-sibling::span/b 20 phonexpath-//div[idiaddress_TEL_wrap]//input[classnui-ipt-input] 21 commentid-input_DETAIL 22 commitxpath-//span[text()确 定] 23 tooltipxpath-//span[text()请正确填写邮件地址。] 24 [SendMailPageElements];126邮箱发送邮件页面元素 25 writeMailxpath-//div[iddvNavContainer]//span[text()写 信] 26 addresseexpath-//input[aria-label收件人地址输入框请输入邮件地址多人时地址请以分号隔开] 27 subjectxpath-//input[contains(id, _subjectInput)] 28 iframexpath-//iframe[classAPP-editor-iframe] 29 textxpath-/html/body 30 sendBtnxpath-//header//span[text()发送] 31 expectxpath-//h1[contains(id,_succInfo)] 32 uploadAttachmentxpath-//div[title点击添加附件] 33 deletexpath-//a[text()删除] 新建excel文件分3个sheet分别为logincontactmail #每个sheet中数据可自行填写驱动测试用例执行不同的数据进行测试 login contact mail 数据UI对象库解析方法都已经有了接下来通过PageObject模式设计编写每个页面的操作及封装126邮箱的功能以便后续设计用例调用 1 2 ------------------------------------3 Time : 2019/4/20 8:454 Auth : linux超5 File : BasePage.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 import time11 from selenium.webdriver.support import expected_conditions as EC12 from selenium.webdriver.support.wait import WebDriverWait as wd13 from selenium.webdriver.common.by import By14 from selenium.common.exceptions import NoSuchWindowException, TimeoutException, \15 NoAlertPresentException, NoSuchFrameException16 from selenium import webdriver17 18 from util.clipboard import ClipBoard19 from util.keyboard import KeyBoard20 from util.parseConFile import ParseConFile21 from util.parseExcelFile import ParseExcel22 23 24 class BasePage(object):25 26 结合显示等待封装一些selenium 内置方法27 28 cf ParseConFile()29 excel ParseExcel()30 31 def __init__(self, driver, outTime30):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_TEXT38 }39 self.driver driver40 self.outTime outTime41 42 def findElement(self, by, locator):43 44 find alone element45 :param by: eg: id, name, xpath, css.....46 :param locator: id, name, xpath for str47 :return: element object48 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 e58 else:59 # print([Info:Had found the element {} by {}!].format(locator, by))60 return element61 62 def findElements(self, by, locator):63 64 find group elements65 :param by: eg: id, name, xpath, css.....66 :param locator: eg: id, name, xpath for str67 :return: elements object68 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 e78 else:79 # print([Info:Had found the elements {} by {}!].format(locator, by))80 return elements81 82 def isElementExsit(self, by, locator):83 84 assert element if exist85 :param by: eg: id, name, xpath, css.....86 :param locator: eg: id, name, xpath for str87 :return: if element return True else return false88 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 False96 except NoSuchWindowException:97 print(Error: element {} not exsit!.format(locator))98 return False99 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, nameNone): 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, num0): 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[idloginDiv]/ifram) 259 wait BasePage(driver) 260 driver.get(https://mail.126.com/) 261 wait.switchToFrame(*frame) 262 username wait.findElement(xpath, //input[nameemail]) 263 username.send_keys(账号) 264 if wait.isElementExsit(xpath, //input[namepassword]): 265 wait.findElement(xpath, //input[namepassword]).send_keys(xiaochao11520) 266 wait.click(xpath, //a[iddologin]) 1 2 ------------------------------------3 Time : 2019/4/20 12:284 Auth : linux超5 File : HomePage.py6 IDE : PyCharm7 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, MenumailList): 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:284 Auth : linux超5 File : LoginPage.py6 IDE : PyCharm7 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(https://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:294 Auth : linux超5 File : ContactPage.py6 IDE : PyCharm7 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(281754041qq.com) 1 2 ------------------------------------3 Time : 2019/4/20 9:164 Auth : linux超5 File : SendMailPage.py6 IDE : PyCharm7 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(281754043qq.com, pytest, pytest实战实例, 1, D:\KeyWordDriverTestFrameWork\geckodriver.log) 所有的准备工作都已经做好了还有一个问题我们的添加联系人和发送邮件应该是否应该在已经登录的前提下测试呢答案是肯定的。所以我们在用例同目录下新建conftest.py文件并调用登录功能 1 2 ------------------------------------3 Time : 2019/4/20 15:104 Auth : linux超5 File : conftest.py6 IDE : PyCharm7 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(scopefunction) 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:104 Auth : linux超5 File : test_loginCase.py6 IDE : PyCharm7 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:154 Auth : linux超5 File : test_contactCase.py6 IDE : PyCharm7 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): 34 contact_page.assertValueInSource(expect) 35 else: 36 contact_page.assertErrorTip(expect) 37 38 if __name__ __main__: 39 pytest.main([-v, test_contactCase.py]) 1 2 ------------------------------------3 Time : 2019/4/20 10:044 Auth : linux超5 File : test_sendMailCase.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 import pytest 11 from Page.PageObject.SendMailPage import SendMailPage 12 13 pytest.mark.sendMailTest 14 class TestSendMail(object): 15 16 sendMailSheet SendMailPage.getSheet(mail) 17 data SendMailPage.excel.getAllValuesOfSheet(sendMailSheet) 18 19 pytest.mark.sendmail 20 pytest.mark.parametrize(Address, Subject, Text, PFA, data) 21 def test_sendMail(self, driver, login, Address, Subject, Text,PFA): 22 测试发送邮件包括带附件的邮件 23 send_mail SendMailPage(driver) 24 send_mail.sendMail(Address, Subject, Text, PFA) 25 send_mail.sleep(5) 26 assert send_mail.isElementExsit(*SendMailPage.expect) 27 28 if __name____main__: 29 pytest.main([-v, test_sendMailCase.py]) 问题 用例已经写完了有两个问题 1.有没有发现我们的报告怎么生成的也没有失败用例截图 2.我们貌似并没有编写驱动浏览器的代码 现在我们来解决这个两个问题根据pytest的conftest.py文件的原理我们可以把驱动浏览器的代码写在一个全局的conftest.py文件里面。报告生成其实是通过命令 pytest --html‘report.html’ --self-contained-html生成的但是这样的报告对用例的描述不是很清晰且没有对失败用例截图也不方便我们分析项目的缺陷我们也可以填写代码放到这个文件里面 1 2 ------------------------------------3 Time : 2019/4/12 14:104 Auth : linux超5 File : conftest.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 import pytest 11 from selenium import webdriver 12 from py._xmlgen import html 13 14 _driver None 15 # 测试失败时添加截图和测试用例描述(用例的注释信息) 16 17 pytest.mark.hookwrapper 18 def pytest_runtest_makereport(item): 19 20 当测试失败的时候自动截图展示到html报告中 21 :param item: 22 23 pytest_html item.config.pluginmanager.getplugin(html) 24 outcome yield 25 report outcome.get_result() 26 extra getattr(report, extra, []) 27 28 if report.when call or report.when setup: 29 xfail hasattr(report, wasxfail) 30 if (report.skipped and xfail) or (report.failed and not xfail): 31 file_name report.nodeid.replace(::, _).png 32 screen_img _capture_screenshot() 33 if file_name: 34 html divimg srcdata:image/png;base64,%s altscreenshot stylewidth:600px;height:300px; \ 35 onclickwindow.open(this.src) alignright//div % screen_img 36 extra.append(pytest_html.extras.html(html)) 37 report.extra extra 38 report.description str(item.function.__doc__) 39 report.nodeid report.nodeid.encode(utf-8).decode(unicode_escape) 40 41 42 pytest.mark.optionalhook 43 def pytest_html_results_table_header(cells): 44 cells.insert(1, html.th(Description)) 45 cells.insert(2, html.th(Test_nodeid)) 46 cells.pop(2) 47 48 49 pytest.mark.optionalhook 50 def pytest_html_results_table_row(report, cells): 51 cells.insert(1, html.td(report.description)) 52 cells.insert(2, html.td(report.nodeid)) 53 cells.pop(2) 54 55 56 def _capture_screenshot(): 57 58 截图保存为base64 59 :return: 60 61 return _driver.get_screenshot_as_base64() 62 # 这里我设置的级别是模块级别也就是每个测试文件运行一次 63 # 可以设置为session全部用例执行一次但是针对126邮箱的话 64 # 登录次数太多会叫你验证如果验证就没法执行用例了我没有对验证处理处理比较复杂 65 66 67 pytest.fixture(scopemodule) 68 def driver(): 69 global _driver 70 print(------------open browser------------) 71 _driver webdriver.Firefox() 72 73 yield _driver 74 print(------------close browser------------) 75 _driver.quit() 最后呢为了减小项目维护成本我们把一些全局的配置项放到我们的功能配置文件中共全局使用包括运行用例的一些命令字符串可以自行修改 1 2 ------------------------------------3 Time : 2019/4/20 16:504 Auth : linux超5 File : conf.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 from datetime import datetime 11 import os 12 # 项目根目录 13 projectDir os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 14 # 报告目录 15 reportDir os.path.join(projectDir, report) 16 # ui对象库config.ini文件所在目录 17 configDir os.path.join(projectDir, config, config.ini) 18 # 测试数据所在目录 19 excelPath os.path.join(projectDir, data, tcData.xlsx) 20 # 当前时间 21 currentTime datetime.now().strftime(%H_%M_%S) 22 23 # 邮件配置信息 24 # 邮件服务器 25 smtpServer smtp.qq.com 26 # 发送者 27 fromUser 账号qq.com 28 # 发送者密码 29 fromPassWord mhxvqpewblldbjhf 30 # 接收者 31 toUser [账号qq.com]# 可以同时发送给多人追加到列表中 32 # 邮件标题 33 subject xx项目自动化测试报告 34 # 邮件正文 35 contents 测试报告正文 36 # 报告名称 37 htmlName r{}\testReport{}.html.format(reportDir, currentTime) 38 39 # 脚本执行命令 40 args rpytest --html htmlName --self-contained-html 41 # modify by linuxchao at 2019/4/25 42 args_login rpytest --html htmlName -m loginTest --self-contained-html 43 args_contact rpytest --html htmlName -m contactTest --self-contained-html 44 args_sendmail rpytest --html htmlName -m sendMailTest --self-contained-html 运行项目 通过命令运行 1.cmd切换到项目的根目录执行pytest --html‘report.html’ --self-contained-html命令此运行方式无法发送测试报告邮件这种方式感觉有点low我们换另外一种方式可以通过os模块自动执行相关命令编写运行用例代码 1 2 ------------------------------------3 Time : 2019/4/15 16:144 Auth : linux超5 File : RunTestCase.py6 IDE : PyCharm7 Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!8 ------------------------------------9 10 import sys 11 sys.path.append(.) 12 from config.conf import * 13 from util.sendMailForReprot import SendMailWithReport 14 15 16 def main(): 17 # 判断项目的根目录是否在sys.path中没有就添加 18 if projectDir not in sys.path: 19 sys.path.append(projectDir) 20 # 执行用例 21 os.system(args) 22 # 发送邮件 23 SendMailWithReport.send_mail( 24 smtpServer, fromUser, fromPassWord, 25 toUser, subject, contents, 26 htmlName) 27 28 29 if __name__ __main__: 30 main() 我们可以直接执行这个文件执行所用的测试用例了 其实我们运行用例往往不只是 使用pytest --html‘report.html’ --self-contained-html 这样一个简单的命令运行通常会添加很多的命令选项比如-v,-q,-s等等那么怎么办呢这时候就用到了pytest.ini配置文件了 只添加了几个简单的命令选项 1 [pytest] 2 addopts-vqs 3 testpaths./TestCases 4 markers 5 loginTest: Run login test cases 6 contactTest: Run add contact test cases 7 sendMailTest: Run send mail test cases 测试输出 1.自动生成html格式报告其中报告里面附带用例执行日志明细及用例失败自动截图(部分报告展示) 2.自动发送测试邮件给指定用户 最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你
http://www.dnsts.com.cn/news/45694.html

相关文章:

  • 如何建设手机端网站企业网站创建步
  • 网站的构成元素青岛网站设计微动力百家号
  • 企业网站做电脑营销国家重点项目建设部网站
  • WORDPRESS微信订阅号采集企业网站怎样做seo优化 应该如何做
  • 中国站长素材网自己做头像的软件
  • 江苏水利建设网站牡丹江网络推广
  • 石家庄做网站排名wordpress付款后查看内容
  • 网站建设怎么挣钱英文企业网站模板
  • 汕头市网站建设平面设计是做什么的工作
  • 网站建设征求意见稿自己主机域名网站开发
  • 河北网站推广nodejs 如何做网站后端
  • 广西中小型营销型网站建设公司短视频营销论文
  • cms网站是什么wordpress教程网页修改
  • 电商网站的二级菜单怎么做南通网站建设兼职
  • ppt设计网站网站建设结算系统
  • 网站概述怎么写全部免费网站软件
  • 门户网站的建设方案网站域名怎么登陆
  • 小学免费资源网站模板做论坛app网站有哪些
  • 如何做网站的注册页面长宁哪里有做网站优化比较好
  • 网站建设软件是什么前端怎么做电商网站
  • sae 网站模板wordpress 改社交图标
  • 淮安网站建设方案整站seo技术
  • 山西省这房和城乡建设厅网站电子类网站模板
  • 山东省建设厅网站特种作业河北省城乡住房建设厅网站
  • 网站备案主体空壳室内设计公司名字起名大全
  • 163网站建设公司网站建设空间
  • 黔江网站制作如何建立营销性企业网站论文
  • 厦门市建设局网站规划标准做网站黑网站赚钱么么
  • 正邦做网站多少钱百度竞价点击神器下载安装
  • 北京网站制作17页高要区住房和城乡建设局网站