python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))

【python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))】一.前言
1.数据驱动自动化测试,会不会有这样的疑问:数据怎么管理?数据怎么才能驱动测试用例执行?到底怎么样才算数据驱动?
二.项目介绍
地址:https://www.126.com/
1.实现126邮箱登录功能的验证
2.实现126邮箱添加新联系人功能的验证
python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))
文章图片

python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))
文章图片

三.目录结构
python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))
文章图片

四.项目源码
1.新建config目录存放和业务无关的数据文件。
1.1.比如PageElementLocator.ini用来存放每个页面的定位元素表达式。
PageElementLocator.ini

[126mail_login] loginPage.frame=xpath>//div[@id='loginDiv']/iframe loginPage.username=xpath>//input[@name='email'] loginPage.password=xpath>//input[@name='password'] loginPage.loginBtn=xpath>//a[@id='dologin'] [126mail_homePage] homePage.addressbook=id>_mail_tabitem_1_4text [126mail_addContactPage] addContactPage.newContact=xpath>//span[text()='新建联系人'] addContactPage.newName=id>input_N addContactPage.newMail=xpath>//div[@id='iaddress_MAIL_wrap']//input[@class='nui-ipt-input'] addContactPage.newMark=xpath>//span[@class='nui-chk-text']/preceding-sibling::span/b addContactPage.newPhone=xpath>//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input'] addContactPage.newComment=id>input_DETAIL addContactPage.newCommit=xpath>//span[text()='确 定']

2.有了上面元素的表达式,又该如何查找元素呢?这时候需要封装一套无论何种定位方式都可以使用的通用的查找方法。
2.1.新建pages目录(pages目录主要存放和业务无关的公共方法及PO页面类方法),此目录下新建base.py文件作为基类,供其他PO页面类和用例继承调用使用。
base.py
# 基类:供所有页面的页面类及用例继承使用 from selenium.webdriver.support.wait import WebDriverWait from util.GetDateTime import DateTime as DataTimeclass Base(object): # 定义浏览器驱动,前置条件,url等操作 def __init__(self, driver): self.driver = driver self.driver.implicitly_wait(30) self.url = 'https://mail.126.com'def open_url(self): return self.driver.get(self.url)def delete_cookies(self): # 清空删除所有登录过的cookies,为了后续能正常登录(如果不清楚就会造成免登陆,因为登录过一次,有cookies) return self.driver.delete_all_cookies()def get_element(self, by, locate): """ 查找单一个元素 :param by: 定位方式,id, name, class, xpath... :param locate: 定位表达式 :return: 元素 """ try: element = WebDriverWait(self.driver, 30).until(lambda x: x.find_element(by, locate)) except Exception as e: raise e else: return elementdef get_elements(self, by, locate): """ 查找一组元素 :param by: 定位方式 :param locate: 定位表达式 :return: 一组元祖组成的列表 """ try: elements = WebDriverWait(self.driver, 30).until(lambda x: x.find_elements(by, locate)) except Exception as e: raise e else: return elementsdef save_screen_shot(self, string): ''' 获取截图并保存 :param string: 字符串 :return: 截图名称地址 ''' # 调用DataTime类中的create_picture_path方法和get_current_time方法 picture_name = \ DataTime.create_picture_path() + '\\' + DataTime.get_current_time() + string + '.png' try: self.driver.get_screenshot_as_file(picture_name) except Exception as e: raise e else: return picture_namedef switch_frame(self, by, locator): ''' 切换iframe框架 :param by: 定位方式 :param locator: 定位表达式 :return: 切换的iframe ''' iframe = self.get_element(by, locator) return self.driver.switch_to.frame(iframe)def switch_to_default(self): ''' 从iframe框架切回原来框架 :return: ''' self.driver.switch_to.default_content()def quit(self): return self.driver.quit()if __name__ == '__main__': pass

