1. unittest简介unittest 是一个Python单元测试框架。它受到 JUnit 的启发,与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化,配置共享和关机代码测试。支持将测试样例聚合到测试集中,并将测试与报告框架独立。
主要参考 unittest - 单元测试框架 。
2. 脚本编写新建一个 tests/test_demo.py 脚本,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import unittestclass TestStringMethods (unittest.TestCase): def test_upper (self ): self .assertEqual('foo' .upper(), 'FOO' ) def test_isupper (self ): self .assertTrue('FOO' .isupper()) self .assertFalse('Foo' .isupper()) def test_split (self ): s = 'hello world' self .assertEqual(s.split(), ['hello' , 'world' ]) with self .assertRaises(TypeError): s.split(2 ) if __name__ == '__main__' : unittest.main()
继承 unittest.TestCase 就创建了一个测试样例。上述三个独立的测试是三个类的方法,这些方法的命名都以 test 开头。 这个命名约定告诉测试运行者类的哪些方法表示测试。
每个测试的关键是:调用 assertEqual() 来检查预期的输出; 调用 assertTrue() 或 assertFalse() 来验证一个条件;调用 assertRaises() 来验证抛出了一个特定的异常。
通过 setUp() 和 tearDown() 方法,可以设置测试开始前与完成后需要执行的指令。
最后的代码块中,演示了运行测试的一个简单的方法。 unittest.main() 提供了一个测试脚本的命令行接口。
3. 执行测试方法一:脚本级别调用(直接运行脚本)
1 2 3 python tests/test_demo.py python tests/test_demo.py -v python -m unittest tests/test_demo.py
方法二:包、模块、类和方法级别调用
1 2 3 4 5 6 7 8 # 包级别调用(进入tests目录查找所有test_*.py文件并运行) python -m unittest discover -s tests -p "test_*.py" # 模块级别调用 python -m unittest tests.test_demo # 类级别调用 python -m unittest tests.test_demo.TestStringMethods # 方法级别调用 python -m unittest tests.test_demo.TestStringMethods.test_upper
4. 单元测试之mock单元测试时,如果涉及网络请求,建议使用mock模块来模拟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import jsonimport unittestfrom unittest import mockimport requestsdef request_system (method: str , url: str , data={} ): headers = { 'Content-Type' : 'application/json' } response = requests.request(method=method, url=url, headers=headers, data=json.dumps(data)) return response def login (username: str , password: str ): LOGIN_URL='http://127.0.0.1/login' data = { 'username' : username, 'password' : password } response = request_system('POST' , LOGIN_URL) if response.status == 200 : return json.loads(response.text) else : return None class TestMockMethods (unittest.TestCase): def test_request_system (self ): mock_response = mock.Mock() mock_response.status_code = 200 mock_response.text = json.dumps({"code" : 0 , "msg" :"success" }) request_system = mock.Mock(return_value=mock_response) response = request_system(method='POST' ,url='http://127.0.0.1/' ) print (response.status_code) print (response.text) self .assertEqual(200 , response.status_code) def test_login (self ): login = mock.Mock(return_value={"code" : 0 , "msg" :"success" }) data = login(username='voidking' ,password='voidking' ) print (data) self .assertEqual(0 , data.get('code' )) if __name__ == '__main__' : unittest.main()
这种模拟测试方式很巧妙,适合测试访问第三方接口,但是并不会真正发出请求。 另一个问题来了,Python怎么测试自己的接口?不知道。 想到以前使用Beego框架进行开发,它的单元测试就很巧妙,先在测试数据库插入数据,然后通过beego.BeeApp.Handlers.ServeHTTP(w, r)把自己临时启动起来,最后自己的单元测试调用自己的接口。 其中的关键在于把自己启动起来,理论上Python也能做到。
5. 后记python语言中的单元测试,除了使用unittest,还可以使用pytest。
FROM ChatGPT: unittest和pytest是Python中两种流行的单元测试框架,它们有以下主要区别:
语法:unittest是Python标准库中的测试框架,而pytest是一个第三方测试框架。因此,unittest的语法更加正式和严格,而pytest的语法更加简洁和灵活。 自动化:pytest比unittest更加自动化和智能化。pytest可以自动发现和运行测试用例,而unittest需要手动编写测试用例的套件和运行代码。 插件和扩展性:pytest提供了大量的插件和扩展功能,例如测试报告、代码覆盖率、测试并行化、测试重试等。相比之下,unittest的扩展性较弱,需要编写更多的自定义代码才能实现类似的功能。 断言:unittest和pytest都提供了丰富的断言方法,用于检查测试结果是否符合预期。但是,pytest的断言方法更加灵活和易于使用,例如使用assert语句进行断言。 用例参数化:pytest支持用例参数化,可以通过数据驱动的方式多次运行同一个测试用例,以检查不同的输入和输出。相比之下,unittest需要手动编写多个测试用例,以实现类似的功能。