上一篇介绍了自动化框架的架构,今天宏哥就带领小伙伴或者童鞋们开始开工往这个框架里开始添砖加瓦。主要是介绍一个框架unittest单元测试框架和一种设计思想POM。html
前面文章已经简单介绍了一些关于自动化测试框架的介绍,知道了什么是自动化测试框架,主要有哪些特色,基本组成部分等。在继续介绍框架设计以前,咱们先来学习一个工具,叫unittest。前端
unittest是一个单元测试框架,是Python编程的单元测试框架。有时候,也作叫作“PyUnit”,是Junit的Python语言版本。这里了解下,Junit是Java语言的单元测试框架,Java还有一个很好用的单元测试框架叫TestNG,本系列只学习Python,因此只须要unittest是python
Python里的一个单元测试框架就能够了。web
unittest支持测试自动化,共享测试用例中的初始化和关闭退出代码,在unittest中最小单元是test,也就是一个测试用例。要了解unittest单元测试框架,先来了解如下几个重要的概念。编程
一个测试固件包括两部分,执行测试代码以前的准备部分和测试结束以后的清扫代码。这两部分通常用函数setUp()和tearDown()表示。这里举例如下,例如要测试百度搜索selenium这个场景,咱们的测试固件能够这样写,setUp()里写打开浏览器,浏览器最大设计模式
化,和打开百度首页等脚本代码;在tearDown()里写结束搜索后,退出并关闭浏览器的代码。浏览器
unittest中管理的最小单元是测试用例,一个测试用例,包括测试固件,和具体测试业务的函数或者方法。一个测试用例中,测试固件能够不写,可是至少有一个已test开头的函数。unittest会自动化识别test开头的函数是测试代码,若是你写的函数不是test开头,架构
unittest是不会执行这个函数里面的脚本的,这个千万要记住,全部的测试函数都要test开头,记住是小写的哦。框架
很简单,就是不少测试用例的集合,叫测试套件,一个测试套件能够随意管理多个测试用例。若是测试用例比做单个学生,测试套件就是好像是班级的概念。函数
test runner是一个用来执行加载测试用例,并执行用例,且提供测试输出的一个组建。test runner能够加载test case或者test suite进行执行测试任务。
咱们举例来,练习一下test fixture和test case的使用,学习unittest的简单用法:
1. 新建一个testbaidu.py的文件
2. 导入unittest模块
3. 当前测试类继承unittest.TestCase,至关于当前利用unittest建立了一个test case,这个test case是可以被unittest直接识别。
4. 写setUP(),主要是打开浏览器和打开站点
5. 写一个test_search()用例写搜索的代码
6. 写tearDown(),主要是浏览器退出操做
相关脚本代码以下:
# coding=utf-8🔥 # 1.先设置编码,utf-8可支持中英文,如上,通常放在第一行 # 2.注释:包括记录建立时间,建立人,项目名称。 ''' Created on 2019-12-18 @author: 北京-宏哥 QQ交流群:705269076 Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过期不候 ''' # 3.导入模块 import time import unittest from selenium import webdriver class BaiduSearch(unittest.TestCase): def setUp(self): """ 测试固件的setUp()的代码,主要是测试的前提准备工做 :return: """ self.driver = webdriver.Chrome() self.driver.maximize_window() self.driver.implicitly_wait(8) self.driver.get("https://www.baidu.com") def tearDown(self): """ 测试结束后的操做,这里基本上都是关闭浏览器 :return: """ self.driver.implicitly_wait(8) self.driver.quit() def test_baidu_search(self): """ 这里必定要test开头,把测试逻辑代码封装到一个test开头的方法里。 :return: """ self.driver.find_element_by_id('kw').send_keys('selenium') time.sleep(1) self.driver.find_element_by_id('su').click() time.sleep(3) try: assert 'selenium' in self.driver.title print ('Test Pass.') except Exception as e: print ('Test Fail.', format(e)) if __name__ == '__main__': unittest.main()
运行代码后,控制台打印以下图的结果
解释:
最后结尾处的unittest.main(),添加这个是支持在cmd,里面,cd到这个脚本文件所在的目录,而后python 脚本名.py执行,若是不添加这一段,是没法执行cmd里面运行脚本的,在PyCharm中,不添加最后一段,也能够经过,右键 Run "unittest xxx",来达到执行效果。
前面咱们介绍了Python中的单元测试框架unittest,之后咱们全部的测试类文件,都采用unittest来辅助咱们进行debug和脚本开发。搞定了debug机制和肯定了unittest来进行建立和管理咱们的自动化测试脚本,接下来咱们来考虑下,框架设计中一种很广泛的设计
思想-POM(Page Object Model)。
Page Object Model (POM) 直译为“页面对象模型”,这种设计模式旨在为每一个待测试的页面建立一个页面对象(class),将那些繁琐的定位操做封装到这个页面对象中,只对外提供必要的操做接口。
POM 将页面定位和业务操做分开,分离了测试对象和测试脚本,若是UI更改页面,测试脚本不须要更改,只须要更改页面对象中的某些代码就能够,提升了可维护性。
POM,中文字母意思是,页面对象模型,POM是一种最近几年很是流行的自动化测试模型,或者思想,POM不是一个框架,就是一个解决问题的思想。采用POM的目的,是为了解决前端中UI变化频繁,从而形成测试自动化脚本维护的成本愈来愈大。下图,形
象描述了POM的好处。
从上图看出,采起了POM设计思路和不采起的区别,左侧把测试代码和页面元素都写在一个类文件,若是须要更改页面,那么就要修改页面元素定位,从而要修改这个类中测试代码,这个看起来和混乱。右侧,采起POM后,主要的区别就是,把页面元素和业务
逻辑和测试脚本分离出来到两个不一样类文件。ClassA只写页面元素定位,和业务逻辑代码操做的封装,ClassB只写测试脚本,不关心如何元素定位,只写调用ClassA的代码去覆盖不一样的测试场景。若是前端页面发生变化,只须要修改ClassA的元素定位,而不须要去
修改ClassB中的测试脚本代码。
POM主要有如下优势:
1. 把web ui对象仓库从测试脚本分离,业务代码和测试脚本分离。
2. 每个页面对应一个页面类,页面的元素写到这个页面类中。
3. 页面类主要包括该页面的元素定位,和和这些元素相关的业务操做代码封装的方法。
4. 代码复用,从而减小测试脚本代码量。
5. 层次清晰,同时支持多个编写自动化脚本开发,例如每一个人写哪几个页面,不影响他人。
6. 建议页面类和业务逻辑方法都给一个有意义的名称,方便他人快速编写脚本和维护脚本。
好比测试一个登录页面:新浪微博 ,执行测试的人员传递不一样的数据到账号、密码框就能够了,而不该该去顾虑:页面是否已经加载完成?怎样定位到账号输入框?怎样定位到登录按钮等等问题。
这些问题所有交由登录页面的“页面对象”去解决并封装起来,只提供给测试人员三个接口方法:1.账号输入接口、2.密码输入接口、3.提交接口。
首先定义一个基本页面 BasePage类 ,定义基本的页面操做,提供给其余页面去继承,basePage.py 内容以下:
# coding=utf-8🔥 # 1.先设置编码,utf-8可支持中英文,如上,通常放在第一行 # 2.注释:包括记录建立时间,建立人,项目名称。 ''' Created on 2019-12-18 @author: 北京-宏哥 QQ交流群:705269076 Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过期不候 ''' # 3.导入模块 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage(object): """ 基础页面,提供给其余页面继承 """ def __init__(self, driver, base_url, title): """ 初始化 """ self.driver = driver self.base_url = base_url self.title = title def _open(self, url): """ 私有方法,打开url参数指定的页面, 并检查打开是否正确 """ self.driver.get(url) # 显式等待10秒,若是打开页title与预期不符或者超时,抛出异常 WebDriverWait(self.driver, 10).until(EC.title_is(self.title)) def open(self): """ 公共方法,调用私有方法_open()打开连接 """ self._open(self.base_url) def find_element(self, *loc): """ 定位指定元素 """ # 显式等待元素,超过10秒未找到则抛出超时异常(TimeoutException) # presence_of_element_located: 不关心元素是否可见,只关心元素是否存在在页面中 # visibility_of_element_located: 不只找到元素,而且该元素必须可见 WebDriverWait(self.driver, 15).until(EC.visibility_of_element_located(loc)) return self.driver.find_element(*loc) if __name__ == '__main__': driver = webdriver.Chrome() driver.maximize_window() page = BasePage(driver, 'https://www.baidu.com/','百度一下,你就知道') page.open() driver.quit()
运行代码后,控制台打印以下图的结果
# coding=utf-8🔥 # 1.先设置编码,utf-8可支持中英文,如上,通常放在第一行 # 2.注释:包括记录建立时间,建立人,项目名称。 ''' Created on 2019-12-18 @author: 北京-宏哥 QQ交流群:705269076 Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过期不候 ''' # 3.导入模块 from selenium import webdriver from selenium.webdriver.common.by import By from basePage import BasePage class LoginPage(BasePage): """ 新浪微薄登录页面 继承自基础页面BasePage """ # 定位账号输入框 username_loc = (By.ID, 'loginname') # 定位密码输入框 password_loc = (By.NAME, 'password') # 定位登录按钮 submit_loc = (By.XPATH, './/*[@id="pl_login_form"]/div/div[3]/div[6]/a') # 定位提示信息,如:请输入验证码 # 不要迷信开发者工具提供的Xpath, # 好比这里提供的Xpath://*[@id="layer_15582553868501"]/div/p/span[2], # id是动态的,没法使用,需自行推到Xpath message_loc = (By.XPATH, '//div[@class="content layer_mini_info"]/p/span[2]') # 输入用户名操做 def type_username(self, username): self.find_element(*self.username_loc).send_keys(username) # 输入密码操做 def type_password(self, password): self.find_element(*self.password_loc).send_keys(password) # 点击登录按钮操做 def submit(self): self.find_element(*self.submit_loc).click() # 获取提示信息 def get_message(self): return self.find_element(*self.message_loc).text if __name__ == '__main__': # 测试登录 # 预打开页面 base_url = 'https://weibo.com/' # 页面title title = '微博-随时随地发现新鲜事' # 准备好待输入的用户名和密码 username = 'haha' password = 'hehe' # 打开Chrome浏览器 driver = webdriver.Chrome() driver.maximize_window() # 登录页面初始化 login = LoginPage(driver, base_url, title) # 打开新浪微博页 login.open() # 输入用户名 login.type_username(username) # 输入密码 login.type_password(password) # 点击登录 login.submit() # 打印提示信息 print(login.get_message())
运行代码后,控制台打印以下图的结果
好了,今天的分享就到这里吧!!!谢谢各位的耐心阅读。有问题加群交流讨论
您的确定就是我进步的动力。若是你感受还不错,就请鼓励一下吧!记得随手点波 推荐 不要忘记哦!!!
别忘了点推荐留下您来过的痕迹
原文出处:https://www.cnblogs.com/du-hong/p/12058673.html