3.定位表达式有了,查找元素的方法封装好了,下面需要解析配置文件,获取配置文件中需要的定位方式和定位表达式。
3.1.在新建util目录(util目录主要存放和业务无关的公共方法)下,新建ParseConfig.py文件用来解析配置文件。
ParseConfig.py
# 封装解析配置文件方法 from config.config import pageElementLocatorPath as UiObjectLibrary import configparserclass ParseConfigFile(object): """解析ini配置文件"""def __init__(self): try: # 获取配置文件对象 self.cf = configparser.ConfigParser() # 加载配置文件到内存中 self.cf.read(UiObjectLibrary, encoding='utf-8') except Exception as e: raise edef get_items_section(self, section_name): """ 获取指定section下面所有section的键值values :param section_name: :return: """ try: # 遍历ini配置文件中所有的section_name值 values = dict(self.cf.items(section_name)) except Exception as e: raise e else: return valuesdef get_element_value(self, section_name, option_name): ''' 切割指定的section_name和option_name,从而获取对应的值 :param section_name: :param option_name: :return: ''' try: locator = self.cf.get(section_name, option_name).split('>') except Exception as e: raise e else: # 获取option键对应的value return locatordef get_all_sections(self): ''' 获取所有sections值并返回列表输出 :return: ''' try: all_sections = self.cf.sections() except Exception as e: raise e else: # 所有的sections返回值是个列表 return all_sectionsdef get_all_options(self, section): ''' 获取指定的section,输出section指定对应所有的options值 :param section: :return: ''' try: options = self.cf.options(section) except Exception as e: raise e else: # 某个section下面的键 return optionsif __name__ == '__main__': # 类额实例化ParseConfigFile cf = ParseConfigFile()''' # 获取指定section下面所有section的键值values get_items_section_one = cf.get_items_section('126mail_login') get_items_section_two = cf.get_items_section('126mail_homePage') get_items_section_three = cf.get_items_section('126mail_addContactPage') print(get_items_section_one) print(get_items_section_two) print(get_items_section_three) '''# 切割指定的section_name和option_name,从而获取对应的值 location = cf.get_element_value('126mail_login', 'loginPage.username') #location1 = cf.get_element_value('126mail_homePage', 'homePage.addressbook') #location2 = cf.get_element_value('126mail_addContactPage', 'addContactPage.newContact') print(location) #print(location1) #print(location2)print(cf.get_items_section('126mail_login')) # 获取所有sections值并返回列表输出 print(cf.get_all_sections()) # 获取指定的section,输出section指定对应所有的options值 print(cf.get_all_options('126mail_addContactPage'))

4.已经可以获取到了每一个元素的定位方式和定位表达式,接下来又该如何查找到元素对象呢?这时候会想到PO设计模式,把每一个page页面的元素保存到对应页面的文件中。
4.1.新建pages目录,在此目录下分别创建HomePage.py LoginPage.py NewContact.py 三个页面文件。
4.2.LoginPage.py存放登录页面所需要的元素。
# PO模式登陆页面类 from pages.base import Base from util.ParseConfig import ParseConfigFile as DoConfclass LoginPage(Base): """登录页面所有的操作元素对象""" # 调用ParseConfigFile类进行实例化 cf = DoConf()''' @property def click_password_login_btn(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_login', 'loginPage.passWordLoginBtn') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中get_element方法 password_login_btn = self.get_element(by, locator) return password_login_btn '''def switch_to_frame(self): """切换frame""" # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_login', 'loginPage.frame') try: # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中switch_frame方法 self.switch_frame(by, locator) except Exception as e: raise edef switch_to_default_frame(self): """跳出frame""" try: # 调用基类base中switch_to_default方法 self.switch_to_default() except Exception as e: raise e@property # 用户名输入框 def user_name_element(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_login', 'loginPage.username') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中get_element方法 username = self.get_element(by, locator) return username@property # 密码输入框 def password_element(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_login', 'loginPage.password') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中get_element方法 password = self.get_element(by, locator) return password@property # 登录按钮 def login_btn_element(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_login', 'loginPage.loginBtn') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中get_element方法 login_btn = self.get_element(by, locator) return login_btnif __name__ == '__main__': pass

