├── .gitattributes ├── .gitignore ├── README.md ├── RunTest.py ├── bussines ├── AddContact.py ├── LoginAction.py └── __init__.py ├── config ├── PageElementLocator.ini ├── __init__.py └── config.py ├── img ├── 2019-08-03 │ ├── 22_52_27yyy-yyyy.png │ ├── 23_24_42yyy-yyyy失败.png │ ├── 23_29_36yyy-yyyy失败.png │ └── 23_41_57yyy-yyyy失败.png └── __init__.py ├── log ├── __init__.py ├── log2019-03-21.txt └── log2019-08-03.txt ├── pages ├── HomePage.py ├── LoginPage.py ├── NewContactPage.py ├── __init__.py └── base.py ├── requirements.txt ├── testCases ├── TestMail126.py └── __init__.py ├── testData ├── 126MailContact.xlsx └── __init__.py └── util ├── GetDateTime.py ├── ParseConfig.py ├── ParseExcel.py ├── RecordLog.py └── __init__.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py linguist-language=python 2 | *.html linguist-language=python 3 | *.css linguist-language=python 4 | *.xlsx linguist-language=python -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ##ignore these files## 2 | .idea 3 | *.log 4 | venv/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DataDriverTestFrameWork 2 | 一.说明 3 | 4 | ``本实例为数据驱动测试框架搭建实践`` 5 | 6 | 二.框架分析 7 | 8 | 注意!注意!注意!重要的示请说3遍,本项目只用于学习使用,为了你能够成功执行本项目 9 | excel文件中我的126邮箱帐号和密码并未修改,所以讷,请不要使用我的帐号做有损国家和我利益的事情,再次感谢 10 | .本项目未使用任何测试框架, 比如ddt数据驱动,unittest框架,pytest框架 11 | 完全通过代码的控制及结合excel实现自动化测试的数据驱动,学习性很强 12 | .如果你深入理解了本项目的设计逻辑,对于以后学习ddt,PO设计模式,unittest单元测试框架有很大的帮助 13 | .本项目所有的元素定位表达式采用了UI对象库存储思想,当页面元素发生变化时只需修改UI对象库中的定位表达式即可完成项目的后期维护 14 | .所有的测试用例采用excel存储,方便管理,且可任意添加测试数据 15 | .项目中使用了PO设计模式,把被测项目的每个页面抽象成一个类,对每个页面的每个操作单独封装一个方法,减小代码的耦合,也方便代码的维护 16 | 17 | 三.如何运行此框架 18 | 19 | .克隆项目框架到本地 20 | .找到excel文件,可以修改里面的账号密码等数据,当然你也可以不修改 21 | .运行方式1:打开cmd切换到项目目录,输入命令python RunTest.py(注意:需要接此文件完整路径) 22 | .运行方式2:从已经配置了python解释器的ide中手动运行RunTest.py文件 23 | .可以根据自己的需求添加其他功能 24 | 25 | 四.本人联系方式 26 | 27 | .联系QQ:281754043 技术交流QQ群:878565760 个人博客地址:https://www.cnblogs.com/linuxchao/ 28 | 29 | 五.修改记录 30 | 31 | .modify by linuxchao at 2019.08.03 32 | .修改了部分代码逻辑 33 | .修改了部分代码编写规范, 更加符合PEP8规范 34 | .添加了截图功能 35 | .由于126邮箱做了升级,因此修改了用例的逻辑 36 | .为了他人能够顺利的运行本项目,添加了环境管理文件requirements.txt文件 37 | .如果你clone了本项目,可以为本项目新键一个虚拟环境 38 | 在虚拟环境中执行pip install -r requirements.txt即可为本项目安装所有的依赖库,避免使用本地环境冲突 -------------------------------------------------------------------------------- /RunTest.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from testCases.TestMail126 import test_mail_login 13 | 14 | 15 | if __name__ == '__main__': 16 | test_mail_login() 17 | -------------------------------------------------------------------------------- /bussines/AddContact.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from pages.HomePage import HomePage 13 | from pages.NewContactPage import AddContactPage 14 | 15 | 16 | class NewContactPersonAction(object): 17 | def __init__(self, driver): 18 | self.driver = driver 19 | self.home_page = HomePage(self.driver) 20 | self.new_contact_page = AddContactPage(self.driver) 21 | 22 | def address_link(self): 23 | """点击通讯录按钮""" 24 | self.home_page.address_link.click() 25 | 26 | def add_contact(self, contact_name, contact_mail, is_star, contact_phone, contact_comment): 27 | """添加联系人场景""" 28 | # 点击新建联系人 29 | self.new_contact_page.new_contact.click() 30 | if contact_name: 31 | # 非必填项 32 | self.new_contact_page.add_name.send_keys(contact_name) 33 | # 必填项 34 | self.new_contact_page.add_mail.send_keys(contact_mail) 35 | if is_star == '是': 36 | self.new_contact_page.mark_star.click() 37 | if contact_phone: 38 | self.new_contact_page.add_phone.send_keys(contact_phone) 39 | if contact_comment: 40 | self.new_contact_page.add_content.send_keys(contact_comment) 41 | self.new_contact_page.click_commit_btn.click() 42 | 43 | 44 | if __name__ == '__main__': 45 | pass 46 | -------------------------------------------------------------------------------- /bussines/LoginAction.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from pages.LoginPage import LoginPage 13 | 14 | 15 | class LoginAction(object): 16 | 17 | def __init__(self, driver): 18 | self.driver = driver 19 | self.login_page = LoginPage(self.driver) 20 | 21 | def click_password_login(self): 22 | self.login_page.click_password_login_btn.click() 23 | 24 | def login(self, username, password): 25 | """登录场景""" 26 | self.login_page.switch_to_frame() 27 | self.login_page.user_name_element.send_keys(username) 28 | self.login_page.password_element.send_keys(password) 29 | self.login_page.login_btn_element.click() 30 | self.login_page.switch_to_default_frame() 31 | 32 | 33 | if __name__ == '__main__': 34 | pass 35 | -------------------------------------------------------------------------------- /bussines/__init__.py: -------------------------------------------------------------------------------- 1 | # 目录封装业务逻辑功能 -------------------------------------------------------------------------------- /config/PageElementLocator.ini: -------------------------------------------------------------------------------- 1 | [126mail_login] 2 | loginPage.passWordLoginBtn=xpath>//a[@id='switchAccountLogin'] 3 | loginPage.frame=xpath>//div[@id='loginDiv']/iframe 4 | loginPage.username=xpath>//input[@name='email'] 5 | loginPage.password=xpath>//input[@name='password'] 6 | loginPage.loginBtn=xpath>//a[@id='dologin'] 7 | [126mail_homePage] 8 | homePage.addressbook=id>_mail_tabitem_1_4text 9 | [126mail_addContactPage] 10 | addContactPage.newContact=xpath>//span[text()='新建联系人'] 11 | addContactPage.newName=id>input_N 12 | addContactPage.newMail=xpath>//div[@id='iaddress_MAIL_wrap']//input[@class='nui-ipt-input'] 13 | addContactPage.newMark=xpath>//span[@class='nui-chk-text']/preceding-sibling::span/b 14 | addContactPage.newPhone=xpath>//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input'] 15 | addContactPage.newComment=id>input_DETAIL 16 | addContactPage.newCommit=xpath>//span[text()='确 定'] -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | # 存放定位元素等数据和测试对象相关的数据 -------------------------------------------------------------------------------- /config/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | import os 13 | 14 | # print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 15 | # 项目目录 16 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | CONFIG_DIR = os.path.join(ROOT_DIR, 'config') 18 | DATA_DIR = os.path.join(ROOT_DIR, 'testData') 19 | # 日志文件存放路径 20 | LOG_DIR = os.path.join(ROOT_DIR, 'log') 21 | # 错误截图路径 22 | IMAGE_DIR = os.path.join(ROOT_DIR, 'img') 23 | # init文件路径 24 | pageElementLocatorPath = os.path.join(CONFIG_DIR, 'PageElementLocator.ini') 25 | # excel文件路径 26 | testExcelValuePath = os.path.join(DATA_DIR, '126MailContact.xlsx') 27 | 28 | 29 | # 126username 表,每列对用的序号 30 | accountUserName = 2 31 | accountPassWord = 3 32 | accountDataBook = 4 33 | accountIsExecute = 5 34 | accountTestResult = 6 35 | 36 | # 126联系人表,每列对应的序号 37 | contactName = 2 38 | contactMail = 3 39 | contactStar = 4 40 | contactPhone = 5 41 | contactComment = 6 42 | contactKeyWords = 7 43 | contactIsExecute = 8 44 | contactExecuteTime = 9 45 | contactTestResult = 10 46 | 47 | 48 | if __name__ == '__main__': 49 | print(pageElementLocatorPath) 50 | print(testExcelValuePath) 51 | print(LOG_DIR) 52 | -------------------------------------------------------------------------------- /img/2019-08-03/22_52_27yyy-yyyy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/img/2019-08-03/22_52_27yyy-yyyy.png -------------------------------------------------------------------------------- /img/2019-08-03/23_24_42yyy-yyyy失败.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/img/2019-08-03/23_24_42yyy-yyyy失败.png -------------------------------------------------------------------------------- /img/2019-08-03/23_29_36yyy-yyyy失败.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/img/2019-08-03/23_29_36yyy-yyyy失败.png -------------------------------------------------------------------------------- /img/2019-08-03/23_41_57yyy-yyyy失败.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/img/2019-08-03/23_41_57yyy-yyyy失败.png -------------------------------------------------------------------------------- /img/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:55 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 | @QQ : 28174043@qq.com 9 | @GROUP: 878565760 10 | ------------------------------------ 11 | """ -------------------------------------------------------------------------------- /log/__init__.py: -------------------------------------------------------------------------------- 1 | # 存放日志文件 2 | -------------------------------------------------------------------------------- /log/log2019-03-21.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/log/log2019-03-21.txt -------------------------------------------------------------------------------- /log/log2019-08-03.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/log/log2019-08-03.txt -------------------------------------------------------------------------------- /pages/HomePage.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from pages.base import Base 13 | from util.ParseConfig import ParseConfigFile as DoConf 14 | 15 | 16 | class HomePage(Base): 17 | 18 | cf = DoConf() 19 | 20 | @property 21 | def address_link(self): 22 | """通讯录菜单对象""" 23 | by, locator = self.cf.get_element_value('126mail_homePage', 'homePage.addressbook') 24 | element = self.get_element(by, locator) 25 | return element 26 | 27 | 28 | if __name__ == '__main__': 29 | pass 30 | -------------------------------------------------------------------------------- /pages/LoginPage.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from pages.base import Base 13 | from util.ParseConfig import ParseConfigFile as DoConf 14 | 15 | 16 | class LoginPage(Base): 17 | """登录页面所有的操作元素对象""" 18 | 19 | cf = DoConf() 20 | 21 | @property 22 | def click_password_login_btn(self): 23 | by, locator = self.cf.get_element_value('126mail_login', 'loginPage.passWordLoginBtn') 24 | password_login_btn = self.get_element(by, locator) 25 | return password_login_btn 26 | 27 | def switch_to_frame(self): 28 | """切换frame""" 29 | by, locator = self.cf.get_element_value('126mail_login', 'loginPage.frame') 30 | try: 31 | self.switch_frame(by, locator) 32 | except Exception as e: 33 | raise e 34 | 35 | def switch_to_default_frame(self): 36 | """跳出frame""" 37 | try: 38 | self.switch_to_default() 39 | except Exception as e: 40 | raise e 41 | 42 | @property 43 | def user_name_element(self): # 用户名输入框 44 | by, locator = self.cf.get_element_value('126mail_login', 'loginPage.username') 45 | username = self.get_element(by, locator) 46 | return username 47 | 48 | @property 49 | def password_element(self): # 密码输入框 50 | by, locator = self.cf.get_element_value('126mail_login', 'loginPage.password') 51 | password = self.get_element(by, locator) 52 | return password 53 | 54 | @property 55 | def login_btn_element(self): # 登录按钮 56 | by, locator = self.cf.get_element_value('126mail_login', 'loginPage.loginBtn') 57 | login_btn = self.get_element(by, locator) 58 | return login_btn 59 | 60 | 61 | if __name__ == '__main__': 62 | pass 63 | -------------------------------------------------------------------------------- /pages/NewContactPage.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from selenium.webdriver.support.wait import WebDriverWait 13 | from selenium.webdriver.support import expected_conditions as ec 14 | from selenium.common.exceptions import TimeoutException 15 | 16 | from util.ParseConfig import ParseConfigFile as DoConf 17 | from pages.base import Base 18 | 19 | 20 | class AddContactPage(Base): 21 | """添加联系人页面所有操作元素对象""" 22 | cf = DoConf() 23 | 24 | @property 25 | def wait_new_contact_visibility(self): 26 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newContact') 27 | try: 28 | return WebDriverWait(self.driver, 30).until(ec.element_to_be_clickable((by, locator))) 29 | except TimeoutException: 30 | print("新键联系人按钮不可以点击或者没有找到") 31 | 32 | @property 33 | def new_contact(self): # 新建联系人 34 | # by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newContact') 35 | element = self.wait_new_contact_visibility 36 | return element 37 | 38 | @property 39 | def add_name(self): # 姓名输入框 40 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newName') 41 | element = self.get_element(by, locator) 42 | return element 43 | 44 | @property 45 | def add_mail(self): # 电子邮件输入框 46 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newMail') 47 | element = self.get_element(by, locator) 48 | return element 49 | 50 | @property 51 | def mark_star(self): # 设为星际联系人 52 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newMark') 53 | element = self.get_element(by, locator) 54 | return element 55 | 56 | @property 57 | def add_phone(self): # 手机号码输入框 58 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newPhone') 59 | element = self.get_element(by, locator) 60 | return element 61 | 62 | @property 63 | def add_content(self): # 备注 64 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newComment') 65 | element = self.get_element(by, locator) 66 | return element 67 | 68 | @property 69 | def click_commit_btn(self): # 确定按钮 70 | by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newCommit') 71 | element = self.get_element(by, locator) 72 | return element 73 | 74 | 75 | if __name__ == '__main__': 76 | pass 77 | -------------------------------------------------------------------------------- /pages/__init__.py: -------------------------------------------------------------------------------- 1 | # 用于实现被测试对象的页面对象 -------------------------------------------------------------------------------- /pages/base.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from selenium.webdriver.support.wait import WebDriverWait 13 | 14 | from util.GetDateTime import DateTime as DataTime 15 | 16 | 17 | class Base(object): 18 | 19 | def __init__(self, driver): 20 | self.driver = driver 21 | self.driver.implicitly_wait(30) 22 | self.url = 'https://mail.126.com' 23 | 24 | def open_url(self): 25 | return self.driver.get(self.url) 26 | 27 | def delete_cookies(self): 28 | return self.driver.delete_all_cookies() 29 | 30 | def get_element(self, by, locate): 31 | """ 32 | 查找单一个元素 33 | :param by: 定位方式,id, name, class, xpath... 34 | :param locate: 定位表达式 35 | :return: 元素 36 | """ 37 | try: 38 | element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element(by, locate)) 39 | except Exception as e: 40 | raise e 41 | else: 42 | return element 43 | 44 | def get_elements(self, by, locate): 45 | """ 46 | 查找一组元素 47 | :param by: 定位方式 48 | :param locate: 定位表达式 49 | :return: 一组元祖组成的列表 50 | """ 51 | try: 52 | elements = WebDriverWait(self.driver, 30).until(lambda x: x.find_elements(by, locate)) 53 | except Exception as e: 54 | raise e 55 | else: 56 | return elements 57 | 58 | def save_screen_shot(self, string): 59 | picture_name = \ 60 | DataTime.create_picture_path() + '\\' + DataTime.get_current_time() + string + '.png' 61 | try: 62 | self.driver.get_screenshot_as_file(picture_name) 63 | except Exception as e: 64 | raise e 65 | else: 66 | return picture_name 67 | 68 | def switch_frame(self, by, locator): 69 | iframe = self.get_element(by, locator) 70 | return self.driver.switch_to.frame(iframe) 71 | 72 | def switch_to_default(self): 73 | self.driver.switch_to.default_content() 74 | 75 | def quit(self): 76 | return self.driver.quit() 77 | 78 | 79 | if __name__ == '__main__': 80 | pass 81 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | et-xmlfile==1.0.1 2 | jdcal==1.4.1 3 | openpyxl==2.6.2 4 | selenium==3.141.0 5 | urllib3==1.25.3 6 | -------------------------------------------------------------------------------- /testCases/TestMail126.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | import time 13 | import logging 14 | import traceback 15 | from selenium import webdriver 16 | 17 | from bussines.LoginAction import LoginAction as LoginAction 18 | from bussines.AddContact import NewContactPersonAction as NewAction 19 | from config.config import ( 20 | accountIsExecute as accountIsExecute, 21 | accountUserName as accountUserName, 22 | accountPassWord as accountPassWord, 23 | accountDataBook as accountDataBook, 24 | accountTestResult as accountTestResult, 25 | contactIsExecute as contactIsExecute, 26 | contactName as contactName, 27 | contactMail as contactMail, 28 | contactStar as contactStar, 29 | contactPhone as contactPhone, 30 | contactComment as contactComment, 31 | contactKeyWords as contactKeyWords, 32 | contactTestResult as contactTestResult 33 | ) 34 | from util.ParseExcel import ParseExcel 35 | from util.RecordLog import Logger 36 | from pages.base import Base 37 | 38 | 39 | log = Logger(__name__, logging.INFO) 40 | do_excel = ParseExcel() 41 | sheetName = do_excel.wb.sheetnames # 获取所有的sheetname 是个列表 42 | 43 | 44 | def test_mail_login(): 45 | """测试用例""" 46 | driver = webdriver.Firefox() 47 | base = Base(driver) 48 | base.open_url() 49 | login_action = LoginAction(driver) 50 | add_contact = NewAction(driver) 51 | # 是否执行列数据 52 | is_execute = do_excel.get_column_value(sheetName[0], accountIsExecute) 53 | data_book = do_excel.get_column_value(sheetName[0], accountDataBook) 54 | for idx, value in enumerate(is_execute[:]): 55 | # print(idx, value) # 获取是否执行列数据列表的索引和数据 56 | if value.lower() == 'y': 57 | user_row_value = do_excel.get_row_value(sheetName[0], idx + 2) # 获取执行状态为y所在行的数据 58 | user_name = user_row_value[accountUserName - 2] 59 | pass_word = user_row_value[accountPassWord - 2] 60 | # 登录 61 | login_action.click_password_login() 62 | login_action.login(user_name, pass_word) 63 | time.sleep(10) # 足够的时间加载登录成功的页面 64 | try: 65 | assert '通讯录' in driver.page_source 66 | except Exception: 67 | base.save_screen_shot(user_name + '-' + pass_word + '失败') 68 | log.logger.info('登录失败,输出信息如下:{}'.format(traceback.format_exc())) 69 | do_excel.write_cell(sheetName[0], idx + 2, accountTestResult, 'failed') 70 | base.delete_cookies() 71 | base.open_url() 72 | else: 73 | log.logger.info('账号:{}登录成功, 测试通过'.format(user_name)) 74 | do_excel.write_cell(sheetName[0], idx + 2, accountTestResult, 'pass') 75 | # 获取联系人数据表中是否执行列的数据 76 | if data_book[idx] == sheetName[1]: 77 | is_execute = do_excel.get_column_value(sheetName[1], contactIsExecute) 78 | for index, data in enumerate(is_execute): 79 | if data.lower() == 'y': 80 | # 获取y表示行的数据 81 | contact_person_value = \ 82 | do_excel.get_row_value(sheetName[1], index + 2) 83 | # 获取添加联系人所需的数据 84 | # 联系人姓名 85 | contact_person_name = \ 86 | contact_person_value[contactName - 2] 87 | # 联系人邮箱 88 | contact_person_mail = \ 89 | contact_person_value[contactMail - 2] 90 | # 是否为星级联系人 91 | contact_person_star = \ 92 | contact_person_value[contactStar - 2] 93 | # 联系人手机号 94 | contact_person_phone = \ 95 | contact_person_value[contactPhone - 2] 96 | # 联系人备注 97 | contact_person_comment = \ 98 | contact_person_value[contactComment - 2] 99 | # 验证页面包含的关键字 100 | contact_assert = \ 101 | contact_person_value[contactKeyWords - 2] 102 | add_contact.address_link() 103 | add_contact.add_contact( 104 | contact_person_name, 105 | contact_person_mail, 106 | contact_person_star, 107 | contact_person_phone, 108 | contact_person_comment 109 | ) 110 | try: 111 | assert contact_assert in driver.page_source 112 | except Exception: 113 | base.save_screen_shot('添加联系人失败') 114 | do_excel.write_cell(sheetName[1], index + 2, contactTestResult, 'fail') 115 | else: 116 | do_excel.write_cell(sheetName[1], index + 2, contactTestResult, 'pass') 117 | # 设置足够长的时间 让添加联系人成功后的提示框自动消失,当然可以自己写代码关闭 118 | time.sleep(10) 119 | base.delete_cookies() 120 | base.open_url() 121 | else: 122 | base.delete_cookies() 123 | base.open_url() 124 | base.quit() 125 | 126 | 127 | if __name__ == '__main__': 128 | pass 129 | -------------------------------------------------------------------------------- /testCases/__init__.py: -------------------------------------------------------------------------------- 1 | # 测试用例脚本目录 -------------------------------------------------------------------------------- /testData/126MailContact.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13691579846/DataDriverTestFrameWork/97687cd9eee11482243f1389f24b0f7b6e7c4aed/testData/126MailContact.xlsx -------------------------------------------------------------------------------- /testData/__init__.py: -------------------------------------------------------------------------------- 1 | # 存放测试所需要的数据文件 -------------------------------------------------------------------------------- /util/GetDateTime.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | import os 13 | from datetime import datetime, date 14 | 15 | from config.config import IMAGE_DIR as IMG 16 | 17 | 18 | class DateTime(object): 19 | 20 | @staticmethod 21 | def get_current_date(): 22 | """获取当前日期""" 23 | try: 24 | current_date = date.today() 25 | except Exception as e: 26 | raise e 27 | else: 28 | return str(current_date) 29 | 30 | @staticmethod 31 | def get_current_time(): 32 | """获取当前时间""" 33 | try: 34 | time = datetime.now() 35 | current_time = time.strftime('%H_%M_%S') 36 | except Exception as e: 37 | raise e 38 | else: 39 | return current_time 40 | 41 | @staticmethod 42 | def create_picture_path(): 43 | """创建图片存放路径路径""" 44 | try: 45 | picture_path = os.path.join(IMG, DateTime.get_current_date()) 46 | if not os.path.exists(picture_path): 47 | os.makedirs(picture_path) # 生成多级目录 48 | except Exception as e: 49 | raise e 50 | else: 51 | return picture_path 52 | 53 | 54 | if __name__ == '__main__': 55 | print(DateTime.get_current_date()) 56 | print(DateTime.get_current_time()) 57 | print(DateTime.create_picture_path()) 58 | -------------------------------------------------------------------------------- /util/ParseConfig.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from config.config import pageElementLocatorPath as UiObjectLibrary 13 | import configparser 14 | 15 | 16 | class ParseConfigFile(object): 17 | """解析ini配置文件""" 18 | 19 | def __init__(self): 20 | try: 21 | self.cf = configparser.ConfigParser() # 获取配置文件对象 22 | self.cf.read(UiObjectLibrary, encoding='utf-8') # 加载配置文件到内存中 23 | except Exception as e: 24 | raise e 25 | 26 | def get_items_section(self, section_name): 27 | """ 28 | 获取section下面所有section的键值 29 | :param section_name: 30 | :return: 31 | """ 32 | try: 33 | values = dict(self.cf.items(section_name)) 34 | except Exception as e: 35 | raise e 36 | else: 37 | return values 38 | 39 | def get_element_value(self, section_name, option_name): 40 | try: 41 | locator = self.cf.get(section_name, option_name).split('>') 42 | except Exception as e: 43 | raise e 44 | else: 45 | return locator # 获取option键对应的value 46 | 47 | def get_all_sections(self): 48 | try: 49 | all_sections = self.cf.sections() 50 | except Exception as e: 51 | raise e 52 | else: 53 | return all_sections # 所有的sections返回值是个列表 54 | 55 | def get_all_options(self, section): 56 | try: 57 | options = self.cf.options(section) 58 | except Exception as e: 59 | raise e 60 | else: 61 | return options # 某个section下面的键 62 | 63 | 64 | if __name__ == '__main__': 65 | cf = ParseConfigFile() 66 | location = cf.get_element_value('126mail_login', 'loginPage.username') 67 | print(cf.get_items_section('126mail_login')) 68 | print(cf.get_all_sections()) 69 | print(cf.get_all_options('126mail_addContactPage')) 70 | -------------------------------------------------------------------------------- /util/ParseExcel.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | from openpyxl import load_workbook 13 | 14 | from config.config import testExcelValuePath as DataPath 15 | 16 | 17 | class ParseExcel(object): 18 | """解析excel文件""" 19 | def __init__(self): 20 | self.data_path = DataPath 21 | self.wb = load_workbook(self.data_path) 22 | 23 | def get_row_value(self, sheet_name, raw_no): 24 | """获取某一行的数据""" 25 | sh = self.wb[sheet_name] 26 | row_value_list = [] 27 | for y in range(2, sh.max_column + 1): 28 | value = sh.cell(raw_no, y).value 29 | row_value_list.append(value) 30 | return row_value_list 31 | 32 | def get_column_value(self, sheet_name, col_no): 33 | """获取某一列的数据""" 34 | sh = self.wb[sheet_name] 35 | col_value_list = [] 36 | for x in range(2, sh.max_row + 1): 37 | value = sh.cell(x, col_no).value 38 | col_value_list.append(value) 39 | return col_value_list 40 | 41 | def get_cell_value(self, sheet_name, raw_no, col_no): 42 | """获取某一个单元格的数据""" 43 | sh = self.wb[sheet_name] 44 | value = sh.cell(raw_no, col_no).value 45 | return value 46 | 47 | def write_cell(self, sheet_name, raw_no, col_no, value): 48 | """向某个单元格写入数据""" 49 | sh = self.wb[sheet_name] 50 | sh.cell(raw_no, col_no).value = value 51 | self.wb.save(self.data_path) 52 | 53 | 54 | if __name__ == '__main__': 55 | p = ParseExcel() 56 | print(p.get_row_value('126account', 2)) 57 | print(p.get_column_value('126account', 3)) 58 | print(p.get_cell_value('126account', 2, 3)) 59 | -------------------------------------------------------------------------------- /util/RecordLog.py: -------------------------------------------------------------------------------- 1 | """ 2 | ------------------------------------ 3 | @Time : 2019/8/3 21:59 4 | @Auth : linux超 5 | @File : GetDateTime.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 | import logging 13 | import time 14 | 15 | from config.config import LOG_DIR 16 | 17 | 18 | class Logger(object): 19 | """封装的日志模块""" 20 | def __init__(self, logger, file_level=logging.INFO): 21 | """ 22 | :param logger: logger名 23 | :param file_level: 文件级别 24 | """ 25 | self.logger = logging.getLogger(logger) 26 | self.logger.setLevel(logging.DEBUG) # 设置日志输出的默认级别 27 | # 日志输出格式 28 | fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s') 29 | # 日志文件名称 30 | curr_time = time.strftime("%Y-%m-%d") 31 | self.LogFileName = LOG_DIR + r'/' + 'log' + curr_time + '.txt' 32 | # 设置文件输出 33 | fh = logging.FileHandler(self.LogFileName) 34 | fh.setFormatter(fmt) 35 | fh.setLevel(file_level) # 日志级别 36 | self.logger.addHandler(fh) 37 | 38 | 39 | if __name__ == '__main__': 40 | log = Logger("fox", file_level=logging.DEBUG) 41 | log.logger.debug("debug") 42 | log.logger.log(logging.ERROR, '%(module)s %(info)s', {'module': 'log日志', 'info': 'error'}) 43 | -------------------------------------------------------------------------------- /util/__init__.py: -------------------------------------------------------------------------------- 1 | # 实现测试过程中调用的工具类方法, 例如读取配置文件,页面元素的操作方法, 解析excel文件 --------------------------------------------------------------------------------