目录
定义:unittest是python自带的一个单元测试框架,也是python里面最基本的单元测试框架,存放在python安装目录下的lib目录下
为什么要使用:
在项目内使用unittest框架来组织测试用例
unittest里面最核心的四个理念:
test case 测试用例
test fixture 测试夹具
test runner 测试执行
test suite 测试套件
一.unittest书写规则
1.测试文件必需一test开头. 如:test_01_unittest入门脚本.py
2.测试类必需继承:unittest.TestCase
3.测试类必需以Test开头
4.测试方法最好以test开头. 如def test_01_login(self):
5.在测试的py文件里面去执行代码用 unittest.main()
6.在测试类里面可以有普通方法,但是普通方法需要被测试方法调用
二.入门脚本
例:
# 导包
import unittest
# 创建类
class Testlogin(unittest.TestCase):
def test_login(self):
print('执行正确登录')
def test_login_re(self):
print('执行保存登录')
if __name__ == '__main__':
unittest.main()
四.测试夹具(test fixture)
方法级别:
setUp() 在每一个测试执行之前执行setup的代码
tearDown() 在每一个测试执行之后执行tearDown的代码
类级别:
setupclass() 在每一个测试类执行之前执行的方法,需要@classmethod装饰
teardownclass() 在每一个测试类执行之后执行的方法,需要@classmethod装饰
例:
import unittest
class Testlogin(unittest.TestCase):
def test_login(self):
print('执行正确登录')
def test_login_re(self):
print('执行保存登录')
def setUp(self) -> None:
print('方法之前执行的代码')
def tearDown(self) -> None:
print('方法之后执行的代码')
@classmethod
def setUpClass(cls) -> None:
print('类之前执行代码')
@classmethod
def tearDownClass(cls) -> None:
print('类方法之后执行的代码')
if __name__ == '__main__':
unittest.main()
五.用例执行顺序
在unittest里面,用例执行的顺序默认是按照ASCII码执行,因此我们需要给每一条用例加上执行序号 如:01 02
import unittest
class Testlogin(unittest.TestCase):
def test_01_openweb(self):
print('打开网页')
def test_02_login(self):
print('执行登录步骤')
def test_03_view(self):
print('浏览网页并挑选商品')
def test_04_add(self):
print('加入购物车')
def test_05_Place_an_order(self):
print('下单商品')
def test_06_orders(self):
print('生成订单')
六.断言
判断预期结果和实际结果是否相符合
self.assertEqual(a,b,msg='错误描述') 判断 a==b成立则测试用例通过
self.assertTrue(x,msg='错误描述') 判断 表达式x 是否为true,为true通过测试
self.assertIn(a,b,msg='错误描述') 判断 a in b成立则测试通过
例:
import unittest
class Testlogin(unittest.TestCase):
def test_01_openweb(self):
print('打开网页')
def test_02_login(self):
a='admin'
b='admin2'
print('执行登录步骤')
self.assertEqual(a,b,msg='预期结果与实际结果不相等') # a==b(预期结果与实际结果相等)用例通过
def test_03_view(self):
print('浏览网页并挑选商品')
def test_04_add(self):
print('加入购物车')
x=10
y=9
self.assertTrue(x==y,msg='购物车数量不符') # 表达式为真,用例通过
def test_05_Place_an_order(self):
print('下单商品')
def test_06_orders(self):
print('生成订单')
s='1234'
d='aaaa123'
self.assertIn(s,d,msg='预期结果不在实际结果里面') # s在b里面(预期结果在实际结果里面)用例通过
if __name__ == '__main__':
unittest.main()
七.跳过测试
1.当我们写的部分用例,在某些情况下不需要执行的时候可以跳过
2.当系统更新之后,部分的测试用例失效,但是不确定后面是否还会再改回来,就直接跳过
装饰器实现的跳过测试用例
@unittest.skip(原因) 没有条件,直接跳过
@unittest.skipIf(表达式,原因) 表达式为真跳过测试
@unittest.skipUnless(表达式,原因) 表达式为假跳过测试
import unittest
num=4
class Testlogin(unittest.TestCase):
def test_01_openweb(self):
print('打开网页')
def test_02_login(self):
print('执行登录步骤')
def test_03_view(self):
print('浏览网页并挑选商品')
@unittest.skip('不想加入购物车') # 没有条件直接跳过
def test_04_add(self):
print('加入购物车')
@unittest.skipIf(num>3,'下单数量不能大于3') # 条件为真就跳过
def test_05_Place_an_order(self):
print('下单商品')
@unittest.skipUnless(num==4,'订单数量要等于4') # 条件为假就跳过
def test_06_orders(self):
print('生成订单')
if __name__ == '__main__':
unittest.main()
八.runcas
test suite 测试套件:把需要执行的测试用例放到一个套子
test runner 测试执行:使用测试执行去执行所有在套子里面的测试用例
方法1:
unittest.main()
方法2:
测试套件:适合作为调试测试用例
suite = unittest.TestSuite() suite.addTest(测试类('测试方法'))
测试执行
runner = unittest.TextTestRunner() runner.run(suite)
例:
import unittest
from case.test_03_用例执行顺序 import Testlogin
# 实例化一个测试套件
suite=unittest.TestSuite()
suite.addTest(Testlogin('test_02_login'))
# 执行
runner=unittest.TextTestRunner()
runner.run(suite)
方法3:runAllCase
import unittest
# 添加所有的测试用例到套件
suite=unittest.defaultTestLoader.discover('./case',pattern='test_03_用例执行顺序.py')
#实例化测试执行对象
runner=unittest.TextTestRunner()
# 执行suite
runner.run(suite)
九.测试报告
HTMLTestRunner:第三方插件
下载resource里面的HTMLTestRunnerPlugins放到python安装目录下的 lib 目录下
1.生成的报告应该放在Report里面
2.生成的报告应该以 .html结尾
例:
import unittest
import HTMLTestRunnerPlugins
import os
import time
# 获取测试报告的路径进行拼接
report_path = os.path.dirname(__file__) + '/Report/'
# 获取当前时间
now = time.strftime('%Y-%m-%d %H_%M_%S')
# 根据路径和时间拼接最终的文件路径
report_name = report_path + now + 'HTMLReport.html'
# 添加执行的测试目录到套件里面
suite = unittest.defaultTestLoader.discover('./Case')
# unittest.TextTestRunner().run(suite)
# 打开我们刚才拼接好的路径
with open(report_name, 'wb') as fq:
# 实例化一个 HTMLTestRunner
runner = HTMLTestRunnerPlugins.HTMLTestRunner(
stream=fq,
verbosity=2,
title='web自动化测试报告',
description="本次执行完所有的测试用例",
tester='第一组'
)
# 执行套件
runner.run(suite)
十.数据驱动
有的用例只是参数不一样,其他代码完全一样,就可以通过改变测试参数来实现一条用例方法 执行多种不同的测试场景.在unittest里面需要使用 ddt 来提供参数化的功能
ddt可以参数化读取列表嵌套列表或者列表嵌套字典的数据
列表嵌套列表读取:
先在类前面加上: @ddt.ddt
在方法前面加上: @ddt.data(*列表嵌套列表)
@ddt.unpack
import unittest
import ddt
from Common.OperationData import OperationData
from Page.LoginPage import LoginPage
data_list = OperationData('user_data.xls').get_data_list()
data_dict = OperationData('user_data.xls').get_data_dict()
@ddt.ddt
class TestLoginDDt(unittest.TestCase):
@ddt.data(*data_list)
@ddt.unpack
def test_login(self, username, password):
login = LoginPage("chrome")
login.open_login_url()
login.send_user_name(username)
login.send_password(password)
列表嵌套字典读取:
先在类前面加上: @ddt.ddt
在方法前面加上: @ddt.data(*列表嵌套列表)
在方法里面使用一个形式参数来接收
import unittest
import ddt
from Common.OperationData import OperationData
from Page.LoginPage import LoginPage
data_list = OperationData('user_data.xls').get_data_list()
data_dict = OperationData('user_data.xls').get_data_dict()
@ddt.ddt
class TestLoginDDt(unittest.TestCase):@ddt.data(*data_dict)
def test_login_dict(self, dict_data):
login = LoginPage("chrome")
login.open_login_url()