4.3.HomePage.py存放登录成功后首页所需要的元素。
# PO模式登录成功后首页页面类 from pages.base import Base from util.ParseConfig import ParseConfigFile as DoConfclass HomePage(Base): # 调用ParseConfigFile类进行实例化 cf = DoConf()@property def address_link(self): """通讯录菜单对象""" # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_homePage', 'homePage.addressbook') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中get_element方法 element = self.get_element(by, locator) return elementif __name__ == '__main__': pass

4.4.NewContactPage.py存放添加联系人页面所需要的元素。
# PO模式添加联系人页面类 from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as ec from selenium.common.exceptions import TimeoutException from util.ParseConfig import ParseConfigFile as DoConf from pages.base import Baseclass AddContactPage(Base): """添加联系人页面所有操作元素对象""" # 调用ParseConfigFile类进行实例化 cf = DoConf()@property def wait_new_contact_visibility(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newContact') try: # 把获取到的定位方式和定位表达式作为参数定位传入 # 显示等待每个元素的出现 return WebDriverWait(self.driver, 30).until(ec.element_to_be_clickable((by, locator))) except TimeoutException: print(u"新键联系人按钮不可以点击或者没有找到")@property # 新建联系人 def new_contact(self): # by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newContact') # 调用前面定义的方法wait_new_contact_visibility等元素出现定位操作 element = self.wait_new_contact_visibility return element@property # 姓名输入框 def add_name(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newName') element = self.get_element(by, locator) return element@property def add_mail(self):# 电子邮件输入框 # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newMail') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中的get_element方法 element = self.get_element(by, locator) return element@property # 设为星际联系人 def mark_star(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newMark') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中的get_element方法 element = self.get_element(by, locator) return element@property # 手机号码输入框 def add_phone(self): # 调用ParseConfigFile类中的get_element_value # 把获取到的定位方式和定位表达式作为参数定位传入 by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newPhone') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中的get_element方法 element = self.get_element(by, locator) return element@property # 备注 def add_content(self): # 调用ParseConfigFile类中的get_element_value # 把获取到的定位方式和定位表达式作为参数定位传入 by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newComment') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中的get_element方法 element = self.get_element(by, locator) return element@property # 确定按钮 def click_commit_btn(self): # 调用ParseConfigFile类中的get_element_value by, locator = self.cf.get_element_value('126mail_addContactPage', 'addContactPage.newCommit') # 把获取到的定位方式和定位表达式作为参数定位传入 # 调用基类base中的get_element方法 element = self.get_element(by, locator) return elementif __name__ == '__main__': pass

5.接下来考虑,框架需要数据驱动?那么该怎么用数据驱动测试呢?是不是应该通过修改测试数据能够控制用例的执行还是不执行呢?没错,大概就是这个样子,那又该如何来设计数据呢?大概最好的办法就是使用excel文件来存储或者如果有能力可以考虑使用数据库来存储,看下表格是什么样子。
5.1.新建testData目录(存放测试过程中所有和业务数据相关的数据文件),并新建126MailContact.xlsx 文件。文件中分两个sheet:126account 和126contact分别存放登录和联系人数据。
python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))
文章图片

python|第二十九(如何搭建数据驱动自动化测试框架(粗糙))
文章图片

