Selenium自动化测试-unittest单元测试框架使用
一、unittest
unittest是一个单元测试框架,是Python编程的单元测试框架。有时候,也做叫做“PyUnit”,是Junit的Python语言版本。这里了解下,Junit是Java语言的单元测试框架,Java还有一个很好用的单元测试框架叫TestNG,本系列只学习Python,所以只需要unittest是Python里的一个单元测试框架就可以了。
unittest支持测试自动化,共享测试用例中的初始化和关闭退出代码,在unittest中最小单元是test,也就是一个测试用例。要了解unittest单元测试框架,先来了解以下几个重要的概念。
1. 测试固件(test fixture)
一个测试固件包括两部分,执行测试代码之前的准备部分和测试结束之后的清扫代码。这两部分一般用函数setUp()和tearDown()表示。这里举例以下,例如要测试百度搜索selenium这个场景,我们的测试固件可以这样写,setUp()里写打开浏览器,浏览器最大化,和打开百度首页等脚本代码;在tearDown()里写结束搜索后,退出并关闭浏览器的代码。
2. 测试用例(test case)
unittest中管理的最小单元是测试用例,一个测试用例,包括测试固件,和具体测试业务的函数或者方法。一个测试用例中,测试固件可以不写,但是至少有一个已test开头的函数。unittest会自动化识别test开头的函数是测试代码,如果你写的函数不是test开头,unittest是不会执行这个函数里面的脚本的,这个千万要记住,所有的测试函数都要test开头,记住是小写的哦。
3. 测试套件 (test suite)
很简单,就是很多测试用例的集合,叫测试套件,一个测试套件可以随意管理多个测试用例。如果测试用例比作单个学生,测试套件就是好像是班级的概念。
4. 测试执行器 (test runner)
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
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.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(1)
try:
assert 'selenium' in self.driver.title
print ('Test Pass.')
except Exception as e:
print ('Test Fail.', format(e))
if __name__ == '__main__':
unittest.main()
二、
- 基类base_page.py的具体实现代码,这里就封装了几个常用方法。
- baidu_homepage.py页面对象中,百度主页的元素定位和简单的操作函数,页面类主要是元素定位和页面操作写成函数,供测试类调用。
- 测试类的写法举例:
import time
import unittest
from selenium_package.browser_engine import BrowserEngine
from pageobject.baidu_homepage import HomePage
class BaiduSearch2(unittest.TestCase):
def setUp(self):
"""
测试固件的setUp()的代码,主要是测试的前提准备工作
:return:
"""
browse = BrowserEngine(self)
self.driver = browse.open_browser(self)
def tearDown(self):
"""
测试结束后的操作,这里基本上都是关闭浏览器
:return:
"""
self.driver.quit()
def test_baidu_search2(self):
"""
这里一定要test开头,把测试逻辑代码封装到一个test开头的方法里。
:return:
"""
homepage = HomePage(self.driver)
# 上面这行代码要注意,意思是,到一个页面,第一件事情是初始化这个页面的一个页面对象实例。
# 注意,一定要带self.driver,不然会报错,这个self.driver,可以这样理解:
# 在当前测试类里面,self.driver是来自浏览器引擎类中方法得到的,
# 在初始化一个页面对象的时候,也把这个来自浏览器引擎类的driver给赋值给当前的页面对象,
# 这样,才能执行页面对象或者基类里面的相关driver方法。
# 写多了selenium的自动化脚本,你会明白,最重要的是保持前后driver的唯一性。
homepage.type_search('selenium') # 调用页面对象中的方法
homepage.send_submit_btn() # 调用页面对象类中的点击搜索按钮方法
time.sleep(2)
homepage.get_windows_img() # 调用基类截图方法
try:
assert 'selenium' in homepage.get_page_title() # 调用页面对象继承基类中的获取页面标题方法
print('test pass')
except Exception as e:
print('Test Fail.', format(e))
def test_search2(self):
homepage = HomePage(self.driver)
homepage.type_search('python') # 调用页面对象中的方法
homepage.send_submit_btn() # 调用页面对象类中的点击搜索按钮方法
time.sleep(2)
homepage.get_windows_img() # 调用基类截图方法
if __name__ == '__main__':
unittest.main()
问题发现了没,我们的浏览器启动和关闭了两次,是不是这个问题?原来,没执行一次test开头的函数,都要执行一次测试固件,也就是说执行setUp()和()一次,如果有N个test开头的函数,测试固件就执行N次,我们到底有没有,只需要执行一次测试固件,支持执行多次测试函数。
我们测试中,肯定需要,打开一个页面,然后测试这个页面的多个用例,才关闭这个页面,去测试其他页面,在unittest是有相关测试固件方法去支持这种行为。请看下面调整,自己对比下,能不能找出不同。
class BaiduSearch(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""
测试固件的setUp()的代码,主要是测试的前提准备工作
:return:
"""
browse = BrowserEngine(cls)
cls.driver = browse.open_browser(cls)
@classmethod
def tearDownClass(cls):
"""
测试结束后的操作,这里基本上都是关闭浏览器
:return:
"""
cls.driver.quit()
补充:
# @classmethod和 @ setUpclass(cls) 接口测试 token处理用法详解: