最近接触到Python的测试框架unittest, 浅浅的学习了一下。
unittest和HTMLTestRunner搭配,可以完成自动化测试的功能并生成自动化测试报告。
一. 简介
-
Python内置的unittest模块,用于编写和执行单元测试。
HTMLTestRunner 是一个用于生成自动化测试报告的工具,扩展了 unittest 模块。它可以生成详细的 HTML 测试报告,包含测试结果、用例数、成功率等信息。
HTMLTestRunner非内置模块,需要另外安装。安装方式如下: pip install HTMLTestRunner-Python3 -
unittest一些很重要的概念:
test fixture
A test fixture represents the preparation needed to perform one or more tests, and any associated cleanup actions.
This may involve, for example, creating temporary or proxy databases, directories, or starting a server process.test case
A test case is the individual unit of testing. It checks for a specific response to a particular set of inputs.
unittest provides a base class, TestCase, which may be used to create new test cases.test suite
A test suite is a collection of test cases, test suites, or both. It is used to aggregate tests that should be executed together.test runner
A test runner is a component which orchestrates the execution of tests and provides the outcome to the user.
The runner may use a graphical interface, a textual interface, or return a special value to indicate the results of executing the tests. -
A testcase is created by subclassing unittest.TestCase. The three individual tests are defined with methods whose names start with the letters test.
This naming convention informs the test runner about which methods represent tests. -
assert
The TestCase class provides several assert methods to check for and report failures.
The following table lists the most commonly used methods (see the tables below for more assert methods):
二. 代码
代码示例运行环境:
win10 + Python3.11.5 + IDIE
代码示例
点击查看代码
unittest_sample.py:import unittest
from HTMLTestRunner import HTMLTestRunner
import timeclass Student(object):def __init__(self, age, weight):self.__age = ageself.__weight = weightdef getAge(self):return self.__agedef getWeight(self):return self.__weightdef setAge(self, age):self.__age = agereturn Truedef setWeight(self, weight):self.__weight = weightreturn Trueclass Calculator(object):@classmethoddef add(cls, num1, num2):return num1 + num2@classmethoddef sub(cls, num1, num2):return num2 - num1@classmethoddef mul(cls, num1, num2):return num1 * num2@classmethoddef div(cls, num1, num2):return num2 / num1def getTestReportNameWithTimestamp():now_time = time.strftime('%Y%m%d%H%M%S')testReportName = './result_' + now_time + '.html'return testReportNameclass TestStudent(unittest.TestCase):@classmethoddef setUpClass(cls):print('TestStudent setUpClass ...')cls.stu = Student(10, 20)@classmethoddef tearDownClass(cls):print('TestStudent tearDownClass ...')def setUp(self):print('TestStudent setUp ...')def tearDown(self):print('TestStudent tearDown ...')def test_get_age(self):''' verify age '''print('testcase get age')self.assertEqual(self.stu.getAge(), 10)def test_get_weight(self):''' verify weight '''print('testcase get weight')self.assertEqual(self.stu.getWeight(), 20)def test_set_age(self):''' verify change age '''print('testcase set age')self.stu.setAge(20)self.assertEqual(self.stu.getAge(), 20)def test_set_weight(self):''' verify change weight '''print('testcase get weight')self.stu.setWeight(100)self.assertTrue(self.stu.getWeight(), 100)class TestCalculator(unittest.TestCase):@classmethoddef setUpClass(cls):print('TestCalculator setUpClass')@classmethoddef tearDownClass(cls):print('TestCalculator tearDownClass')def setUp(self):print('TestCalculator setUp')def tearDown(self):print('TestCalculator tearDown')def test_add(self):self.assertEqual(Calculator.add(1, 2), 3)def test_sub(self):self.assertEqual(Calculator.sub(3, 5), 2)def test_mul(self):self.assertEqual(Calculator.mul(2, 8), 16)def test_div(self):self.assertEqual(Calculator.div(5, 100), 20)def run_unittest():unittest.main()def run_suite_addTest():suite_obj = unittest.TestSuite()suite_obj.addTest(TestStudent("test_get_age"))suite_obj.addTest(TestStudent("test_get_weight"))suite_obj.addTest(TestStudent("test_set_age"))suite_obj.addTest(TestStudent("test_set_weight"))testReportName = getTestReportNameWithTimestamp()with open(testReportName, 'wb') as fp:runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='Test Student', description='TestCase List')runner.run(suite_obj)def run_suite_addTests():map_obj = map(TestStudent, ['test_get_age', 'test_get_weight', 'test_set_age', 'test_set_weight', 'test_aget_weight'])suite_obj = unittest.TestSuite()suite_obj.addTests(map_obj)testReportName = getTestReportNameWithTimestamp()with open(testReportName, 'wb') as fp:runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='Test Student', description='TestCase List')runner.run(suite_obj)def run_testloader():suite = unittest.TestSuite()testCaseSuite1 = unittest.TestLoader().loadTestsFromTestCase(TestStudent)suite.addTests(testCaseSuite1)testCaseSuite2 = unittest.TestLoader().loadTestsFromTestCase(TestCalculator)suite.addTests(testCaseSuite2)testReportName = getTestReportNameWithTimestamp()with open(testReportName, 'wb') as fp:runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='Test Result Report', description='TestCase List')runner.run(suite)if __name__ == '__main__':run_testloader()
执行后生成的自动化测试报告如下:
参考 https://docs.python.org/3/library/unittest.html