6.通过上面的表可以看到两列数据“是否执行”,没错就是通过这来控制数据是否驱动用例执行的,用例执行后写入测试是否通过和测试执行时间(代码中没加写入时间,感兴趣的自己在用例只加就行了)。
7.有了这些数据,又该如何读取到这些数据应用到用例中呢?
7.1.在util目录下新建ParseExcel.py用来解析excel文件。
ParseExcel.py
# 读取和解析excel文件 from openpyxl import load_workbook from config.config import testExcelValuePath as DataPathclass ParseExcel(object): """解析excel文件"""def __init__(self): # 调用testExcelValuePath进行类的实例化 self.data_path = DataPath self.wb = load_workbook(self.data_path)def get_row_value(self, sheet_name, raw_no): """获取某一行的数据""" # 根据页签名sheet获取对应页面数据 sh = self.wb[sheet_name] # 定义获取一组行为空列表数据 row_value_list = [] # 根据指定行数遍历获取一行数据 for y in range(2, sh.max_column + 1): value = https://www.it610.com/article/sh.cell(raw_no, y).value row_value_list.append(value) return row_value_listdef get_column_value(self, sheet_name, col_no):"""获取某一列的数据""" # 根据页签名sheet获取对应页面数据 sh = self.wb[sheet_name] # 定义获取一组列为空列表数据 col_value_list = [] # 根据指定列数遍历获取一列数据 for x in range(2, sh.max_row + 1): value = https://www.it610.com/article/sh.cell(x, col_no).value col_value_list.append(value) return col_value_listdef get_cell_value(self, sheet_name, raw_no, col_no):"""获取某一个单元格的数据""" # 根据页签名sheet获取对应页面数据 sh = self.wb[sheet_name] # 根据指定行和列数获取单元格数据 value = https://www.it610.com/article/sh.cell(raw_no, col_no).value return valuedef write_cell(self, sheet_name, raw_no, col_no, value):"""向某个单元格写入数据""" # 根据页签名sheet获取对应页面数据 sh = self.wb[sheet_name] # 根据指定行和列数,变更对应的单元格数据(输写入数据) sh.cell(raw_no, col_no).value = https://www.it610.com/article/value self.wb.save(self.data_path)if __name__ =='__main__': # 类的实例化ParseExcel p = ParseExcel()print(p.get_row_value('126account', 2)) print(p.get_column_value('126account', 3)) print(p.get_cell_value('126account', 2, 3))

8.在config目录下新建config.py文件来存储一些目录信息和数据表对应的列号。
config.py
import os#print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 项目目录 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))# 配置文件读取路径 CONFIG_DIR = os.path.join(ROOT_DIR, 'config')# 测试数据路径 DATA_DIR = os.path.join(ROOT_DIR, 'testData')# 日志文件存放路径 LOG_DIR = os.path.join(ROOT_DIR, 'log')# 错误截图路径 IMAGE_DIR = os.path.join(ROOT_DIR, 'img')# 配置文件读取路径:读取init文件路径 pageElementLocatorPath = os.path.join(CONFIG_DIR, 'PageElementLocator.ini')# 测试数据路径:读取excel文件路径 testExcelValuePath = os.path.join(DATA_DIR, '126MailContact.xlsx')# 126username表,每列对用的序号 accountUserName = 2 accountPassWord = 3 accountDataBook = 4 accountIsExecute = 5 accountTestResult = 6# 126联系人表,每列对应的序号 contactName = 2 contactMail = 3 contactStar = 4 contactPhone = 5 contactComment = 6 contactKeyWords = 7 contactIsExecute = 8 contactExecuteTime = 9 contactTestResult = 10if __name__ == '__main__': print(ROOT_DIR) print(CONFIG_DIR) print(DATA_DIR) print(LOG_DIR) print(IMAGE_DIR) print(pageElementLocatorPath) print(testExcelValuePath)

9.所有的数据已经准备完全,可以编写用例了吧?等等! 是不是要考虑把业务功能封装一下呢?这样也方便以后依赖这些功能的用例直接调用!
9.1.新建目录bussines此目录用来存放业务功能代码,目录下新建LoginAction.py和AddContact.py文件。
LoginAction.py
# 业务功能封装:方便以后依赖这些功能的用例直接调用 from pages.LoginPage import LoginPageclass LoginAction(object):def __init__(self, driver): self.driver = driver # 调用LoginPage类进行实例化 self.login_page = LoginPage(self.driver)''' def click_password_login(self): # 调用LoginPage类中click_password_login_btn方法,并点击操作 self.login_page.click_password_login_btn.click() '''def login(self, username, password): """登录场景""" # 调用LoginPage类中switch_to_frame方法 self.login_page.switch_to_frame() # 调用LoginPage类中user_name_element方法,并输入操作 self.login_page.user_name_element.send_keys(username) # 调用LoginPage类中password_element方法,并输入操作 self.login_page.password_element.send_keys(password) # 调用LoginPage类中login_btn_element方法,并点击操作 self.login_page.login_btn_element.click() # 调用LoginPage类中switch_to_default_frame方法 self.login_page.switch_to_default_frame()if __name__ == '__main__': pass

