1. Unittest是什么?
Unittest是python单元测试框架,是受到JUnit 的启发,与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化,配置共享和关机代码测试。支持将测试样例聚合到测试集中,并将测试与报告框架独立。它不仅适用于单元测试,还在自动化测试领域占有一席之地。借助它组织执行测试用例,使用它提供的丰富的断言方法进行测试结果的比对,并结合HTMLTestRunner生成测试报告完成整个自动化测试流程。
2. Unittest的基本用法
想要使用unittest,在创建测试类的时候,就需要继承unittest的testcase类;如果类中有多个测试函数,当只想单独执行一个测试函数时,在那个测试函数def 所在的行右击运行;当需要全部运行时,使用main()的方法,该方法是unittest中区中的全局方法
import unittest
class TestApi(unittest.TestCase):
def test_add(self):
self.assertEqual(5,5)
if __name__ == '__main__':
TestApi.main()
注:用例函数名需要以test开头以满足unittest.TestLoader类的搜索方式
3. unittest的前后置插件
setUpModule/tearDownModule:在整个模块的开始和结束时被执行
setUpClass/tearDownClass:在测试类的开始和结束时执行,需要加@classmethod装饰器
setUp/tearDown:在测试函数的开始与结束时被执行
import unittest
def setUpModule():
print('模块前置')
def tearDownModule():
print('模块后置')
class TestApi(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
print('类前置')
@classmethod
def tearDownClass(cls) -> None:
print('类后置')
def setUp(self) -> None:
print('函数前置')
def tearDown(self) -> None:
print('函数后置')
def test_add(self):
print('测试函数')
self.assertEqual(5,5)
if __name__ == '__main__':
TestApi.main()
'''
模块前置
类前置
PASSED[100%]函数前置
测试函数
函数后置
类后置
模块后置
'''
4. unittest.TestSuite测试套件
unittest.TestSuite().addTest(测试类名(‘测试函数名’)):每次加载单个测试用例到套件中
unittest.TestSuite().addTests(cases):同时加载多个测试用例到套件中,cases是有多个(测试类名(‘测试函数名’))组成的列表
unittest.TestSuite().addTests(unittest.TestLoader().loadTestsFromTestCase(测试类名)):加载整个测试类中的测试用例到套件中
unittest.defaultTestLoader.discover(start_dir,pattern='test*.py',top_level_dir=None):模糊匹配给套件需要执行的测试用例,start_dir表示测试类所在的文件路径,pattern表示匹配规则,用于匹配对应的测试类所在的文件名格式,top_level_dir表示测试模块的顶层目录
import unittest
from demo1 import TestApi
if __name__ == '__main__':
suite = unittest.TestSuite()
#1.每次添加单个测试用例
suite.addTest(TestApi('test_add'))
#2.每次添加多个测试用例
cases = [TestApi('test_add'),TestApi('test_sub')]
suite.addTests(cases)
#3.添加整个测试用例
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestApi))
#4.使用模糊匹配查找测试用例
casepath = '../unittestlearn'
suite = unittest.defaultTestLoader.discover(start_dir=casepath,pattern='demo*.py')
#创建测试执行器
runner = unittest.TextTestRunner()
runner.run(suite)
5. 测试用例跳过和预期失败
@unittest.skip(reason):无条件的跳过装饰的测试用例,reason说明跳过测试的原因
@unittest.skiIf(condition,reason):当condition为True时,跳过测试用例
@unittest.skipUnless(condition,reason):当condition为False时,跳过测试用例
@unittest.expectedFailure():测试表示为失败,不管执行结果是否失败,统一标记为失败,但不会抛出错误信息
@unittest.expectedFailure:如果断言失败,则不计入case数目中
6. HTMLTestRunner自动生成测试报告
HTMLTestRunner是python标准库unittest单元测试框架的一个拓展,它生成易于使用的HTML测试报告。HTMLTestRunner下载地HTMLTestRunner.html,在GitHub上也有一个人在这个基础上做过改动的,可以自己去下载,下载下来是一个HTMLTestRunner.py文件,选中后单击鼠标右键,在弹出的快捷菜单中选择目标另存为,将它保存到本地。安装方法是将其复制到python安装目录下即可。
import unittest
from HTMLTestRunner import HTMLTestRunner
import os
if __name__ == '__main__':
casepath = '../unittestlearn'
suite = unittest.defaultTestLoader.discover(start_dir=casepath,pattern='demo*.py')
report_path = './report/'
report_title = 'unittest—learn'
report_desc = '本次是学习unittest的过程'
file_path = report_path+'test.html'
if not os.path.exists(report_path):
os.mkdir(report_path)
with open(file_path,'wb') as f:
runner = HTMLTestRunner(stream=f,title=report_title,description=report_desc)
runner.run(suite)
7. Excel数据读取
当测试用例数据在写excel的时候,就需要对excel文件进行读取,以支持后续的数据驱动。
from openpyxl import load_workbook
class ReadExcel:
def get_data(self,path,sheet_name):
#打开表格
wb = load_workbook(path)
#指定sheet表单
ws = wb[sheet_name]
rows = ws.max_row
cols = ws.max_column
infos = []
#r和c的范围,取决于表的格式
for r in range(2,rows+1):
info = []
for c in range(1,cols+1):
info.append(ws.cell(r,c).value)
infos.append(info)
return infos
8. DDT数据驱动
在测试活动中经常会使用相同的测试脚本使用不同的测试数据来执行,测试数据和测试行为完全分离,这样的测试脚本设计模式称为数据驱动。例如:当我们测试某个网站的登录功能时,往往我们会使用不同的用户名和密码来验证登录模块对系统的影响,那么如果我们每一条数据都编写一条测试用例,这无疑是增加了代码量,代码重复冗余很多,这时候我们可以使用不同数据执行相同的用例测试不同的场景。
import unittest
import ddt
from readecxel import ReadExcel
@ddt.ddt
class TestApi(unittest.TestCase):
infos = ReadExcel().get_data('./test_data.xlsx','Sheet1')
@ddt.data(*infos)
@ddt.unpack
def test_add(self,a,b,msg):
print('test_add')
self.assertEqual(a+b,msg)
if __name__ == '__main__':
TestApi.main()
参数说明:@ddt.ddt:表示该类可以使用数据驱动来加载测试数据
@ddt.data(*infos):装饰出测试用例,*infos表示将infos中的值一次加载到ddt中
@ddt.unpack:表示将每次得到的data值进行分离,按顺序传入装饰的测试函数中
9. PO模型的设计
Page Object模式主要是将每个页面设计为一个class,其中包含页面中的需要测试的元素(按钮,输入框,标题等),这样在Selenium测试页面中可以通过调取页面类来获取页面元素,这样避免当页面元素id或者位置变化后,需要改测试代码。当元素ID变化时,只需要改测试页面Class中的页面属性即可。将页面定位与和业务分开,分离测试对象(元素对象)和测试脚本(用例脚本),提高可维护性。
Page Object模式是一种自动化测试设计模式,将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),提高用例的可维护性。
unittest是一种单元测试框架,用于设计各式各样的测试用例,可调用PageObject设计的页面类(对象),设计出更加可维护的用例。它提供用例组织与执行,提供丰富的比较(断言)方法,提供丰富的日志,统一适用于web自动化用例的开发与执行。
使用python+selenium+unitte+openpyxl+ddt可以实现UI自动化测试脚本的搭建,将每个单元测试可以分为元素层,操作层和业务层,需要注意的是:在定义的时候,操作层需要继承元素层,业务层需要继承操作层,元素乘则需要继承浏览器获取操作