unitTest介绍
- UnitTest是python自带的自动化测试框架
- UnitTest主要包含的内容
-
TestCase(测试用例)
-
TestSuite(测试套件,把多个TestCase集成到一个测试TestSuite)
-
TestRunner(执行测试用例)
-
TestLoader(自动从代码中加载多个测试用例TestCase)
-
Fixture(UnitTest特性)
TestCase(测试用例)
使用时注意点:
- 类必须要继承unitTest.TestCase
- 创建方法名必须以test开头
# 导包
import unittest
def my_sum(a, b):
return a + b
# 创建类
class test(unittest.TestCase):#类必须要继承unitTest.TestCase
# 创建方法(方法名必须以test开头)
def test_01(self):
print(my_sum(5, 6))
# 创建方法(方法名必须以test开头)
def test_02(self):
print(my_sum(7, 6))
TestSuite(测试套件,把多个TestCase集成到一个测试TestSuite)
注意点:主要是调用unitTest.TestSuite()方法中的addTest()方法添加测试用例
# 用unittest.makeSuite一次导入一个类中的所有测试方法
testSuite()与TestLoader()的区别:
- 当只是要执行py文件中的几个用例时,使用TestSuite()方法中的addTest()方法加载指定用例
- 当要执行整个py文件时可以直接调用TestLoader(),加载整个py文件的测试用例
# 测试套件
# 导包
import unittest
import unitTest_testCase
# 只是把测试用例添加到了测试套件中,并不是执行测试用例
suite = unittest.TestSuite()
suite.addTest(unitTest_testCase.test.test_01())
suite.addTest(unitTest_testCase.test.test_02())
# 用unittest.makeSuite一次导入一个类中的所有测试方法
# suite.addTest(unittest.makeSuite(unitTest_testCase.test))
TestRunner(执行测试用例)
注意点:主要是调用unitTest.TextTestRunner()方法中的run()方法来执行测试用例
# 测试套件
# 导包
import unittest
import unitTest_testCase
suite = unittest.TestSuite()
suite.addTest(unitTest_testCase.test.test_01())
suite.addTest(unitTest_testCase.test.test_02())
# 执行测试套件
runner = unittest.TextTestRunner()
runner.run(suite)
TestLoader(自动从代码中加载多个测试用例TestCase)
# 测试套件
# 导包
import unittest
import unitTest_testCase
# TestLoader
# 用TestLoader对象的discover方法来自动查找py,自动加载py文件中的方法
# 第一个参数是从哪里找py文件,"."从当前目录开始查找py文件
# 第二个参数是指定py文件的文件名,可以用通配符
suite = unittest.TestLoader().discover(".", "unitTest_testCase.py")
# 执行测试套件
runner = unittest.TextTestRunner()
runner.run(suite)
小结:
- 所有的testCase都是被textTestRunner来执行
- textTestRunner执行的是testSuite
- 一个testSuite中有很多testCase
Fixture(UnitTest特性)
方法级别的FiXTure:在方法执行前调用setup()方法;在用例执行之后调用tearDown()方法
# 导包
import unittest
def my_sum(a, b):
return a + b
# 创建类
class test(unittest.TestCase):
def setUp(self):
print("方法级调用---setup")
def tearDown(self):
print("方法级调用---tearDown")
# 创建方法(方法名必须以test开始)
def test_01(self):
print(my_sum(5, 6))
# 创建方法(方法名必须以test开始)
def test_02(self):
print(my_sum(7, 6))
类级别的fixture:在类执行前调用setUpClass(cls)方法,在类执行之后调用tearDownClass(cls)方法,类级别的调用要加@classmethod装饰器
# 导包
import unittest
def my_sum(a, b):
return a + b
# 创建类
class test(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("类级别调用--setUpClass")
@classmethod
def tearDownClass(cls):
print("类级别调用--tearDownClass")
def setUp(self):
print("方法级调用---setup")
def tearDown(self):
print("方法级调用---tearDown")
# 创建方法(方法名必须以test开始)
def test_01(self):
print(my_sum(5, 6))
# 创建方法(方法名必须以test开始)
def test_02(self):
print(my_sum(7, 6))
模块级别调用: 模块级别调用指整个py文件执行之前调用setUpModule()方法,执行之后调用tearDownModule()方法
import unittest
def setUpModule():
print("setUpModule自动调用了")
def tearDownModule():
print("tearDownModule自动调用了")
def my_sum(a, b):
return a + b
class my_test1(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setupclass自动调用了")
@classmethod
def tearDownClass(cls):
print("teardownclass自动调用了")
def setUp(self):
print("setup被自动调用了")
def tearDown(self):
print("teardown被自动调用了")
def test_001(self):
print(my_sum(5, 6))
def test_002(self):
print(my_sum(0, 3))
class my_test2(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setupclass自动调用了")
@classmethod
def tearDownClass(cls):
print("teardownclass自动调用了")
def setUp(self):
print("setup被自动调用了")
def tearDown(self):
print("teardown被自动调用了")
def test_001(self):
print(my_sum(5, 6))
def test_002(self):
print(my_sum(0, 3))
fixture小结
- 一定要在继承于unittest.TestCase这个类的子类中使用
- setUP,tearDown, 每个方法执行开始和完毕后自动调用
- setUPClass, tearDownClass, 每个类开始时候和结束时候自动调用
- setUpModule, tearDownModule,每个py文件开始和结束的时候自动调用
assert断言
让程序判断测试用例执行是否符合预期
常用方法:assertEqual(参数1,参数2)
- 如果参数1与参数2的值相等,则断言成功,否则断言失败。
- 两个参数有一个存放实际结果,一个存放预期结果。
常用方法:assertIn(参数1,参数2)
-
如果参数1在参数2里面,断言通过,否则断言失败
参数化
测试用例中使用参数化的场景:多个测试用例代码相同,只是测试数据不同,预期结果不同,可以把多个测试用例通过参数化技术合并 为一个测试用例
步骤:
- 导入from parameterized import parameterized
- 在方法上面用@parameterized.expand()修饰方法
- expand()里面是一个列表
- 列表里面放多个元组,每个列表中的成员就代表调用方法使用的实参
- 列表中有几个元组方法就会被调用几次
import unittest
from parameterized import parameterized
def my_sum(a, b):
return a + b
class my_test1(unittest.TestCase):
@parameterized.expand([(1, 2, 3), (5, 6, 110)])
def test_001(self, a, b, c):
# a是my_sum()方法的第一个参数
# b是my_sum()方法的第二个参数
# c是预期结果
num = my_sum(a, b)
self.assertEqual(num, c) # num是实际数值,C是预期数值
# 实际结果与预期结果相符,代表测试用例测试通过
# 不相符代表测试用例测试失败
跳过:
方法:unitTest.skip
可以通过@unittest.skip跳过指定的方法或者函数
import unittest
from parameterized import parameterized
def my_sum(a, b):
return a + b
class my_test1(unittest.TestCase):
@parameterized.expand([(1, 2, 3), (5, 6, 110)])
def test_001(self, a, b, c):
num = my_sum(a, b)
self.assertEqual(num, c) # num是实际数值,C是预期数值
@unittest.skip
def test_002(self, ):
print("跳过")
HTML报告
通过TextTestRunner生成测试报告
- 在实例化TextTestRunner对象的时候,需要写参数
- runner = HTMLTestRunner(stream=file, title="我的第一个html测试报告",verbosity=2)
- stream=file, verbosity=2,file代表用open打开的一个文件verbosity=2,固定
第一步:用open,w方式打开测试报告文件
第二步:实例化TextTestRunner对象
第三步调用对象的run方法执行测试套件
第四步:关闭open打开的文件
import unittest
# 用TestLoader对象的discover方法来自动查找py,自动加载py文件中的方法
# 第一个参数是从哪里找py文件,"."从当前目录开始查找py文件
# 第二个参数是指定py文件的文件名,可以用通配符
suite = unittest.TestLoader().discover(".", "my*.py")
# runner = unittest.TextTestRunner()
file = open("test01.txt", "w", encoding="utf8")
runner = unittest.TextTestRunner(stream=file, verbosity=2)
runner.run(suite)
HTML测试报告:
- 把文件HTMLTestRunner.py拷贝到项目目录下
- 在代码中导入模块from HTMLTestRunner import HTMLTestRunner
- 调用HTMLTestRunner(stream=file, title="我的第一个html测试报告")
- 第一个参数是用open打开的文件, 打开的文件扩展名一定是.html;open打开文件的时候,用wb,不用指定字符集
- 调用runner对象的run方法执行测试套件
- 关闭open打开的文件
# 测试套件
# 导包
import unittest
from HTMLTestRunner import HTMLTestRunner
# 加载unitTest_testCase.py模块下的所有测试用例
suite = unittest.TestLoader().discover(".", "unitTest_testCase.py")
# 用open,w方式打开测试报告文件
file = open("test01.html", "wb") # open打开文件的时候,用wb,不用指定字符集
runner = HTMLTestRunner(stream=file, title="我的第一个html测试报告")
# 执行测试套件
runner.run(suite)
# 关闭open打开的文件
file.close()