AddContact.py
# 业务功能封装:方便以后依赖这些功能的用例直接调用 from pages.HomePage import HomePage from pages.NewContactPage import AddContactPageclass NewContactPersonAction(object):def __init__(self, driver): self.driver = driver # 调用HomePage类进行实例化 self.home_page = HomePage(self.driver) # 调用AddContactPage类进行实例化 self.new_contact_page = AddContactPage(self.driver)def address_link(self): """点击通讯录按钮""" # 调用HomePage类中的address_link方法,并点击操作 self.home_page.address_link.click()def add_contact(self, contact_name, contact_mail, is_star, contact_phone, contact_comment): """添加联系人场景""" # 点击新建联系人 # 调用AddContactPage类中new_contact方法,并点击操作 self.new_contact_page.new_contact.click() if contact_name: # 非必填项 # 调用AddContactPage类中add_name方法,并输入操作 self.new_contact_page.add_name.send_keys(contact_name) # 必填项 # 调用AddContactPage类中add_mail方法,并输入操作 self.new_contact_page.add_mail.send_keys(contact_mail) if is_star == u'是': # 调用AddContactPage类中mark_star方法,并点击操作 self.new_contact_page.mark_star.click() if contact_phone: # 调用AddContactPage类中add_phone方法,并输入操作 self.new_contact_page.add_phone.send_keys(contact_phone) if contact_comment: # 调用AddContactPage类中add_content方法,并输入操作 self.new_contact_page.add_content.send_keys(contact_comment) # 调用AddContactPage类中click_commit_btn方法,并点击操作 self.new_contact_page.click_commit_btn.click()if __name__ == '__main__': pass

10.大体框架就已经搭建完成了,貌似还少了个执行日志,在util目录下新建RecordLog.py封装日志模块, 加入到想加入的任何地方(用例中就加了几条,可以自己任意加在想加的位置)。
RecordLog.py
# 封装日志模块 import logging import time from config.config import LOG_DIRclass Logger(object): """封装的日志模块""" def __init__(self, logger, file_level=logging.INFO): """ :param logger: logger名 :param file_level: 文件级别 """ self.logger = logging.getLogger(logger)# 设置日志输出的默认级别 self.logger.setLevel(logging.DEBUG)# 日志输出格式 fmt = logging.Formatter('%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s')# 日志文件名称 #self.LogFileName = os.path.join(conf.log_path, "{0}.log.txt".format(time.strftime("%Y-%m-%d")))# %H_%M_%S curr_time = time.strftime("%Y-%m-%d") self.LogFileName = LOG_DIR + r'/' + 'log' + curr_time + '.txt'# 设置控制台输出 #sh = logging.StreamHandler() #sh.setFormatter(fmt) # 日志级别 #sh.setLevel(CmdLevel)# 设置文件输出 fh = logging.FileHandler(self.LogFileName) fh.setFormatter(fmt) # 日志级别 fh.setLevel(file_level)#self.logger.addHandler(sh) self.logger.addHandler(fh)if __name__ == '__main__': log = Logger("fox", file_level=logging.DEBUG) log.logger.debug("debug") #ERROR,log日志 error log.logger.log(logging.ERROR, '%(module)s %(info)s', {'module': u'log日志', 'info': 'error'})

