1、UnitTest案例准备
通过PyCharm在工程目录下创建UnitTestDemo的PythonPackage。UnitTest的案例均存在UnitTestDemo下。
(1)、创建基础待测方法。在UnitTestDemo下新建mathfunc.py文件,代码如下:
# 加法,返回a+b的值
def add(a, b):
return a+b
# 减法,返回a-b的值
def minus(a,b):
return a-b
# 乘法,返回a*b的值
def multi(a, b):
return a*b
# 除法,返回a/b的值
def divide(a,b):
return a/b
(2)、设计测试用例。为前面的测试方法设计测试用例,在UnitTestDemo下创建test_mathfunc.py文件,代码如下:
import unittest
from UnitTestDemo.mathfunc import *
class TestMathFunc(unittest.TestCase):
"""测试mathfunc.py"""
def test_add(self):
"""测试加法add"""
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))
def test_minus(self):
"""测试减法minus"""
self.assertEqual(1, minus(3, 2))
def test_multi(self):
"""测试乘法multi"""
self.assertEqual(6, multi(2, 3))
def test_divide(self):
"""测试除法divide"""
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))
2、组织与设定测试用例的执行顺序
测试套件(TestSuite)是多个测试用例的集合,是针对被测程序的对应功能和模块创建的一组测试。
通过TestSuite()的addTest()方法手动把TestCase添加到TestSuite中,或通过Test Loader把TestCase自动加载到Test Suite中。首先创建测试套件,执行单挑用例调用addTest()方法,在UnitTestDemo下创建test_suite.py文件,代码如下:
import unittest
from UnitTestDemo.test_mathfunc import TestMathFunc
if __name__ == "__main__":
suite = unittest.TestSuite()
# addTest()添加单个TestSuit
suite.addTest(TestMathFunc("test_multi"))
runner = unittest.TextTestRunner()
runner.run(suite)
执行多条测试用例addTests()方法,test_suite,py文件下的代码如下:
import unittest
from UnitTestDemo.test_mathfunc import TestMathFunc
if __name__ == "__main__":
suite = unittest.TestSuite()
# addTest()添加单个TestSuit
# suite.addTest(TestMathFunc("test_multi"))
tests = [TestMathFunc("test_add"), TestMathFunc("test_divide"), TestMathFunc("test_minus")]
suite.addTests(tests)
runner = unittest.TextTestRunner()
runner.run(suite)
3、测试结果
TextTestRunner测试执行器负责测试执行调度并且生成测试结果给用户。可以将测试结果直接在控制台输出,也可以将测试结果输出到外部文件中。
有时候想要很清楚的看到每条用例执行的详细信息,可以通过设置verbosity参数来实现。verbosity默认值为1,可以设置为0 和2.
- 0(静默模式):只能获得总的测试用例数和总的结果;
- 1(默认模式):非常类似于静默模式,只是在每个成功的用例i起那面有个“.”,每个失败的用例起那面有个“E”;
- 2(详细模式):测试结果会显示每个测试用例的所有相关信息,并且在命令行里加入不同的参数可以起到一起的现过。
(1)将结果输出到IDE中。
verbosity=0,修改test_suite.py文件,代码如下:
import unittest
from UnitTestDemo.test_mathfunc import TestMathFunc
if __name__ == "__main__":
suite = unittest.TestSuite()
tests = [TestMathFunc("test_add"), TestMathFunc("test_divide"), TestMathFunc("test_minus")]
suite.addTests(tests)
runner = unittest.TextTestRunner(verbosity=0)
runner.run(suite)
运行结果:
设置verbosity=1,运行代码,结果如下:
设置verbosity=2,运行代码,结果如下:
(2)将结果输出到外部文件中
优化test_suite.py文件,通过stream参数将结果输出到外部文件中,优化test_suite.py文件后的代码如下:
import unittest
from UnitTestDemo.test_mathfunc import TestMathFunc
if __name__ == "__main__":
suite = unittest.TestSuite()
# addTest()添加单个TestSuit
# suite.addTest(TestMathFunc("test_multi"))
tests = [TestMathFunc("test_add"), TestMathFunc("test_divide"), TestMathFunc("test_minus")]
suite.addTests(tests)
# runner = unittest.TextTestRunner(verbosity=2)
# runner.run(suite)
with open("F:\\result.txt", "a") as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
运行后可以在F盘下发现多了一个result.txt文件。result.txt文件如下:
4、测试初始化与还原
通过使用Fixture,可以定义测试执行之前的准备工作和测试执行之后的清理工作。
- setUp():执行用例的前置条件,如建立数据库连接;
- tearDown():执行完用例后,为了不影响下一次用例的执行,一般有一个数据还原的过程,tearDown()是执行用例的后置条件,如关闭数据库连接。
下面结合案例,分别针对初始化与还原的接种方式进行详细介绍:
方式1:setUp()与tearDown()方法.
- setUp():每个测试case运行之前执行;
- tearDown():每个测试擦色运行完后执行。
修改UnitTestDemo创建的test_mathfunc.py文件,增加setUp()与tearDown()方法,代码如下:
import unittest
from UnitTestDemo.mathfunc import *
class TestMathFunc(unittest.TestCase):
"""测试mathfunc.py"""
# 在每条测试用例执行之前准备好测试环境
def setUp(self) -> None:
print("do something before test!")
def test_add(self):
"""测试加法add"""
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))
def test_minus(self):
"""测试减法minus"""
self.assertEqual(1, minus(3, 2))
def test_multi(self):
"""测试乘法multi"""
self.assertEqual(6, multi(2, 3))
def test_divide(self):
"""测试除法divide"""
self.assertEqual(2, divide(6, 3))
self.assertEqual(2, divide(5, 2))
# 在每条测试用例执行结束之后清理测试环境,还原到初始状态
def tearDown(self) -> None:
print("do something after test!")
方式2:setUpClass()与tearDownClass()方法
- setUpClass():必须使用@classmethod装饰器,初始化操作在所有case运行前只运行一次;
- testDownClass():必须使用@classmethod装饰器,还原操作在所有case运行后只运行一次。
修改UintTestDemo创建的test_mathtunc.py文件,在其中增加setUpClass()与tearDownClass()方法,代码如下:
import unittest
from UnitTestDemo.mathfunc import *
class TestMathFunc(unittest.TestCase):
"""测试mathfunc.py"""
# 在每条测试用例执行之前准备好测试环境
# def setUp(self) -> None:
# print("do something before test!")
@classmethod
def setUpClass(cls) -> None:
print("so something before testClass,only run once!")
def test_add(self):
"""测试加法add"""
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))
def test_minus(self):
"""测试减法minus"""
self.assertEqual(1, minus(3, 2))
def test_multi(self):
"""测试乘法multi"""
self.assertEqual(6, multi(2, 3))
def test_divide(self):
"""测试除法divide"""
self.assertEqual(2, divide(6, 3))
self.assertEqual(2, divide(5, 2))
# 在每条测试用例执行结束之后清理测试环境,还原到初始状态
# def tearDown(self):
# print("do something after test!")
# def tearDown(self) -> None:
# print("do something after test!")
@classmethod
def tearDownClass(cls) -> None:
print("do something after testClass,only run once")
运行结果:
5、测试用例跳过(skip)
在执行测试用例时,有时候有些用例时不需要执行的,UniteTest提供了跳过用例的方法。
- @unittest.skip(reason):强制跳过,不需要判断条件。reason参数时跳过原因的描述,必须填写。
- @unittest.skipUnless(condition,reason):condition为True时将跳过用例。
- @unittest.expectedFailure:如果test失败了,这个test不计入失败的case数目。
下面以@unittest.skipUnless为例,通过@unittest.skipUnless来跳过执行某条测试用例。修改test_mathfunc.py文件,修改后的代码如下:
import unittest
from UnitTestDemo.mathfunc import *
class TestMathFunc(unittest.TestCase):
"""测试mathfunc.py"""
def test_add(self):
"""测试加法add"""
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))
def test_minus(self):
"""测试减法minus"""
self.assertEqual(1, minus(3, 2))
def test_multi(self):
"""测试乘法multi"""
self.assertEqual(6, multi(2, 3))
def test_divide(self):
"""测试除法divide"""
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))
未添加test_mathfunc.py添加@unittest.skipUnless前,运行结果如下:
添加了@unittest.skipUnless后,运行结果如下:
可以看到test_add()用例未被执行,被跳过了,这是由于@unittest.skipUnless(condition,reason):当condition为False(@unittest.skipUnless(1 > 2, "don't run the case!"))时跳过了用例。