├── .gitattributes ├── .gitignore ├── Page ├── BasePage.py ├── PageObject │ ├── ContactPage.py │ ├── HomePage.py │ ├── LoginPage.py │ ├── SendMailPage.py │ └── __init__.py └── __init__.py ├── README.md ├── RunTestCase.py ├── TestCases ├── __init__.py ├── conftest.py ├── test_contactCase.py ├── test_loginCase.py └── test_sendMailCase.py ├── config ├── __init__.py ├── conf.py └── config.ini ├── conftest.py ├── data ├── __init__.py ├── attachment ├── contact_data.py ├── login_data.py ├── send_mail_data.py └── tcData.xlsx ├── pytest.ini ├── report ├── testReport18_19_10.html └── testReport22_52_18.html ├── requirements.txt └── util ├── __init__.py ├── clipboard.py ├── keyboard.py ├── parseConFile.py ├── parseExcelFile.py └── sendMailForReprot.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py linguist-language=python 2 | *.html linguist-language=python 3 | *.css linguist-language=python 4 | *.xlsx linguist-language=python 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ##ignore these files## 2 | assets 3 | .pytest_cache 4 | .idea 5 | *.log 6 | venv -------------------------------------------------------------------------------- /Page/BasePage.py: -------------------------------------------------------------------------------- 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.wait import WebDriverWait as WD 12 | from selenium.webdriver.support import expected_conditions as ec 13 | from selenium.webdriver.common.by import By 14 | from selenium.common.exceptions import ( 15 | TimeoutException, 16 | NoAlertPresentException, 17 | ) 18 | 19 | from util.clipboard import ClipBoard 20 | from util.keyboard import KeyBoard 21 | from util.parseConFile import ParseConFile 22 | from util.parseExcelFile import ParseExcel 23 | 24 | 25 | class BasePage(object): 26 | """结合显示等待封装一些selenium内置方法""" 27 | cf = ParseConFile() 28 | excel = ParseExcel() 29 | 30 | def __init__(self, driver, timeout=30): 31 | self.byDic = { 32 | 'id': By.ID, 33 | 'name': By.NAME, 34 | 'class_name': By.CLASS_NAME, 35 | 'xpath': By.XPATH, 36 | 'link_text': By.LINK_TEXT 37 | } 38 | self.driver = driver 39 | self.outTime = timeout 40 | 41 | def find_element(self, by, locator): 42 | """ 43 | find alone element 44 | :param by: eg: id, name, xpath, css..... 45 | :param locator: id, name, xpath for str 46 | :return: element object 47 | """ 48 | try: 49 | print('[Info:Starting find the element "{}" by "{}"!]'.format(locator, by)) 50 | element = WD(self.driver, self.outTime).until(lambda x: x.find_element(by, locator)) 51 | except TimeoutException as t: 52 | print('error: found "{}" timeout!'.format(locator), t) 53 | else: 54 | return element 55 | 56 | def find_elements(self, by, locator): 57 | """ 58 | find group elements 59 | :param by: eg: id, name, xpath, css..... 60 | :param locator: eg: id, name, xpath for str 61 | :return: elements object 62 | """ 63 | try: 64 | print('[Info:start find the elements "{}" by "{}"!]'.format(locator, by)) 65 | elements = WD(self.driver, self.outTime).until(lambda x: x.find_elements(by, locator)) 66 | except TimeoutException as t: 67 | print('error: found "{}" timeout!'.format(locator), t) 68 | else: 69 | return elements 70 | 71 | def is_element_exist(self, by, locator): 72 | """ 73 | assert element if exist 74 | :param by: eg: id, name, xpath, css..... 75 | :param locator: eg: id, name, xpath for str 76 | :return: if element return True else return false 77 | """ 78 | if by.lower() in self.byDic: 79 | try: 80 | WD(self.driver, self.outTime). \ 81 | until(ec.visibility_of_element_located((self.byDic[by], locator))) 82 | except TimeoutException: 83 | print('Error: element "{}" not exist'.format(locator)) 84 | return False 85 | return True 86 | else: 87 | print('the "{}" error!'.format(by)) 88 | 89 | def is_click(self, by, locator): 90 | if by.lower() in self.byDic: 91 | try: 92 | element = WD(self.driver, self.outTime). \ 93 | until(ec.element_to_be_clickable((self.byDic[by], locator))) 94 | except TimeoutException: 95 | print("元素不可以点击") 96 | else: 97 | return element 98 | else: 99 | print('the "{}" error!'.format(by)) 100 | 101 | def is_alert(self): 102 | """ 103 | assert alert if exsit 104 | :return: alert obj 105 | """ 106 | try: 107 | re = WD(self.driver, self.outTime).until(ec.alert_is_present()) 108 | except (TimeoutException, NoAlertPresentException): 109 | print("error:no found alert") 110 | else: 111 | return re 112 | 113 | def switch_to_frame(self, by, locator): 114 | """判断frame是否存在,存在就跳到frame""" 115 | print('info:switching to iframe "{}"'.format(locator)) 116 | if by.lower() in self.byDic: 117 | try: 118 | WD(self.driver, self.outTime). \ 119 | until(ec.frame_to_be_available_and_switch_to_it((self.byDic[by], locator))) 120 | except TimeoutException as t: 121 | print('error: found "{}" timeout!切换frame失败'.format(locator), t) 122 | else: 123 | print('the "{}" error!'.format(by)) 124 | 125 | def switch_to_default_frame(self): 126 | """返回默认的frame""" 127 | print('info:switch back to default iframe') 128 | try: 129 | self.driver.switch_to.default_content() 130 | except Exception as e: 131 | print(e) 132 | 133 | def get_alert_text(self): 134 | """获取alert的提示信息""" 135 | alert = self.is_alert() 136 | if alert: 137 | return alert.text 138 | else: 139 | return None 140 | 141 | def get_element_text(self, by, locator, name=None): 142 | """获取某一个元素的text信息""" 143 | try: 144 | element = self.find_element(by, locator) 145 | if name: 146 | return element.get_attribute(name) 147 | else: 148 | return element.text 149 | except AttributeError: 150 | print('get "{}" text failed return None'.format(locator)) 151 | 152 | def load_url(self, url): 153 | """加载url""" 154 | print('info: string upload url "{}"'.format(url)) 155 | self.driver.get(url) 156 | 157 | def get_source(self): 158 | """获取页面源码""" 159 | return self.driver.page_source 160 | 161 | def send_keys(self, by, locator, value=''): 162 | """写数据""" 163 | print('info:input "{}"'.format(value)) 164 | try: 165 | element = self.find_element(by, locator) 166 | element.send_keys(value) 167 | except AttributeError as e: 168 | print(e) 169 | 170 | def clear(self, by, locator): 171 | """清理数据""" 172 | print('info:clearing value') 173 | try: 174 | element = self.find_element(by, locator) 175 | element.clear() 176 | except AttributeError as e: 177 | print(e) 178 | 179 | def click(self, by, locator): 180 | """点击某个元素""" 181 | print('info:click "{}"'.format(locator)) 182 | element = self.is_click(by, locator) 183 | if element: 184 | element.click() 185 | else: 186 | print('the "{}" unclickable!') 187 | 188 | @staticmethod 189 | def sleep(num=0): 190 | """强制等待""" 191 | print('info:sleep "{}" minutes'.format(num)) 192 | time.sleep(num) 193 | 194 | def ctrl_v(self, value): 195 | """ctrl + V 粘贴""" 196 | print('info:pasting "{}"'.format(value)) 197 | ClipBoard.set_text(value) 198 | self.sleep(3) 199 | KeyBoard.two_keys('ctrl', 'v') 200 | 201 | @staticmethod 202 | def enter_key(): 203 | """enter 回车键""" 204 | print('info:keydown enter') 205 | KeyBoard.one_key('enter') 206 | 207 | def wait_element_to_be_located(self, by, locator): 208 | """显示等待某个元素出现,且可见""" 209 | print('info:waiting "{}" to be located'.format(locator)) 210 | try: 211 | return WD(self.driver, self.outTime).until(ec.presence_of_element_located((self.byDic[by], locator))) 212 | except TimeoutException as t: 213 | print('error: found "{}" timeout!'.format(locator), t) 214 | 215 | def get_page_source(self): 216 | return self.get_source() 217 | 218 | 219 | if __name__ == "__main__": 220 | pass 221 | -------------------------------------------------------------------------------- /Page/PageObject/ContactPage.py: -------------------------------------------------------------------------------- 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 | from util.parseConFile import ParseConFile 12 | 13 | 14 | class ContactPage(BasePage): 15 | # 配置文件读取元素 16 | do_conf = ParseConFile() 17 | # 新键联系人按钮 18 | new_contact_btn = do_conf.get_locators_or_account('ContactPageElements', 'new_contact') 19 | # 姓名输入框 20 | name = do_conf.get_locators_or_account('ContactPageElements', 'name') 21 | # 电子邮箱输入框 22 | mail = do_conf.get_locators_or_account('ContactPageElements', 'mail') 23 | # 标记为星级 24 | star = do_conf.get_locators_or_account('ContactPageElements', 'star') 25 | # 电话号码输入框 26 | phone = do_conf.get_locators_or_account('ContactPageElements', 'phone') 27 | # 备注输入框 28 | comment = do_conf.get_locators_or_account('ContactPageElements', 'comment') 29 | # 确定按钮 30 | commit = do_conf.get_locators_or_account('ContactPageElements', 'commit') 31 | # 添加失败的提示信息 32 | error_tip = do_conf.get_locators_or_account('ContactPageElements', 'tooltip') 33 | 34 | def add_contact(self, name, mail, star, phone, comment): 35 | """添加联系人""" 36 | self.click_new_contact_btn() 37 | self.input_name(name) 38 | self.input_mail(mail) 39 | if star == '1': 40 | self.select_str() 41 | self.input_phone(phone) 42 | self.input_comment(comment) 43 | self.click_commit_btn() 44 | 45 | def click_new_contact_btn(self): 46 | return self.click(*ContactPage.new_contact_btn) 47 | 48 | def input_name(self, name): 49 | return self.send_keys(*ContactPage.name, name) 50 | 51 | def input_mail(self, mail): 52 | return self.send_keys(*ContactPage.mail, mail) 53 | 54 | def select_str(self): 55 | return self.click(*ContactPage.star) 56 | 57 | def input_phone(self, phone): 58 | return self.send_keys(*ContactPage.phone, phone) 59 | 60 | def input_comment(self, comment): 61 | return self.send_keys(*ContactPage.comment, comment) 62 | 63 | def click_commit_btn(self): 64 | return self.click(*ContactPage.commit) 65 | 66 | def get_error_text(self): 67 | return self.get_element_text(*ContactPage.error_tip) 68 | 69 | 70 | if __name__ == '__main__': 71 | pass 72 | -------------------------------------------------------------------------------- /Page/PageObject/HomePage.py: -------------------------------------------------------------------------------- 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 | from util.parseConFile import ParseConFile 12 | 13 | 14 | class HomePage(BasePage): 15 | # 配置文件读取元素 16 | do_conf = ParseConFile() 17 | # 首页 18 | homePage = do_conf.get_locators_or_account('HomePageElements', 'homePage') 19 | # 通讯录 20 | mailList = do_conf.get_locators_or_account('HomePageElements', 'mailList') 21 | # 应用中心 22 | applicationCenter = do_conf.get_locators_or_account('HomePageElements', 'applicationCenter') 23 | # 收件箱 24 | inBox = do_conf.get_locators_or_account('HomePageElements', 'inBox') 25 | 26 | def select_menu(self, menu='mailList'): 27 | if menu == "mailList": 28 | self.click_address_list_menu() 29 | elif menu == 'homePage': 30 | self.click_home_page_menu() 31 | elif menu == 'applicationCenter': 32 | self.click_application_center_menu() 33 | elif menu == 'inBox': 34 | self.click_in_box_menu() 35 | else: 36 | raise ValueError( 37 | '''菜单选择错误! 38 | homePage->首页 39 | mailList->通讯录 40 | applicationCenter->应用中心 41 | inBox->收件箱''' 42 | ) 43 | 44 | def click_home_page_menu(self): 45 | return self.click(*HomePage.homePage) 46 | 47 | def click_address_list_menu(self): 48 | return self.click(*HomePage.mailList) 49 | 50 | def click_application_center_menu(self): 51 | return self.click(*HomePage.applicationCenter) 52 | 53 | def click_in_box_menu(self): 54 | return self.click(*HomePage.inBox) 55 | 56 | 57 | if __name__ == '__main__': 58 | pass 59 | -------------------------------------------------------------------------------- /Page/PageObject/LoginPage.py: -------------------------------------------------------------------------------- 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 | from util.parseConFile import ParseConFile 12 | 13 | 14 | class LoginPage(BasePage): 15 | # 配置文件读取元素 16 | do_conf = ParseConFile() 17 | # 选择密码登录的按钮 18 | password_login_btn = do_conf.get_locators_or_account('LoginPageElements', 'password_login_btn') 19 | # 登录框外的iframe 20 | frame = do_conf.get_locators_or_account('LoginPageElements', 'frame') 21 | # 用户名输入框 22 | username = do_conf.get_locators_or_account('LoginPageElements', 'username') 23 | # 密码输入框 24 | password = do_conf.get_locators_or_account('LoginPageElements', 'password') 25 | # 登录按钮 26 | loginBtn = do_conf.get_locators_or_account('LoginPageElements', 'loginBtn') 27 | # 登录失败的提示信息 28 | error_head = do_conf.get_locators_or_account('LoginPageElements', 'errorHead') 29 | # 登录成功后的用户显示元素 30 | account = do_conf.get_locators_or_account('HomePageElements', 'account') 31 | 32 | def login(self, username, password): 33 | """登录流程""" 34 | self.open_url() 35 | self.click_password_login_btn() 36 | self.switch_login_frame() 37 | self.input_username(username) 38 | self.input_password(password) 39 | self.click_login_btn() 40 | 41 | def open_url(self): 42 | return self.load_url('https://mail.126.com') 43 | 44 | def click_password_login_btn(self): 45 | return self.click(*LoginPage.password_login_btn) 46 | 47 | def switch_login_frame(self): 48 | return self.switch_to_frame(*LoginPage.frame) 49 | 50 | def clear_username(self): 51 | return self.clear(*LoginPage.username) 52 | 53 | def input_username(self, username): 54 | self.clear_username() 55 | return self.send_keys(*LoginPage.username, username) 56 | 57 | def clear_password(self): 58 | return self.clear(*LoginPage.password) 59 | 60 | def input_password(self, password): 61 | self.clear_password() 62 | return self.send_keys(*LoginPage.password, password) 63 | 64 | def click_login_btn(self): 65 | return self.click(*LoginPage.loginBtn) 66 | 67 | def switch_default_frame(self): 68 | return self.switch_to_default_frame() 69 | 70 | def get_error_text(self): 71 | return self.get_element_text(*LoginPage.error_head) 72 | 73 | def get_login_success_account(self): 74 | return self.get_element_text(*LoginPage.account) 75 | 76 | 77 | if __name__ == "__main__": 78 | pass 79 | -------------------------------------------------------------------------------- /Page/PageObject/SendMailPage.py: -------------------------------------------------------------------------------- 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 | from util.parseConFile import ParseConFile 12 | 13 | 14 | class SendMailPage(BasePage): 15 | # 配置文件读取元素 16 | do_conf = ParseConFile() 17 | # 写信按钮 18 | writeMail = do_conf.get_locators_or_account('SendMailPageElements', 'writeMail') 19 | # 收件人输入框 20 | addressee = do_conf.get_locators_or_account('SendMailPageElements', 'addressee') 21 | # 邮件主题 22 | subject = do_conf.get_locators_or_account('SendMailPageElements', 'subject') 23 | # 上传附件 24 | uploadAttachment = do_conf.get_locators_or_account('SendMailPageElements', 'uploadAttachment') 25 | # 正文外的iframe 26 | iframe = do_conf.get_locators_or_account('SendMailPageElements', 'iframe') 27 | # 正文 28 | text = do_conf.get_locators_or_account('SendMailPageElements', 'text') 29 | # 发送按钮 30 | sendBtn = do_conf.get_locators_or_account('SendMailPageElements', 'sendBtn') 31 | # 发送成功的提示信息 32 | send_success = do_conf.get_locators_or_account('SendMailPageElements', 'send_success') 33 | # 收件人为空的提示信息 34 | error_info_address_is_none = do_conf.get_locators_or_account('SendMailPageElements', 'error_info_address_is_none') 35 | # 收件人格式或者主题为空的提示信息 36 | error_info_popup_window = do_conf.get_locators_or_account('SendMailPageElements', 'error_info_popup_window') 37 | 38 | def send_mail(self, address, subject, text, pfa): 39 | self.click_write_mail_btn() 40 | self.input_address(address) 41 | self.input_subject(subject) 42 | if pfa: 43 | self.upload_file(pfa) 44 | self.switch_frame() 45 | self.input_main_text(text) 46 | self.switch_default_frame() 47 | self.click_send_btn() 48 | 49 | def click_write_mail_btn(self): 50 | return self.click(*SendMailPage.writeMail) 51 | 52 | def input_address(self, address): 53 | return self.send_keys(*SendMailPage.addressee, address) 54 | 55 | def input_subject(self, subject): 56 | return self.send_keys(*SendMailPage.subject, subject) 57 | 58 | def upload_file(self, pfa): 59 | return self.send_keys(*SendMailPage.uploadAttachment, pfa) 60 | 61 | def switch_frame(self): 62 | return self.switch_to_frame(*SendMailPage.iframe) 63 | 64 | def input_main_text(self, text): 65 | return self.send_keys(*SendMailPage.text, text) 66 | 67 | def switch_default_frame(self): 68 | return self.switch_to_default_frame() 69 | 70 | def click_send_btn(self): 71 | return self.click(*SendMailPage.sendBtn) 72 | 73 | def wait_success_info_element_located(self): 74 | return self.wait_element_to_be_located(*SendMailPage.send_success) 75 | 76 | def get_error_address_is_none(self): 77 | element = self.driver.find_element(*SendMailPage.error_info_address_is_none) 78 | return element.text 79 | 80 | def get_error_popup_window(self): 81 | return self.get_element_text(*SendMailPage.error_info_popup_window) 82 | 83 | 84 | if __name__ == '__main__': 85 | pass 86 | -------------------------------------------------------------------------------- /Page/PageObject/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/12 12:28 4 | @Auth : linux超 5 | @File : __init__.py.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ -------------------------------------------------------------------------------- /Page/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/12 9:17 4 | @Auth : linux超 5 | @File : __init__.py.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PytestAutoTestFrameWork 2 | Pytest框架实战项目实例 3 | 帮助: 4 | 通过此项目可以学到以下内容 5 | 1.命令行如何运行测试用例 6 | 2.pytest如何收集测试用例 7 | 3.如何使用fixture 8 | 4.如何使用conftest.py文件 9 | 5.如何使用pytest-html插件生成测试报告 10 | 6.PO设计模式思想是什么样的 11 | 7.selenium 部分API的使用和如何进行简单的二次封装 12 | 9.pytest框架如何参数化测试用例 13 | 10.如何发送测试报告邮件 14 | 11.如何使用代码的方式执行测试用例或整个项目 15 | 12.测试用例编写逻辑 16 | 说明: 17 | 1.本项目测试地址为126邮箱 18 | https://mail.126.com 19 | 2.请先简单了解126邮箱的各个功能 20 | 3.本人博客地址:https://www.cnblogs.com/linuxchao 21 | 环境需求: 22 | 1.windows 7 以上版本 23 | 2.需安装python 3.以上版本 24 | 3.selenium 2 以上版本 25 | 4.需安装pytest框架 26 | 5.需安装pytest -html插件 27 | 6.需安装火狐或谷歌浏览器及对应驱动 28 | 7.需对发送测试报告邮件的邮箱正确配置(可在我博客中找到相关配置文章) 29 | 8.需要安装pypiwin32库 30 | 9.需要安装openpyxl数据处理库 31 | 10.需要安装yagmail库发送测试报告 32 | 运行项目: 33 | 1.下载项目到本地 34 | 2.打开cmd切换到项目根目录 35 | 3.输入python RunTestCase.py运行项目 36 | 4.或者直接通过pytest --html=’report.html‘ 运行(这种方式不会自动发送测试邮件) 37 | 5.或者在pycharm中打开项目,直接运行RunTestCase.py文件 38 | 用例说明: 39 | 请下载原代码自己查看用例具体测试了哪些功能 40 | 41 | 修改说明: 42 | .修改了所有代码的编写规范,使其更加符合PEP8 43 | .由于126邮箱升级,因为修改了部分用例的逻辑,更加容易理解 44 | .所有的用例按照不同错误提示信息进行了分组 45 | .修改了测试数据的存储方式,由excel改为了使用py文件直接存储 46 | .添加了环境管理文件requirement.txt文件,方便clone本想的人能够顺利运行项目 47 | .注意!注意!注意! 48 | .测试数据中的126邮箱的用户名和密码是我本人的邮箱, 请不要做危害国家和我个人的事情,不要浪费我一翻辛苦,非常感谢! 49 | 当然,你最好改为你自己的邮箱,否则你运行项目的时候我会平凡收到邮件 50 | .由于126邮箱有很多限制,坑比较多,比如你登录次数过多时会有验证码的提示(验证码比较难处理, 我未做处理),所以如果 51 | 有验证码提示了后面用例步骤就没办法执行了, 即使清楚cookies下次还是会提示,很烦, 所以我整个项目是多次打开浏览器的 52 | 能够防止一下这种情况 53 | .还有一个限制是在发送邮件的时候,如果发送过多次数,也会有验证,我就不细说了,请自行体会吧 54 | .最后说一句,clone本项目后,最好为本项目建立的空白的虚拟环境, 然后在虚拟环境中使用pip install -r requirements.txt自动安装依赖 55 | -------------------------------------------------------------------------------- /RunTestCase.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/15 16:14 4 | @Auth : linux超 5 | @File : RunTestCase.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ 10 | import sys 11 | import pytest 12 | 13 | from config.conf import ROOT_DIR, HTML_NAME 14 | 15 | # from util.sendMailForReprot import SendMailWithReport 16 | 17 | 18 | def main(): 19 | if ROOT_DIR not in sys.path: 20 | sys.path.append(ROOT_DIR) 21 | # 执行用例 22 | args = ['--reruns', '1', '--html=' + './report/' + HTML_NAME] 23 | pytest.main(args) 24 | # 发送邮件 这里我屏蔽了 自己添加自己的邮箱信息 25 | # SendMailWithReport.send_mail( 26 | # smtpServer, fromUser, fromPassWord, 27 | # toUser, subject, contents, 28 | # htmlName) 29 | 30 | 31 | if __name__ == '__main__': 32 | main() 33 | # 我的部分博客地址 34 | # https://www.cnblogs.com/linuxchao/p/linuxchao-pytest-report.html 35 | # https://www.cnblogs.com/linuxchao/p/linuxchao-pytest-configfile.html 36 | # https://www.cnblogs.com/linuxchao/p/linuxchao-pytest-conftest.html 37 | -------------------------------------------------------------------------------- /TestCases/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/12 14:09 4 | @Auth : linux超 5 | @File : __init__.py.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ -------------------------------------------------------------------------------- /TestCases/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 | 12 | from Page.PageObject.LoginPage import LoginPage 13 | from Page.PageObject.HomePage import HomePage 14 | from Page.PageObject.ContactPage import ContactPage 15 | from Page.PageObject.SendMailPage import SendMailPage 16 | from util.parseConFile import ParseConFile 17 | 18 | 19 | do_conf = ParseConFile() 20 | # 从配置文件中获取正确的用户名和密码 21 | userName = do_conf.get_locators_or_account('126LoginAccount', 'username') 22 | passWord = do_conf.get_locators_or_account('126LoginAccount', 'password') 23 | 24 | 25 | # @pytest.fixture(scope='function') 26 | # def login(driver): 27 | # """除登录用例,每一个用例的前置条件""" 28 | # print('------------staring login------------') 29 | # login_action = LoginPage(driver, 30) 30 | # login_action.login(userName, passWord) 31 | # yield 32 | # print('------------end login------------') 33 | # driver.delete_all_cookies() 34 | 35 | @pytest.fixture(scope='class') 36 | def ini_pages(driver): 37 | login_page = LoginPage(driver) 38 | home_page = HomePage(driver) 39 | contact_page = ContactPage(driver) 40 | send_mail_page = SendMailPage(driver) 41 | yield driver, login_page, home_page, contact_page, send_mail_page 42 | 43 | 44 | @pytest.fixture(scope='function') 45 | def open_url(ini_pages): 46 | driver = ini_pages[0] 47 | login_page = ini_pages[1] 48 | # login_page.open_url() 49 | yield login_page 50 | driver.delete_all_cookies() 51 | 52 | 53 | @pytest.fixture(scope='class') 54 | def login(ini_pages): 55 | driver, login_page, home_page, contact_page, send_mail_page = ini_pages 56 | # login_page.open_url() 57 | login_page.login(userName, passWord) 58 | login_page.switch_default_frame() 59 | yield login_page, home_page, contact_page, send_mail_page 60 | driver.delete_all_cookies() 61 | 62 | 63 | @pytest.fixture(scope='function') 64 | def refresh_page(ini_pages): 65 | driver = ini_pages[0] 66 | yield 67 | driver.refresh() 68 | -------------------------------------------------------------------------------- /TestCases/test_contactCase.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 pytest 11 | 12 | from data.contact_data import ContactData 13 | 14 | 15 | @pytest.mark.conatctTest 16 | class TestAddContact(object): 17 | """添加联系人""" 18 | contact_data = ContactData 19 | success_data = contact_data.add_contact_success 20 | fail_data = contact_data.add_contact_fail 21 | 22 | @pytest.mark.parametrize('name, mail, star, phone, comment, expect', success_data) 23 | def test_add_contact_success(self, login, refresh_page, name, mail, star, phone, comment, expect): 24 | """测试添加联系人""" 25 | home_page = login[1] 26 | contact_page = login[2] 27 | home_page.select_menu(menu="mailList") 28 | contact_page.add_contact(name, mail, star, phone, comment) 29 | actual = contact_page.get_source() 30 | assert expect in actual, "添加联系人成功, 断言失败" 31 | 32 | @pytest.mark.parametrize('name, mail, star, phone, comment, expect', fail_data) 33 | def test_add_contact_fail(self, login, refresh_page, name, mail, star, phone, comment, expect): 34 | home_page = login[1] 35 | contact_page = login[2] 36 | home_page.select_menu(menu="mailList") 37 | contact_page.add_contact(name, mail, star, phone, comment) 38 | actual = contact_page.get_error_text() 39 | assert actual == expect, "添加联系人失败, 断言失败" 40 | 41 | 42 | if __name__ == '__main__': 43 | pytest.main(['-v', 'test_contactCase.py']) 44 | -------------------------------------------------------------------------------- /TestCases/test_loginCase.py: -------------------------------------------------------------------------------- 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 | 12 | from data.login_data import LoginData 13 | 14 | 15 | @pytest.mark.loginTest 16 | class TestLogin(object): 17 | """登录""" 18 | login_data = LoginData 19 | 20 | @pytest.mark.parametrize('username, password, expect', login_data.login_success_data) 21 | def test_login(self, open_url, username, password, expect): 22 | login_page = open_url 23 | login_page.login(username, password) 24 | login_page.switch_default_frame() 25 | actual = login_page.get_login_success_account() 26 | assert expect in actual, "登录成功, 断言失败" 27 | 28 | @pytest.mark.parametrize('username, password, expect', login_data.login_fail_data) 29 | def test_fail(self, open_url, username, password, expect): 30 | login_page = open_url 31 | login_page.login(username, password) 32 | actual = login_page.get_error_text() 33 | assert actual == expect, "登录失败, 断言失败" 34 | 35 | 36 | if __name__ == "__main__": 37 | pytest.main(['-v', 'test_loginCase.py']) 38 | -------------------------------------------------------------------------------- /TestCases/test_sendMailCase.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/20 10:04 4 | @Auth : linux超 5 | @File : test_sendMailCase.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 | 12 | from data.send_mail_data import SendMailData 13 | 14 | 15 | @pytest.mark.sendMailTest 16 | class TestSendMail(object): 17 | """发送邮件""" 18 | mail_data = SendMailData 19 | send_success_data = mail_data.send_mail_success 20 | send_fail_address_is_none_data = mail_data.send_fail_address_is_none 21 | send_fail_address_is_invalid_data = mail_data.send_fail_address_is_invalid_data 22 | send_fail_subject_is_none_data = mail_data.send_fail_subject_is_none_data 23 | 24 | @pytest.mark.sendmail 25 | @pytest.mark.parametrize('address, subject, text, pfa, expect', send_success_data) 26 | def test_send_mail_success(self, login, refresh_page, address, subject, text, pfa, expect): 27 | home_page = login[1] 28 | send_mail_page = login[3] 29 | home_page.select_menu(menu="homePage") 30 | send_mail_page.send_mail(address, subject, text, pfa) 31 | send_mail_page.wait_success_info_element_located() 32 | actual = send_mail_page.get_source() 33 | assert expect in actual, "发送邮件成功, 断言失败" 34 | 35 | @pytest.mark.parametrize('address, subject, text, pfa, expect', send_fail_address_is_none_data) 36 | def test_send_fail_address_is_none(self, login, refresh_page, address, subject, text, pfa, expect): 37 | home_page = login[1] 38 | send_mail_page = login[3] 39 | home_page.select_menu(menu="homePage") 40 | send_mail_page.send_mail(address, subject, text, pfa) 41 | actual = send_mail_page.get_error_address_is_none() 42 | assert expect == actual, "发送邮件失败, 断言失败" 43 | 44 | @pytest.mark.parametrize('address, subject, text, pfa, expect', send_fail_address_is_invalid_data) 45 | def test_send_fail_address_invalid(self, login, refresh_page, address, subject, text, pfa, expect): 46 | home_page = login[1] 47 | send_mail_page = login[3] 48 | home_page.select_menu(menu="homePage") 49 | send_mail_page.send_mail(address, subject, text, pfa) 50 | actual = send_mail_page.get_error_popup_window() 51 | assert expect == actual, "发送邮件失败, 断言失败" 52 | 53 | @pytest.mark.parametrize('address, subject, text, pfa, expect', send_fail_subject_is_none_data) 54 | def test_send_fail_subject_is_none_data(self, login, refresh_page, address, subject, text, pfa, expect): 55 | home_page = login[1] 56 | send_mail_page = login[3] 57 | home_page.select_menu(menu="homePage") 58 | send_mail_page.send_mail(address, subject, text, pfa) 59 | actual = send_mail_page.get_error_popup_window() 60 | assert expect == actual, "发送邮件失败, 断言失败" 61 | 62 | 63 | if __name__ == '__main__': 64 | pytest.main(['-v', 'test_sendMailCase.py']) 65 | -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/15 16:50 4 | @Auth : linux超 5 | @File : __init__.py.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ -------------------------------------------------------------------------------- /config/conf.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/20 16:50 4 | @Auth : linux超 5 | @File : conf.py 6 | @IDE : PyCharm 7 | @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 | # 项目根目录 14 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 15 | # 报告目录 16 | REPORT_DIR = os.path.join(ROOT_DIR, 'report') 17 | # ui对象库config.ini文件所在目录 18 | CONF_PATH = os.path.join(ROOT_DIR, 'config', 'config.ini') 19 | # 测试数据所在目录 20 | DATA_Path = os.path.join(ROOT_DIR, 'data', 'tcData.xlsx') 21 | # 当前时间 22 | CURRENT_TIME = datetime.now().strftime('%H_%M_%S') 23 | 24 | # 邮件配置信息 25 | # 邮件服务器 26 | SMTP_SERVER = 'smtp.qq.com' 27 | # 发送者 28 | FROM_USER = '账号@qq.com' 29 | # 发送者密码 30 | FROM_PASSWORD = 'mhxvqpewblldbjhf' 31 | # 接收者 32 | TO_USER = ['账号@qq.com'] # 可以同时发送给多人,追加到列表中 33 | # 邮件标题 34 | SUBJECT = 'xx项目自动化测试报告' 35 | # 邮件正文 36 | CONTENTS = '测试报告正文' 37 | # 报告名称 38 | HTML_NAME = 'testReport{}.html'.format(CURRENT_TIME) 39 | print(HTML_NAME) -------------------------------------------------------------------------------- /config/config.ini: -------------------------------------------------------------------------------- 1 | [126LoginAccount];126邮箱正确的登录账号和密码;运行用例时请更换正确的用户名和密码 2 | username=linuxxiaochao 3 | password=xiaochao11520 4 | [HomePageElements];126邮箱首页菜单栏元素 5 | account=xpath->//span[@id="spnUid"] 6 | homePage=id->_mail_tabitem_0_3text 7 | mailList=id->_mail_tabitem_1_4text 8 | applicationCenter=id->_mail_tabitem_2_5text 9 | inBox=id->_mail_tabitem_3_6text 10 | [LoginPageElements];126邮箱登录页面的元素 11 | password_login_btn=xpath->//a[@id="switchAccountLogin"] 12 | frame=xpath->//div[@id="loginDiv"]/iframe 13 | username=xpath->//input[@name="email"] 14 | password=xpath->//input[@name="password"] 15 | loginBtn=xpath->//a[@id="dologin"] 16 | errorHead=xpath->//div[@class="ferrorhead"] 17 | [ContactPageElements];126邮箱添加联系人页面元素 18 | new_contact=xpath->//span[text()="新建联系人"] 19 | name=id->input_N 20 | mail=xpath->//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"] 21 | star=xpath->//span[@class="nui-chk-text"]/preceding-sibling::span/b 22 | phone=xpath->//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input'] 23 | comment=id->input_DETAIL 24 | commit=xpath->//span[text()='确 定'] 25 | tooltip=xpath->//span[text()='请正确填写邮件地址。'] 26 | [SendMailPageElements];126邮箱发送邮件页面元素 27 | writeMail=xpath->//div[@id='dvNavContainer']//span[text()='写 信'] 28 | addressee=xpath->//input[@aria-label='收件人地址输入框,请输入邮件地址,多人时地址请以分号隔开'] 29 | subject=xpath->//input[contains(@id, '_subjectInput')] 30 | iframe=xpath->//iframe[@class='APP-editor-iframe'] 31 | text=xpath->/html/body 32 | sendBtn=xpath->//header//span[text()='发送'] 33 | send_success=xpath->//*[text()='发送成功'] 34 | uploadAttachment=xpath->//div[contains(@id,'_attachBrowserCloud')]/preceding-sibling::div[contains(@id, '_attachBrowser')]/input 35 | delete=xpath->//a[text()='删除'] 36 | error_info_address_is_none=xpath->//div[@id='zoomMonitorDiv']/following-sibling::div/span[@class='nui-tips-text'] 37 | error_info_popup_window=xpath->//div[@class='nui-msgbox-title'] -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/12 14: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 selenium import webdriver 12 | from py._xmlgen import html 13 | 14 | _driver = None 15 | 16 | 17 | # 测试失败时添加截图和测试用例描述(用例的注释信息) 18 | 19 | @pytest.mark.hookwrapper 20 | def pytest_runtest_makereport(item): 21 | """ 22 | 当测试失败的时候,自动截图,展示到html报告中 23 | :param item: 24 | """ 25 | pytest_html = item.config.pluginmanager.getplugin('html') 26 | outcome = yield 27 | report = outcome.get_result() 28 | extra = getattr(report, 'extra', []) 29 | 30 | if report.when == 'call' or report.when == "setup": 31 | xfail = hasattr(report, 'wasxfail') 32 | if (report.skipped and xfail) or (report.failed and not xfail): 33 | file_name = report.nodeid.replace("::", "_") + ".png" 34 | screen_img = _capture_screenshot() 35 | if file_name: 36 | html = '
screenshot
' % screen_img 38 | extra.append(pytest_html.extras.html(html)) 39 | report.extra = extra 40 | report.description = str(item.function.__doc__) 41 | report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape") 42 | 43 | 44 | @pytest.mark.optionalhook 45 | def pytest_html_results_table_header(cells): 46 | cells.insert(1, html.th('Description')) 47 | cells.insert(2, html.th('Test_nodeid')) 48 | cells.pop(2) 49 | cells.pop() # modify by linuxchao at 2018.0803 delete link for report 50 | 51 | 52 | @pytest.mark.optionalhook 53 | def pytest_html_results_table_row(report, cells): 54 | cells.insert(1, html.td(report.description)) 55 | cells.insert(2, html.td(report.nodeid)) 56 | cells.pop(2) 57 | cells.pop() # modify by linuxchao at 2018.0803 delete link for report 58 | 59 | 60 | def _capture_screenshot(): 61 | """ 62 | 截图保存为base64 63 | :return: 64 | """ 65 | return _driver.get_screenshot_as_base64() 66 | 67 | 68 | # 这里我设置的级别是模块级别,也就是每个测试文件运行一次 69 | # 可以设置为session,全部用例执行一次,但是针对126邮箱的话 70 | # 登录次数太多会叫你验证,如果验证就没法执行用例了,我没有对验证处理(处理比较复杂) 71 | @pytest.fixture(scope='module') 72 | def driver(): 73 | global _driver 74 | print('------------open browser------------') 75 | _driver = webdriver.Firefox() 76 | _driver.maximize_window() 77 | yield _driver 78 | print('------------close browser------------') 79 | _driver.quit() 80 | -------------------------------------------------------------------------------- /data/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/22 17:14 4 | @Auth : linux超 5 | @File : __init__.py.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ -------------------------------------------------------------------------------- /data/attachment: -------------------------------------------------------------------------------- 1 | 本文件作为测试发送带附件的邮件 -------------------------------------------------------------------------------- /data/contact_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/4 14:03 4 | @Auth : linux超 5 | @File : contact_data.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | @QQ : 28174043@qq.com 9 | @GROUP: 878565760 10 | ------------------------------------ 11 | """ 12 | 13 | 14 | class ContactData(object): 15 | """添加联系人测试数据""" 16 | 17 | add_contact_success = [ 18 | ( 19 | "linux1", 20 | "281754041@qq.com", 21 | "1", 22 | "13691579841", 23 | "添加联系人1", 24 | "281754041@qq.com" 25 | ) 26 | ] 27 | add_contact_fail = [ 28 | ( 29 | "linux2", 30 | "@qq.com", 31 | "0", 32 | "13691579842", 33 | "添加联系人2", 34 | "请正确填写邮件地址。" 35 | ) 36 | ] 37 | 38 | 39 | if __name__ == '__main__': 40 | pass 41 | -------------------------------------------------------------------------------- /data/login_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/4 13:05 4 | @Auth : linux超 5 | @File : login_data.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | @QQ : 28174043@qq.com 9 | @GROUP: 878565760 10 | ------------------------------------ 11 | """ 12 | 13 | 14 | class LoginData(object): 15 | """用户登录测试数据""" 16 | 17 | login_success_data = [ 18 | ( 19 | "linuxxiaochao", 20 | "xiaochao11520", 21 | "linuxxiaochao@126.com" 22 | ) 23 | ] 24 | 25 | login_fail_data = [ 26 | ( 27 | "linuxxiaochao", 28 | "", 29 | "请输入密码" 30 | ), 31 | ( 32 | "", 33 | "xiaochao11520", 34 | "请输入帐号" 35 | ), 36 | ( 37 | "linux", 38 | "xiaochao", 39 | "帐号或密码错误" 40 | ) 41 | ] 42 | 43 | 44 | if __name__ == '__main__': 45 | pass 46 | -------------------------------------------------------------------------------- /data/send_mail_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/4 14:44 4 | @Auth : linux超 5 | @File : send_mail_data.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | @QQ : 28174043@qq.com 9 | @GROUP: 878565760 10 | ------------------------------------ 11 | """ 12 | 13 | 14 | class SendMailData(object): 15 | """发送邮件测试数据""" 16 | 17 | send_mail_success = [ 18 | ( 19 | "281754043@qq.com", 20 | "测试发送普通测试邮件", 21 | "测试发送普通测试邮件", 22 | "", 23 | "发送成功" 24 | ), 25 | ( 26 | "281754043@qq.com", 27 | "测试发送带附件的邮件", 28 | "测试发送带附件的邮件", 29 | "D:\\PytestAutoTestFrameWork\\data\\attachment", 30 | "发送成功" 31 | ), 32 | ( 33 | "281754043@qq.com", 34 | "", 35 | "测试发送带附件的邮件且主题为空", 36 | "D:\\PytestAutoTestFrameWork\\data\\attachment", 37 | "发送成功" 38 | ) 39 | ] 40 | 41 | send_fail_address_is_none = [ 42 | ( 43 | "", 44 | "测试收件人地址为空", 45 | "测试收件人地址为空", 46 | "D:\\PytestAutoTestFrameWork\\data\\attachment", 47 | "请填写收件人地址后再发送" 48 | ) 49 | ] 50 | 51 | send_fail_subject_is_none_data = [ 52 | ( 53 | "281754043@qq.com", 54 | "", 55 | "测试邮件主题为空:不能添加附件", 56 | "", 57 | "确定真的不需要写主题吗?" 58 | ) 59 | ] 60 | 61 | send_fail_address_is_invalid_data = [ 62 | ( 63 | "281754043", 64 | "测试收件人格式不正确", 65 | "测试收件人格式不正确", 66 | "D:\\PytestAutoTestFrameWork\\data\\attachment", 67 | "以下邮箱地址无效,将无法成功收到邮件" 68 | ) 69 | ] 70 | 71 | 72 | if __name__ == '__main__': 73 | pass 74 | -------------------------------------------------------------------------------- /data/tcData.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/PytestAutoTestFrameWork/1cb9cb7f910585d04ca51f910a42e1311b51b933/data/tcData.xlsx -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /report/testReport22_52_18.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test Report 6 | 170 | 171 | 400 |