11.框架就算已经搭建完成了,接下来就是编写测试用例。
11.1.新建testCases目录存放测试用例,并新建TestMail126.py编写用例。
TestMail126.py
# 编写测试用例 import time import logging # traceback打印出报错异常信息的位置:直观的知道在哪个文件中的哪一行出错 import traceback from selenium import webdriver from util.RecordLog import Logger from pages.base import Base from bussines.LoginAction import LoginAction as LoginAction from bussines.AddContact import NewContactPersonAction as NewAction from config.config import ( accountUserName as accountUserName, accountPassWord as accountPassWord, accountDataBook as accountDataBook, accountIsExecute as accountIsExecute, accountTestResult as accountTestResult, contactIsExecute as contactIsExecute, contactName as contactName, contactMail as contactMail, contactStar as contactStar, contactPhone as contactPhone, contactComment as contactComment, contactKeyWords as contactKeyWords, contactExecuteTime as contactExecuteTime, contactTestResult as contactTestResult ) from util.ParseExcel import ParseExcellog = Logger(__name__, logging.INFO) # 调用ParseExcel类实例化 do_excel = ParseExcel() # 获取所有的sheetname是个列表输出 sheetName = do_excel.wb.sheetnames print(sheetName)def test_mail_login(): """测试用例""" driver = webdriver.Chrome() driver.maximize_window() # 调用基类Base实例化 base = Base(driver) # 调用基类Base中的open_url方法 base.open_url()# 调用基类LoginAction实例化 login_action = LoginAction(driver) # 调用基类NewContactPersonAction实例化 add_contact = NewAction(driver)# 获取登录数据表是否执行列数据 # 调用ParseExcel实例化类中的get_column_value方法获取某一列 # 根据索引获取页签名 # 参数是调用config文件中定义的accountIsExecute和accountDataBook是指定义的列序号 # 列表数据输出:输出的是一整列数据 is_execute = do_excel.get_column_value(sheetName[0], accountIsExecute) print(is_execute)# 此处获取到的列表值内中,126contact是第二张表的页签名 data_book = do_excel.get_column_value(sheetName[0], accountDataBook) print(data_book)for idx, value in enumerate(is_execute[:]): # 获取前面输出的is_execute列表值,是否执行列数据列表的索引和数据(y) # ids表示返回列表值的索引,value表示返回列表值的索引对应的值 print(idx, value) # 如果前面获取的value列值等于y,执行其对应的一整行数据 if value.lower() == 'y': # 获取执行状态为y所在行的数据 # 调用ParseExcel实例化类中的get_row_value方法获取某一行 # 根据索引获取页签名 # ids表示返回列表值的索引,ids是根据is_execute定义(相加从第二行开始) user_row_value = https://www.it610.com/article/do_excel.get_row_value(sheetName[0], idx + 2) print(user_row_value)# 参数是调用config文件中定义的accountUserName和accountPassWord是指定义的列序号 # 此处获取的是前面返回的列表某行的数据user_row_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据user_row_value索引值 # 从而根据索引值获取对应的数据值value user_name = user_row_value[accountUserName - 2] print(user_name) pass_word = user_row_value[accountPassWord - 2] print(pass_word)# 登录 # 调用实例化LoginAction类中click_password_login方法 #login_action.click_password_login() # 调用实例化LoginAction类中login方法 # 参数是上面根据处理出的索引值获取的对应数据值value login_action.login(user_name, pass_word) # 足够的时间加载登录成功的页面 time.sleep(10)try: # 登录成功后,断言“通讯录”是显示源码 assert u'通讯录' in driver.page_source except Exception: # 调用基类base中save_screen_shot方法 # 参数user_name和pass_word是前面获取到的数据值 base.save_screen_shot(user_name + '-' + pass_word + u'失败') log.logger.info(u'登录失败,输出信息如下:{}'.format(traceback.format_exc()))# 调用实例化ParseExcel类中write_cell方法,写入对应单元格数据(数据变更) # ids表示返回列表值的索引,ids是根据is_execute定义(相加从第二行开始) # 参数是调用config文件中定义的accountTestResult是指定义的列序号 do_excel.write_cell(sheetName[0], idx + 2, accountTestResult, 'failed') # 调用基类base中delete_cookies方法 base.delete_cookies() # 调用基类base中open_url方法 base.open_url() else: log.logger.info(u'账号:{}登录成功, 测试通过'.format(user_name)) # 调用实例化ParseExcel类中write_cell方法,写入对应单元格数据(变更) # ids表示返回列表值的索引,ids是根据is_execute定义(相加从第二行开始) # 参数是调用config文件中定义的accountTestResult do_excel.write_cell(sheetName[0], idx + 2, accountTestResult, 'pass')# 获取联系人数据表中是否执行列的数据 # data_book是前面获取到列的数据值(data_book获取到的值126contact是第二张表的页签名) # data_book[idx]表示data_book返回的列表值的索引idx,ids是根据前面is_execute定义 if data_book[idx] == sheetName[1]: # 调用ParseExcel实例化类中的get_column_value方法获取某一列 # 根据索引获取页签名 # 参数是调用config文件中定义的contactIsExecute是指定义的列序号 # 列表数据输出:输出的是一整列数据 is_execute1 = do_excel.get_column_value(sheetName[1], contactIsExecute) print(is_execute1)for index, data in enumerate(is_execute1): # 获取前面输出的is_execute1列表值,是否执行列数据列表的索引和数据(y) # index表示返回列表值的索引,data表示返回列表值的索引对应的值 print(index, data) # 如果前面获取的列值等于y,执行其对应的一整行数据 if data.lower() == 'y': # 获取执行状态为y所在行的数据 # 调用ParseExcel实例化类中的get_row_value方法获取某一行 # 根据索引获取页签名 # index表示返回列表值的索引,index是根据is_execute1定义(相加从第二行开始) contact_person_value = https://www.it610.com/article/do_excel.get_row_value(sheetName[1], index + 2) print(contact_person_value)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactName是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 联系人姓名 contact_person_name = contact_person_value[contactName - 2] print(contact_person_name)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactMail是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 联系人邮箱 contact_person_mail = contact_person_value[contactMail - 2] print(contact_person_mail)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactStar是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 是否为星级联系人 contact_person_star = contact_person_value[contactStar - 2] print(contact_person_star)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactPhone是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 联系人手机号 contact_person_phone = contact_person_value[contactPhone - 2] print(contact_person_phone)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactComment是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 联系人备注 contact_person_comment = contact_person_value[contactComment - 2] print(contact_person_comment)# 获取添加联系人所需的数据 # 参数是调用config文件中定义的contactKeyWords是指定义的列序号 # 此处获取的是前面返回的列表某行的数据contact_person_value # 并根据定义的参数数据做处理得到相应的返回的列表某行的数据contact_person_value索引值 # 从而根据索引值获取对应的数据值 # 验证页面包含的关键字 contact_assert = contact_person_value[contactKeyWords - 2] print(contact_assert)# 调用实例化类NewContactPersonAction中的address_link方法 add_contact.address_link() # 调用实例化类NewContactPersonAction中的add_contact方法 add_contact.add_contact(contact_person_name, contact_person_mail, contact_person_star, contact_person_phone, contact_person_comment)try: # 添加联系人成功后,断言页面关键字是显示源码 assert contact_assert in driver.page_source except Exception: # 调用基类base中save_screen_shot方法 base.save_screen_shot(u'添加联系人失败')# 调用实例化ParseExcel类中write_cell方法,写入对应单元格数据(数据变更) # index表示返回列表值的索引,index是根据is_execute1定义(相加从第二行开始) # 参数是调用config文件中定义的contactTestResult是指定义的列序号 do_excel.write_cell(sheetName[1], index + 2, contactTestResult, 'fail') else: do_excel.write_cell(sheetName[1], index + 2, contactTestResult, 'pass') # 设置足够长的时间 让添加联系人成功后的提示框自动消失,当然可以自己写代码关闭 time.sleep(10) # 调用基类base中的delete_cookies方法 base.delete_cookies() # 调用基类base中的open_url方法 base.open_url() else: # 调用基类base中的delete_cookies方法 base.delete_cookies() # 调用基类base中的open_url方法 base.open_url() base.quit()if __name__ == '__main__': pass

12.用例编写完成,再来编写统一执行用例的入口文件,在项目根目录下新建RunTest.py。
RunTest.py
from testCases.TestMail126 import test_mail_loginif __name__ == '__main__': test_mail_login()

    推荐阅读