Selenium3与Python3实战 Web自动化测试框架(五)
po模型 + 数据驱动 ,完整代码
1、setting.py:
import os base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 项目首路径 codeerror_path = os.path.join(base_dir,'Image','codeerror.png') # 验证码错误图片路径 code_path = os.path.join(base_dir,'Image','code.png') # 验证码图片保存路径 config_ini_dir = os.path.join(base_dir,'setting_conf','localElement.ini') # localElement.ini 配置文件路径 report_path = os.path.join(base_dir,'report','first_case.html') # 测试报告路径 excel_default_path = os.path.join(base_dir,'ex_data','casedata.xls') # excel表默认路径 excel_keyword_path = os.path.join(base_dir,'ex_data','keyword.xls') # excel表默认路径 setting.py
2、config.py:配置文件,主要用于配送web定位元素
[RegisterElement] user_email=id>register_email user_email_error=id>register_email-error user_name=id>register_nickname user_name_error=id>register_nickname-error password=id>register_password password_error=id>register_password-error code_image=id>getcode_num code_text=id>captcha_code code_text_error=id>captcha_code-error register_button=id>register-btn
3、read.ini:读取config.py配置文件信息,获取value
from setting_conf.setting import config_ini_dir import configparser class Read_Ini(object): # 初始化 def __init__(self,node = None): if node: self.node = node else: self.node = 'RegisterElement' # 配置文件中的某个节点 self.cf = self.load_ini() def load_ini(self): # 加载文件 cf = configparser.ConfigParser() # 使用 configparser模块读取配置文件信息 cf.read(config_ini_dir) # 配置文件所在路径 return cf def get_value(self,key): # 获取配置文件中key的value值 data = self.cf.get(self.node,key) return data read.ini
4、PO模型实现,将数据、业务、操作等分类开
4.1、find_element.py:查找目标元素,定位目标位置
from util.read_ini import Read_Ini class FindElement(object): """获取元素所在位置""" def __init__(self,driver): self.driver = driver def get_element(self,key): read_ini = Read_Ini() data = read_ini.get_value(key) by,value = data.split('>') try: if by == 'id': return self.driver.find_element_by_id(value) elif by == 'name': return self.driver.find_element_by_name(value) elif by == 'className': return self.driver.find_element_by_class_name(value) elif by == 'xpath': return self.driver.find_element_by_xpath(value) else: return self.driver.find_element_by_css(value) except Exception as e: # print("find_element错误信息:",e) return None find_element.py
4.2、register_page.py :操作find_element.py,获取各目标元素位置
from base.find_element import FindElement class RegisterPage(object): """获取元素所在位置""" def __init__(self,driver): self.fd = FindElement(driver) #获取邮箱元素 def get_email_element(self): return self.fd.get_element("user_email") #获取用户名元素 def get_username_element(self): return self.fd.get_element("user_name") #获取密码元素 def get_password_element(self): return self.fd.get_element("password") #获取验证码元素 def get_code_element(self): return self.fd.get_element("code_text") #获取注册按钮元素 def get_button_element(self): return self.fd.get_element("register_button") #获取邮箱错误元素 def get_email_error_element(self): return self.fd.get_element("user_email_error") #获取用户名错误元素 def get_name_error_element(self): return self.fd.get_element("user_name_error") #获取密码错误元素 def get_password_error_element(self): return self.fd.get_element("password_error") #获取验证码错误元素 def get_code_error_element(self): return self.fd.get_element("code_text_errorr") register_page.py
4.3、register_handle.py :操作register_page.py ,获取目标位置后,输入需求数据
4.3.1、get_code_value.py:解析验证码图片,获取验证码内容
from PIL import Image from setting_conf.ShowapiRequest import ShowapiRequest import time class GetCode: """获取验证码图片,解析验证码图片并返回验证码值""" def __init__(self, driver): self.driver = driver def get_code_image(self, file_name): self.driver.save_screenshot(file_name) code_element = self.driver.find_element_by_id("getcode_num") left = code_element.location['x'] top = code_element.location['y'] right = code_element.size['width'] + left height = code_element.size['height'] + top im = Image.open(file_name) img = im.crop((left, top, right, height)) img.save(file_name) # time.sleep(1) # 解析图片获取验证码 def code_online(self, file_name): self.get_code_image(file_name) r = ShowapiRequest("http://route.showapi.com/184-4", "62626", "d61950be50dc4dbd9969f741b8e730f5") r.addBodyPara("typeId", "35") r.addBodyPara("convert_to_jpg", "0") r.addFilePara("image", file_name) # 文件上传时设置 res = r.post() # print("test:",res.text) # time.sleep(1) text = res.json()['showapi_res_body'] # print(text) try: code = text['Result'] return code except Exception as e: print('code_error:',e) return None get_code_value.py
from page.register_page import RegisterPage from util.get_code_value import GetCode class RegisterHandle(object): """打开页面后自动输入相应信息""" def __init__(self,driver): self.driver = driver self.register_p = RegisterPage(self.driver) #输入邮箱 def send_user_email(self,email): # self.loger.info("输入的邮箱值是:"+email) self.register_p.get_email_element().send_keys(email) #输入用户名 def send_user_name(self,username): # self.loger.info("输入的用户名是:"+username) self.register_p.get_username_element().send_keys(username) #输入密码 def send_user_password(self,password): # self.loger.info("输入的密码是:"+password) self.register_p.get_password_element().send_keys(password) #输入验证码 def send_user_code(self,file_name): get_code_text = GetCode(self.driver) code = get_code_text.code_online(file_name) self.register_p.get_code_element().send_keys(code) #获取文字信息 def get_user_text(self,info,user_info): try:# 容错处理 if info == 'user_email_error': text = self.register_p.get_email_error_element().text # 获取邮箱错误信息 elif info == 'user_name_error': text = self.register_p.get_name_error_element().text # 获取用户名错误信息 elif info == 'password_error': text = self.register_p.get_password_error_element().text # 获取用户密码错误信息 else: text = self.register_p.get_code_error_element().text # 获取验证码错误信息 except: text = None return text #点击注册按钮 def click_register_button(self): self.register_p.get_button_element().click() #获取注册按钮文字 def get_register_btn_text(self): """如获取不到信息,表明页面已成功跳转""" return self.register_p.get_button_element().text register_handle.py
4.4、register_business.py:
from handle.register_handle import RegisterHandle class RegisterBusiness: """测试注册页面form表单功能情况""" def __init__(self,driver): self.register_h = RegisterHandle(driver) def user_base(self,email,name,password,file_name): self.register_h.send_user_email(email) self.register_h.send_user_name(name) self.register_h.send_user_password(password) self.register_h.send_user_code(file_name) self.register_h.click_register_button() def register_succes(self): if self.register_h.get_register_btn_text() == None: # 注册成功 return True else: return False # 邮箱错误 def login_email_error(self,email,name,password,file_name): self.user_base(email,name,password,file_name) if self.register_h.get_user_text('user_email_error',"请输入有效的电子邮件地址") == None: # 没找到错误信息,说明输入格式正确,不能起到测试效果。 #print("无错误,邮箱检验不成功") return True else: return False # 数据驱动,只执行此条代码 # 邮箱、用户名、密码、验证码、错误信息定位元素、错误提示信息 def register_function(self,email,username,password,file_name,assertCode,assertText): self.user_base(email,username,password,file_name) if self.register_h.get_user_text(assertCode,assertText) == None: return True else: return False # 用户名错误 def login_name_error(self,email,name,password,file_name): self.user_base(email,name,password,file_name) if self.register_h.get_user_text('user_name_error',"字符长度必须大于等于4,一个中文字算2个字符") == None: #print("用户名检验不成功") return True else: return False # 密码错误 def login_password_error(self,email,name,password,file_name): self.user_base(email,name,password,file_name) if self.register_h.get_user_text('password_error',"最少需要输入 5 个字符") == None: #print("密码检验不成功") return True else: return False # 验证码错误 def login_code_error(self,email,name,password,file_name): self.user_base(email,name,password,file_name) if self.register_h.get_user_text('code_text_error',"验证码错误") == None: #print("验证码检验不成功") return True else: return False register_business.py
4.5、first_ddt_case.py:数据驱动
import ddt import unittest import os # import sys from selenium import webdriver from setting_conf import setting from business.register_business import RegisterBusiness from util.excel_operation import Excel_Opertion from util.HTMLTestRunner import HTMLTestRunner # sys.path.append(setting_conf.base_dir) ex_opr = Excel_Opertion() # 实例化 ex_data = ex_opr.get_data() # 获取excel表中每行数据 @ddt.ddt class FirstDdtCase(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome() cls.driver.get('http://www.5itest.cn/register') cls.driver.maximize_window() cls.file_name = setting.code_path cls.login = RegisterBusiness(cls.driver) def setUp(self): self.driver.refresh() # self.login = RegisterBusiness(self.driver) def tearDown(self): for method_name, error in self._outcome.errors: # case如果执行失败,错误会保存到_outcome.errors 中 if error: # case_name = self._testMethodName # case名,即定义好的方法名 report_error_name = self.assertCode + '.png' report_error_path = os.path.join(setting.base_dir, 'report', report_error_name) self.driver.save_screenshot(report_error_path) @classmethod def tearDownClass(cls): cls.driver.close() @ddt.data(*ex_data) def test_register_case(self,ex_data): # ex_data:[[],[],..] 列表套列表 """数据驱动模式,会按ex_data列表数据,一行一行循环执行,直至列表数据执行完毕""" email, username, password, self.assertCode, assertText = ex_data # 将ex_data每个子列表的数据按顺序赋值。验证码需要提供路径,单独给 # 邮箱、用户名、密码、验证码、错误信息定位元素、错误提示信息 register_error = self.login.register_function(email, username, password, self.file_name,self.assertCode, assertText) self.assertFalse(register_error,"测试失败:{}".format(self.assertCode)) if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(FirstDdtCase) with open(setting.report_path, 'wb') as f: runner = HTMLTestRunner(stream=f,title="This is the first ddt_case report1",description="这个是我们第一次测试报告 --数据驱动",verbosity=2) runner.run(suite) first_ddt_case.py
附例:关键字驱动
from util.excel_cell_value import Get_Cells_Value from keyword_model.actionMethod import ActionMethod from setting_conf import setting class KeywordCase(object): def __init__(self): self.action_metood = ActionMethod() excel_default_path = setting.excel_keyword_path self.get_cell_value = Get_Cells_Value(excel_default_path) # 实例化 def run_main(self): get_lines = self.get_cell_value.get_lines # 获取行数 if get_lines: for i in range(1,get_lines): is_run = self.get_cell_value.get_is_run(i) if is_run == 'yes': carry_method = self.get_cell_value.get_action_method(i) # 获取执行方法 send_value = self.get_cell_value.get_send_value(i) # 获取输入的数据 oper_element = self.get_cell_value.get_oper_element(i) # 获取操作的元素 expect_result_mothod = self.get_cell_value.get_expect_result(i) # 获取预期结果 real_result_value = self.get_cell_value.get_real_result(i) # 获取表中实际要求结果值 self.run_method(carry_method,send_value,oper_element) # 执行excel表中对应指定的方法 if expect_result_mothod != '': # 预期结果有值 result_value = self.get_real_result_value(real_result_value) if result_value[0] == 'text': # url访问,获取网页title result = self.run_method(expect_result_mothod) # expect_result_mothod:driver.get_title()方法 if result_value[1] in result: # 判断实际要求结果值是否存在于实际测试结果中 self.get_cell_value.write_cell_value(i,'pass') # 在excel表中对应单元格写入数据 else: self.get_cell_value.write_cell_value(i,'fail') elif result_value[0] == 'element': # 获取元素,判断输入格式等 result = self.run_method(expect_result_mothod,result_value[1]) # expect_result_mothod:get_element()方法,result_value[1]:参数 if result: # 有值,表示找到对应(如:password_error)错误信息,表示格式测试通过(目的就是测试输入错误格式是否会被检查出来) self.get_cell_value.write_cell_value(i,'pass') else: self.get_cell_value.write_cell_value(i,'fail') else: print("Error:实际要求结果:{},测试无效".format(real_result_value)) else: print('第i条case:预期结果为空') def run_method(self,method,send_value = '',handle_value = ''): main_method = getattr(self.action_metood,method) if send_value == '' and handle_value == '': result = main_method() # 关闭浏览器、等待等 elif send_value == '' and handle_value != '': result = main_method(handle_value) # 打开浏览器、访问url等 elif send_value != '' and handle_value == '': result = main_method(send_value) # 暂时没用到 else: result = main_method(send_value,handle_value) # 输入用户信息 return result # 对实际要求结果值进行切分(实际要求结果形似:text=注册) def get_real_result_value(self, data): return data.split('=') if __name__ == "__main__": keyword_case = KeywordCase() keyword_case.run_main() keyword_case.py