testReport22_52_18.html

401 |

Report generated on 19-Apr-2019 at 22:56:22 by pytest-html v1.20.0

402 |

Environment

403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 |
JAVA_HOMEC:\Program Files\Java\jdk1.8.0_181
Packages{'pytest': '4.4.1', 'py': '1.6.0', 'pluggy': '0.9.0'}
PlatformWindows-10-10.0.17134-SP0
Plugins{'rerunfailures': '7.0', 'metadata': '1.8.0', 'html': '1.20.0'}
Python3.6.4
419 |

Summary

420 |

13 tests ran in 241.68 seconds.

421 | 13 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun 422 |

Results

423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 |
ResultDescriptionTestDurationLinks
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux1-1@qq.com--13691579841-test1]8.15
442 |
---------------------------- Captured stdout setup -----------------------------
------------open browser------------ 443 | ------------staring login------------ 444 | -------staring login------- 445 | info: string upload url "https://mail.126.com" 446 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 447 | info:clearing value 448 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 449 | info:input "linuxxiaochao" 450 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 451 | info:clearing value 452 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 453 | info:input "xiaochao11520" 454 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 455 | info:click "//a[@id="dologin"]" 456 | info:switch back to default iframe 457 | ---------end login--------- 458 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 459 | --------string add contact-------- 460 | info:click "//span[text()="新建联系人"]" 461 | info:input "linux1" 462 | [Info:Starting find the element "input_N" by "id"!] 463 | info:input "1@qq.com" 464 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 465 | info:input "13691579841" 466 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 467 | info:input "test1" 468 | [Info:Starting find the element "input_DETAIL" by "id"!] 469 | info:click "//span[text()='确 定']" 470 | --------end add contact-------- 471 | info:sleep "5" minutes 472 | info:assert "linux1" in page source 473 |
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux2-281754042@.com--13691579842-test1]7.40
483 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 484 | -------staring login------- 485 | info: string upload url "https://mail.126.com" 486 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 487 | info:clearing value 488 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 489 | info:input "linuxxiaochao" 490 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 491 | info:clearing value 492 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 493 | info:input "xiaochao11520" 494 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 495 | info:click "//a[@id="dologin"]" 496 | info:switch back to default iframe 497 | ---------end login--------- 498 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 499 | --------string add contact-------- 500 | info:click "//span[text()="新建联系人"]" 501 | info:input "linux2" 502 | [Info:Starting find the element "input_N" by "id"!] 503 | info:input "281754042@.com" 504 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 505 | info:input "13691579842" 506 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 507 | info:input "test1" 508 | [Info:Starting find the element "input_DETAIL" by "id"!] 509 | info:click "//span[text()='确 定']" 510 | --------end add contact-------- 511 | info:sleep "5" minutes 512 | [Info:Starting find the element "//span[text()='请正确填写邮件地址。']" by "xpath"!] 513 | info: assert "请正确填写邮件地址。"=="请正确填写邮件地址。" 514 |
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux3-043@qq.cn--13691579843-test1]7.35
524 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 525 | -------staring login------- 526 | info: string upload url "https://mail.126.com" 527 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 528 | info:clearing value 529 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 530 | info:input "linuxxiaochao" 531 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 532 | info:clearing value 533 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 534 | info:input "xiaochao11520" 535 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 536 | info:click "//a[@id="dologin"]" 537 | info:switch back to default iframe 538 | ---------end login--------- 539 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 540 | --------string add contact-------- 541 | info:click "//span[text()="新建联系人"]" 542 | info:input "linux3" 543 | [Info:Starting find the element "input_N" by "id"!] 544 | info:input "043@qq.cn" 545 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 546 | info:input "13691579843" 547 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 548 | info:input "test1" 549 | [Info:Starting find the element "input_DETAIL" by "id"!] 550 | info:click "//span[text()='确 定']" 551 | --------end add contact-------- 552 | info:sleep "5" minutes 553 | info:assert "linux3" in page source 554 |
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux4---13691579843-test1]7.74
564 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 565 | -------staring login------- 566 | info: string upload url "https://mail.126.com" 567 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 568 | info:clearing value 569 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 570 | info:input "linuxxiaochao" 571 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 572 | info:clearing value 573 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 574 | info:input "xiaochao11520" 575 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 576 | info:click "//a[@id="dologin"]" 577 | info:switch back to default iframe 578 | ---------end login--------- 579 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 580 | --------string add contact-------- 581 | info:click "//span[text()="新建联系人"]" 582 | info:input "linux4" 583 | [Info:Starting find the element "input_N" by "id"!] 584 | info:input "" 585 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 586 | info:input "13691579843" 587 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 588 | info:input "test1" 589 | [Info:Starting find the element "input_DETAIL" by "id"!] 590 | info:click "//span[text()='确 定']" 591 | --------end add contact-------- 592 | info:sleep "5" minutes 593 | [Info:Starting find the element "//span[text()='请正确填写邮件地址。']" by "xpath"!] 594 | info: assert "请正确填写邮件地址。"=="请正确填写邮件地址。" 595 |
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux3-281754043@qq--13691579843-test1]7.55
605 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 606 | -------staring login------- 607 | info: string upload url "https://mail.126.com" 608 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 609 | info:clearing value 610 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 611 | info:input "linuxxiaochao" 612 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 613 | info:clearing value 614 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 615 | info:input "xiaochao11520" 616 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 617 | info:click "//a[@id="dologin"]" 618 | info:switch back to default iframe 619 | ---------end login--------- 620 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 621 | --------string add contact-------- 622 | info:click "//span[text()="新建联系人"]" 623 | info:input "linux3" 624 | [Info:Starting find the element "input_N" by "id"!] 625 | info:input "281754043@qq" 626 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 627 | info:input "13691579843" 628 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 629 | info:input "test1" 630 | [Info:Starting find the element "input_DETAIL" by "id"!] 631 | info:click "//span[text()='确 定']" 632 | --------end add contact-------- 633 | info:sleep "5" minutes 634 | [Info:Starting find the element "//span[text()='请正确填写邮件地址。']" by "xpath"!] 635 | info: assert "请正确填写邮件地址。"=="请正确填写邮件地址。" 636 |
Passed测试添加联系人TestCases/test_contactCase.py::test_NewContact[linux3-@qq.com--13691579843-test1]7.57
646 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 647 | -------staring login------- 648 | info: string upload url "https://mail.126.com" 649 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 650 | info:clearing value 651 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 652 | info:input "linuxxiaochao" 653 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 654 | info:clearing value 655 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 656 | info:input "xiaochao11520" 657 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 658 | info:click "//a[@id="dologin"]" 659 | info:switch back to default iframe 660 | ---------end login--------- 661 | ----------------------------- Captured stdout call -----------------------------
info:click "_mail_tabitem_1_4text" 662 | --------string add contact-------- 663 | info:click "//span[text()="新建联系人"]" 664 | info:input "linux3" 665 | [Info:Starting find the element "input_N" by "id"!] 666 | info:input "@qq.com" 667 | [Info:Starting find the element "//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]" by "xpath"!] 668 | info:input "13691579843" 669 | [Info:Starting find the element "//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']" by "xpath"!] 670 | info:input "test1" 671 | [Info:Starting find the element "input_DETAIL" by "id"!] 672 | info:click "//span[text()='确 定']" 673 | --------end add contact-------- 674 | info:sleep "5" minutes 675 | [Info:Starting find the element "//span[text()='请正确填写邮件地址。']" by "xpath"!] 676 | info: assert "请正确填写邮件地址。"=="请正确填写邮件地址。" 677 |
Passed测试登录TestCases/test_loginCase.py::test_login[linux-]19.87
687 |
---------------------------- Captured stdout setup -----------------------------
------------open browser------------ 688 | ----------------------------- Captured stdout call -----------------------------
-------staring login------- 689 | info: string upload url "https://mail.126.com" 690 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 691 | info:clearing value 692 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 693 | info:input "linux" 694 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 695 | info:clearing value 696 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 697 | info:input "" 698 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 699 | info:click "//a[@id="dologin"]" 700 | info:switch back to default iframe 701 | ---------end login--------- 702 | info:sleep "5" minutes 703 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 704 | [Info:Starting find the element "//div[@class="ferrorhead"]" by "xpath"!] 705 | info:switch back to default iframe 706 | info: assert "请输入密码" == "请输入密码" 707 |
Passed测试登录TestCases/test_loginCase.py::test_login[-chao]6.11
717 |
----------------------------- Captured stdout call -----------------------------
-------staring login------- 718 | info: string upload url "https://mail.126.com" 719 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 720 | info:clearing value 721 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 722 | info:input "" 723 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 724 | info:clearing value 725 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 726 | info:input "chao" 727 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 728 | info:click "//a[@id="dologin"]" 729 | info:switch back to default iframe 730 | ---------end login--------- 731 | info:sleep "5" minutes 732 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 733 | [Info:Starting find the element "//div[@class="ferrorhead"]" by "xpath"!] 734 | info:switch back to default iframe 735 | info: assert "请输入帐号" == "请输入帐号" 736 |
Passed测试登录TestCases/test_loginCase.py::test_login[l-chao]6.15
746 |
----------------------------- Captured stdout call -----------------------------
-------staring login------- 747 | info: string upload url "https://mail.126.com" 748 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 749 | info:clearing value 750 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 751 | info:input "l" 752 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 753 | info:clearing value 754 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 755 | info:input "chao" 756 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 757 | info:click "//a[@id="dologin"]" 758 | info:switch back to default iframe 759 | ---------end login--------- 760 | info:sleep "5" minutes 761 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 762 | [Info:Starting find the element "//div[@class="ferrorhead"]" by "xpath"!] 763 | info:switch back to default iframe 764 | info: assert "帐号或密码错误" == "帐号或密码错误" 765 |
Passed测试登录TestCases/test_loginCase.py::test_login[-]6.14
775 |
----------------------------- Captured stdout call -----------------------------
-------staring login------- 776 | info: string upload url "https://mail.126.com" 777 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 778 | info:clearing value 779 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 780 | info:input "" 781 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 782 | info:clearing value 783 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 784 | info:input "" 785 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 786 | info:click "//a[@id="dologin"]" 787 | info:switch back to default iframe 788 | ---------end login--------- 789 | info:sleep "5" minutes 790 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 791 | [Info:Starting find the element "//div[@class="ferrorhead"]" by "xpath"!] 792 | info:switch back to default iframe 793 | info: assert "请输入帐号" == "请输入帐号" 794 |
Passed测试发送邮件,包括带附件的邮件TestCases/test_sendMailCase.py::test_sendMail[281754043@qq.com-pytest测试主题1-pytest 测试邮件, 请勿回复!-0-]8.34
804 |
---------------------------- Captured stdout setup -----------------------------
------------open browser------------ 805 | ------------staring login------------ 806 | -------staring login------- 807 | info: string upload url "https://mail.126.com" 808 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 809 | info:clearing value 810 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 811 | info:input "linuxxiaochao" 812 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 813 | info:clearing value 814 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 815 | info:input "xiaochao11520" 816 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 817 | info:click "//a[@id="dologin"]" 818 | info:switch back to default iframe 819 | ---------end login--------- 820 | ----------------------------- Captured stdout call -----------------------------
------------string send mail--------------------- 821 | info:click "//div[@id='dvNavContainer']//span[text()='写 信']" 822 | info:input "281754043@qq.com" 823 | [Info:Starting find the element "//input[@aria-label='收件人地址输入框,请输入邮件地址,多人时地址请以分号隔开']" by "xpath"!] 824 | info:input "pytest测试主题1" 825 | [Info:Starting find the element "//input[contains(@id, '_subjectInput')]" by "xpath"!] 826 | info:switching to iframe "//iframe[@class="APP-editor-iframe"]" 827 | info:input "pytest 测试邮件, 请勿回复!" 828 | [Info:Starting find the element "/html/body" by "xpath"!] 829 | info:switch back to default iframe 830 | info:click "//header//span[text()='发送']" 831 | ------------end send mail--------------------- 832 | info:sleep "5" minutes 833 |
Passed测试发送邮件,包括带附件的邮件TestCases/test_sendMailCase.py::test_sendMail[281754043@qq.com-pytest测试主题2-pytest 测试邮件, 请勿回复!-1-D:\KeyWordDriverTestFrameWork\geckodriver.log]43.19
843 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 844 | -------staring login------- 845 | info: string upload url "https://mail.126.com" 846 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 847 | info:clearing value 848 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 849 | info:input "linuxxiaochao" 850 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 851 | info:clearing value 852 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 853 | info:input "xiaochao11520" 854 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 855 | info:click "//a[@id="dologin"]" 856 | info:switch back to default iframe 857 | ---------end login--------- 858 | ----------------------------- Captured stdout call -----------------------------
------------string send mail--------------------- 859 | info:click "//div[@id='dvNavContainer']//span[text()='写 信']" 860 | info:input "281754043@qq.com" 861 | [Info:Starting find the element "//input[@aria-label='收件人地址输入框,请输入邮件地址,多人时地址请以分号隔开']" by "xpath"!] 862 | info:input "pytest测试主题2" 863 | [Info:Starting find the element "//input[contains(@id, '_subjectInput')]" by "xpath"!] 864 | info:switching to iframe "//iframe[@class="APP-editor-iframe"]" 865 | info:input "pytest 测试邮件, 请勿回复!" 866 | [Info:Starting find the element "/html/body" by "xpath"!] 867 | info:switch back to default iframe 868 | info:click "//div[@title="点击添加附件"]" 869 | info:pasting "D:\KeyWordDriverTestFrameWork\geckodriver.log" 870 | info:sleep "3" minutes 871 | info:keydown enter 872 | info:waiting "//a[text()='删除']" to be located 873 | error: found "//a[text()='删除']" timeout! Message: 874 | 875 | info:click "//header//span[text()='发送']" 876 | ------------end send mail--------------------- 877 | info:sleep "5" minutes 878 |
Passed测试发送邮件,包括带附件的邮件TestCases/test_sendMailCase.py::test_sendMail[281754043@qq.com-pytest测试主题3-pytest 测试邮件, 请勿回复!-1-D:\KeyWordDriverTestFrameWork\geckodriver.log]42.66
888 |
---------------------------- Captured stdout setup -----------------------------
------------staring login------------ 889 | -------staring login------- 890 | info: string upload url "https://mail.126.com" 891 | info:switching to iframe "//div[@id="loginDiv"]/iframe" 892 | info:clearing value 893 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 894 | info:input "linuxxiaochao" 895 | [Info:Starting find the element "//input[@name="email"]" by "xpath"!] 896 | info:clearing value 897 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 898 | info:input "xiaochao11520" 899 | [Info:Starting find the element "//input[@name="password"]" by "xpath"!] 900 | info:click "//a[@id="dologin"]" 901 | info:switch back to default iframe 902 | ---------end login--------- 903 | ----------------------------- Captured stdout call -----------------------------
------------string send mail--------------------- 904 | info:click "//div[@id='dvNavContainer']//span[text()='写 信']" 905 | info:input "281754043@qq.com" 906 | [Info:Starting find the element "//input[@aria-label='收件人地址输入框,请输入邮件地址,多人时地址请以分号隔开']" by "xpath"!] 907 | info:input "pytest测试主题3" 908 | [Info:Starting find the element "//input[contains(@id, '_subjectInput')]" by "xpath"!] 909 | info:switching to iframe "//iframe[@class="APP-editor-iframe"]" 910 | info:input "pytest 测试邮件, 请勿回复!" 911 | [Info:Starting find the element "/html/body" by "xpath"!] 912 | info:switch back to default iframe 913 | info:click "//div[@title="点击添加附件"]" 914 | info:pasting "D:\KeyWordDriverTestFrameWork\geckodriver.log" 915 | info:sleep "3" minutes 916 | info:keydown enter 917 | info:waiting "//a[text()='删除']" to be located 918 | error: found "//a[text()='删除']" timeout! Message: 919 | 920 | info:click "//header//span[text()='发送']" 921 | ------------end send mail--------------------- 922 | info:sleep "5" minutes 923 |
-------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | atomicwrites==1.3.0 2 | attrs==19.1.0 3 | colorama==0.4.1 4 | et-xmlfile==1.0.1 5 | importlib-metadata==0.19 6 | jdcal==1.4.1 7 | more-itertools==7.2.0 8 | openpyxl==2.6.2 9 | packaging==19.1 10 | pluggy==0.12.0 11 | py==1.8.0 12 | pyparsing==2.4.2 13 | pypiwin32==223 14 | pytest==5.0.1 15 | pytest-html==1.21.1 16 | pytest-metadata==1.8.0 17 | pytest-rerunfailures==7.0 18 | pywin32==224 19 | selenium==3.141.0 20 | six==1.12.0 21 | urllib3==1.25.3 22 | wcwidth==0.1.7 23 | yagmail==0.11.220 24 | zipp==0.5.2 25 | -------------------------------------------------------------------------------- /util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/PytestAutoTestFrameWork/1cb9cb7f910585d04ca51f910a42e1311b51b933/util/__init__.py -------------------------------------------------------------------------------- /util/clipboard.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/15 12:04 4 | @Auth : linux超 5 | @File : clipboard.py 6 | @IDE : PyCharm 7 | @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 get_text(): 19 | """获取剪切板的内容""" 20 | wc.OpenClipboard() 21 | value = wc.GetClipboardData(win32con.CF_TEXT) 22 | wc.CloseClipboard() 23 | return value 24 | 25 | @staticmethod 26 | def set_text(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 | pass 36 | -------------------------------------------------------------------------------- /util/keyboard.py: -------------------------------------------------------------------------------- 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 key_down(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 key_up(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 one_key(key): 47 | """模拟单个按键""" 48 | key = key.lower() 49 | KeyBoard.key_down(key) 50 | time.sleep(2) 51 | KeyBoard.key_up(key) 52 | 53 | @staticmethod 54 | def two_keys(key1, key2): 55 | """模拟组合按键""" 56 | key1 = key1.lower() 57 | key2 = key2.lower() 58 | KeyBoard.key_down(key1) 59 | KeyBoard.key_down(key2) 60 | KeyBoard.key_up(key1) 61 | KeyBoard.key_up(key2) 62 | 63 | 64 | if __name__ == '__main__': 65 | pass 66 | -------------------------------------------------------------------------------- /util/parseConFile.py: -------------------------------------------------------------------------------- 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 CONF_PATH 12 | 13 | 14 | class ParseConFile(object): 15 | 16 | def __init__(self): 17 | self.file = CONF_PATH 18 | self.conf = configparser.ConfigParser() 19 | self.conf.read(self.file, encoding='utf-8') 20 | 21 | def get_all_sections(self): 22 | """获取所有的section,返回一个列表""" 23 | return self.conf.sections() 24 | 25 | def get_all_options(self, section): 26 | """获取指定section下所有的option, 返回列表""" 27 | return self.conf.options(section) 28 | 29 | def get_locators_or_account(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 get_option_value(self, section): 41 | """获取指定section下所有的option和对应的数据,返回字典""" 42 | value = dict(self.conf.items(section)) 43 | return value 44 | 45 | 46 | if __name__ == '__main__': 47 | pass 48 | -------------------------------------------------------------------------------- /util/parseExcelFile.py: -------------------------------------------------------------------------------- 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 DATA_Path 12 | 13 | 14 | class ParseExcel(object): 15 | 16 | def __init__(self): 17 | self.wk = load_workbook(DATA_Path) 18 | self.excelFile = DATA_Path 19 | 20 | def get_sheet_by_name(self, sheet_name): 21 | """获取sheet对象""" 22 | sheet = self.wk[sheet_name] 23 | return sheet 24 | 25 | def get_row_num(self, sheet): 26 | """获取有效数据的最大行号""" 27 | return sheet.max_row 28 | 29 | def get_cols_num(self, sheet): 30 | """获取有效数据的最大列号""" 31 | return sheet.max_column 32 | 33 | def get_row_values(self, sheet, row_num): 34 | """获取某一行的数据""" 35 | max_cols_num = self.get_cols_num(sheet) 36 | row_values = [] 37 | for colsNum in range(1, max_cols_num + 1): 38 | value = sheet.cell(row_num, colsNum).value 39 | if value is None: 40 | value = '' 41 | row_values.append(value) 42 | return tuple(row_values) 43 | 44 | def get_column_values(self, sheet, column_num): 45 | """获取某一列的数据""" 46 | max_row_num = self.get_row_num(sheet) 47 | column_values = [] 48 | for rowNum in range(2, max_row_num + 1): 49 | value = sheet.cell(rowNum, column_num).value 50 | if value is None: 51 | value = '' 52 | column_values.append(value) 53 | return tuple(column_values) 54 | 55 | def get_value_of_cell(self, sheet, row_num, column_num): 56 | """获取某一个单元格的数据""" 57 | value = sheet.cell(row_num, column_num).value 58 | if value is None: 59 | value = '' 60 | return value 61 | 62 | def get_all_values_of_sheet(self, sheet): 63 | """获取某一个sheet页的所有测试数据,返回一个元祖组成的列表""" 64 | max_row_num = self.get_row_num(sheet) 65 | column_num = self.get_cols_num(sheet) 66 | all_values = [] 67 | for row in range(2, max_row_num + 1): 68 | row_values = [] 69 | for column in range(1, column_num + 1): 70 | value = sheet.cell(row, column).value 71 | if value is None: 72 | value = '' 73 | row_values.append(value) 74 | all_values.append(tuple(row_values)) 75 | return all_values 76 | 77 | 78 | if __name__ == '__main__': 79 | pass 80 | -------------------------------------------------------------------------------- /util/sendMailForReprot.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/4/16 15:38 4 | @Auth : linux超 5 | @File : sendMailForReprot.py 6 | @IDE : PyCharm 7 | @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 | ------------------------------------ 9 | """ 10 | 11 | import yagmail 12 | 13 | 14 | class SendMailWithReport(object): 15 | """发送邮件""" 16 | 17 | @staticmethod 18 | def send_mail(smtp_server, from_user, from_pass_word, to_user, subject, contents, file_name): 19 | # 初始化服务器等信息 20 | yag = yagmail.SMTP(from_user, from_pass_word, smtp_server) 21 | # 发送邮件 22 | yag.send(to_user, subject, contents, file_name) 23 | 24 | 25 | if __name__ == '__main__': 26 | SendMailWithReport.send_mail('smtp.qq.com', 27 | '账号@qq.com', 28 | 'mhxvqpewblldbjhf', 29 | '账号@qq.com', 30 | 'python自动化测试', 31 | '邮件正文', 32 | '17_12_07.html') 33 | --------------------------------------------------------------------------------