First you have to know what is Selenium?
Selenium is a browser-based automated testing tool that provides a cross-platform, cross-browser web-to-end automation solutions. Selenium mainly includes three parts: Selenium IDE, Selenium WebDriver and Selenium Grid.
-
Selenium IDE: a Firefox extension, it can play back the recording, and the recording operation (e.g., Java, Python, etc.) into the form of test cases derived languages.
-
Selenium WebDriver: to provide the necessary automation Web API, mainly used browser control, select the page elements and debugging. Different browsers require different WebDriver.
-
Selenium Grid: provides the ability to run selenium tests on different machines in different browsers.
Now I will use mind mapping directory structure introduces basic testing framework, writing test cases for functional test cases, I want to help you learn.
Design ideas
Frame python3 + selenium3 + PO + yaml + ddt + unittest and other basic techniques for writing into a testing framework that can adapt to the routine testing needs.
-
Use Page Object Location page mode and a separate business operations, the separation of the test object (target element), and a test script (script use cases), a page to build an object class, improving maintainability use cases;
-
Use yaml management page controls elements of the data and test data. For example, an element ID is changed like, do not need to modify the test code, only need to modify the corresponding page element file yaml;
-
Management sub-module, independently of each other, ready to assemble, used with that.
Testing framework hierarchical design
Find the common operations and packaged into a base class, no matter what the product can be directly used to multiplex
-
The main business layer is encapsulated target page class, a class to build a page, the page inherits the business layer base layer
-
It is constructed to perform simulation test cases for product pages function layer
-
Framework assembly base layer provides the support and the whole process execution function expansion, to provide data for each page element with a layer embodiment, case testing data, test reports etc. Output
Testing framework directory structure
FIG mind the following directory structure Introduction:
Written Example
如果对软件测试、接口测试、自动化测试、面试经验交流。感兴趣可以关注我们爱码小士,公众号内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家
testinfo: - id: test_login001 title: 登录测试 info: 打开抽屉首页 testcase: - element_info: login-link-a find_type: ID operate_type: click info: 打开登录对话框 - element_info: mobile find_type: ID operate_type: send_keys info: 输入手机号 - element_info: mbpwd find_type: ID operate_type: send_keys info: 输入密码 - element_info: //input[@class='keeplogin'] find_type: XPATH operate_type: click info: 单击取消自动登录单选框 - element_info: //span[text()='登录'] find_type: XPATH operate_type: click info: 单击登录按钮 - element_info: userProNick find_type: ID operate_type: perform info: 鼠标悬停账户菜单 - element_info: //a[@class='logout'] find_type: XPATH operate_type: click info: 选择退出 check: - element_info: //div[@class='box-mobilelogin'] /div[1]/span find_type: XPATH info: 检查输入手机号或密码,登录异常提示 - element_info: userProNick find_type: ID info: 成功登录 - element_info: reg-link-a find_type: ID info: 检查退出登录是否成功 login.yaml
例如,我们要新增登录功能测试用例:
首先,只需在testyaml目录下新增一个页面对象yaml文件,参考login.yaml格式编写即可。这些文件是提供给封装页面对象类调用并执行定位识别操作。
- id: test_login001.1 detail : 手机号和密码为空登录 screenshot : phone_pawd_empty data: phone: "" password: "" check : - 手机号不能为空 - id: test_login001.2 detail : 手机号为空登录 screenshot : phone_empty data : phone: "" password : aa check : - 手机号不能为空 - id: test_login001.3 detail : 密码为空登录 screenshot : pawd_empty data : phone : 13511112222 password: "" check : - 密码不能为空 - id: test_login001.4 detail : 非法手机号登录 screenshot : phone_error data : phone : abc password: aa check : - 手机号格式不对 - id: test_login001.5 detail : 手机号或密码不匹配 screenshot : pawd_error data : phone : 13511112222 password: aa check : - 账号密码错误 - id: test_login001.6 detail : 手机号和密码正确 screenshot : phone_pawd_success data : phone : 13865439800 password: ******** check : - yingoja login_data.yaml login_data.yaml
其次,在testdata目录下新增一个login_data.yaml文件提供给登录接口传参的测试数据,编写格式参考login_data.yaml文件。
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(os.path.dirname (os.path.dirname(__file__)))) from config import setting from selenium.webdriver.support.select import Select from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from public.page_obj.base import Page from time import sleep from public.models.GetYaml import getyaml testData = getyaml(setting.TEST_Element_YAML + '/' + 'login.yaml') class login(Page): """ 用户登录页面 """ url = '/' dig_login_button_loc = (By.ID, testData. get_elementinfo(0)) def dig_login(self): """ 首页登录 :return: """ self.find_element(*self.dig_login_button_loc) .click() sleep(1) # 定位器,通过元素属性定位元素对象 # 手机号输入框 login_phone_loc = (By.ID,testData. get_elementinfo(1)) # 密码输入框 login_password_loc = (By.ID,testData. get_elementinfo(2)) # 取消自动登录 keeplogin_button_loc = (By.XPATH,testData. get_elementinfo(3)) # 单击登录 login_user_loc = (By.XPATH,testData. get_elementinfo(4)) # 退出登录 login_exit_loc = (By.ID, testData. get_elementinfo(5)) # 选择退出 login_exit_button_loc = (By.XPATH,testData. get_elementinfo(6))def login_phone(self,phone): """ 登录手机号 :param username: :return: """ self.find_element(*self.login_phone_loc). send_keys(phone)def login_password(self,password): """ 登录密码 :param password: :return: """ self.find_element(*self.login_password_loc). send_keys(password) def keeplogin(self): """ 取消单选自动登录 :return: """ self.find_element(*self.keeplogin_button_loc). click()def login_button(self): """ 登录按钮 :return: """ self.find_element(*self.login_user_loc).click() def login_exit(self): """ 退出系统 :return: """ above = self.find_element(*self.login_exit_loc) ActionChains(self.driver).move_to_element(above). perform() sleep(2) self.find_element(*self.login_exit_button_loc) .click()def user_login(self,phone,password): """ 登录入口 :param username: 用户名 :param password: 密码 :return: """ self.open() self.dig_login() self.login_phone(phone) self.login_password(password) sleep(1) self.keeplogin() sleep(1) self.login_button() sleep(1) phone_pawd_error_hint_loc = (By.XPATH,testData. get_CheckElementinfo(0)) user_login_success_loc = (By.ID,testData. get_CheckElementinfo(1)) exit_login_success_loc = (By.ID,testData. get_CheckElementinfo(2)) # 手机号或密码错误提示 def phone_pawd_error_hint(self): return self.find_element(*self.phone_pawd_error_ hint_loc).text# 登录成功用户名 def user_login_success_hint(self): return self.find_element(*self.user_login_ success_loc).text # 退出登录 def exit_login_success_hint(self): return self.find_element(*self.exit_login_ success_loc).textloginPage.py
然后,在page_obj目录下新增一个loginPage.py文件,是用来封装登录页面对象类,执行登录测试流程操作。
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(os.path. dirname(__file__))) import unittest,ddt,yaml from config import setting from public.models import myunit,screenshot from public.page_obj.loginPage import login from public.models.log import Log try: f =open(setting.TEST_DATA_YAML + '/' + 'login_data.yaml',encoding='utf-8') testData = yaml.load(f) except FileNotFoundError as file: log = Log() log.error("文件不存在:{0}".format(file)) @ddt.ddt class Demo_UI(myunit.MyTest): """抽屉新热榜登录测试""" def user_login_verify(self,phone,password): """ 用户登录 :param phone: 手机号 :param password: 密码 :return: """ login(self.driver).user_login(phone,password) def exit_login_check(self): """ 退出登录 :return: """ login(self.driver).login_exit() @ddt.data(*testData) def test_login(self,datayaml): """ 登录测试 :param datayaml: 加载login_data登录测试数据 :return: """ log = Log() log.info("当前执行测试用例ID-> {0} ; 测试点-> {1}".format(datayaml['id'],datayaml['detail'])) # 调用登录方法 self.user_login_verify(datayaml['data']['phone'], datayaml['data']['password']) po = login(self.driver) if datayaml['screenshot'] == 'phone_pawd_success': log.info("检查点-> {0}".format (po.user_login_success_hint())) self.assertEqual(po.user_login_success_hint(), datayaml['check'][0], "成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint())) log.info("成功登录,返回实际结果是->: {0}".format(po.user_login_success_hint())) screenshot.insert_img(self.driver, datayaml ['screenshot'] + '.jpg') log.info("-----> 开始执行退出流程操作") self.exit_login_check() po_exit = login(self.driver) log.info("检查点-> 找到{0}元素,表示退出成功!".format(po_exit.exit_login_success_hint())) self.assertEqual(po_exit.exit_login_success_hint(), '注册',"退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint())) log.info("退出登录,返回实际结果是->: {0}".format(po_exit.exit_login_success_hint())) else: log.info("检查点-> {0}".format(po.phone _pawd_error_hint())) self.assertEqual(po.phone_pawd_error_hint(), datayaml['check'][0] , "异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint())) log.info("异常登录,返回实际结果是->: {0}".format(po.phone_pawd_error_hint())) screenshot.insert_img(self.driver,datayaml ['screenshot'] + '.jpg') if __name__=='__main__': unittest.main() login_sta.py
最后,在testcase目录下创建测试用例文件login_sta.py,采用ddt数据驱动读取yaml测试数据文件
综上所述,编写用例方法只需要按以上四个步骤创建->编写即可。
执行如下主程序,可看输出的实际结果。
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(__file__)) from config import setting import unittest,time from package.HTMLTestRunner import HTMLTestRunner from public.models.newReport import new_report from public.models.sendmail import send_mail # 测试报告存放文件夹,如不存在,则自动创建 一个report目录 if not os.path.exists(setting.TEST_REPORT):os.makedirs (setting.TEST_REPORT + '/' + "screenshot") def add_case(test_path=setting.TEST_DIR): """加载所有的测试用例""" discover = unittest.defaultTestLoader.discover (test_path, pattern='*_sta.py') return discover def run_case(all_case,result_path=setting.TEST_REPORT): """执行所有的测试用例""" now = time.strftime("%Y-%m-%d %H_%M_%S") filename = result_path + '/' + now + 'result.html' fp = open(filename,'wb') runner = HTMLTestRunner(stream=fp,title=' 抽屉新热榜UI自动化测试报告', description='环境:windows 7 浏览器:chrome', tester='Jason') runner.run(all_case) fp.close() report = new_report(setting.TEST_REPORT) #调用模块生成最新的报告 send_mail(report) #调用发送邮件模块 if __name__ =="__main__": cases = add_case() run_case(cases)
测试结果展示
HTML报告日志
HTML报告点击截图,弹出截图
测试报告通过的日志
自动截图存放指定的目录
邮件测试报告