Python为开发者提供了内置的单元测试框架 unittest,它是一种强大的工具,能够有效地编写和执行单元测试。unittest 提供了完整的测试结构,支持自动化测试的执行,能够对测试用例进行组织,并且提供了丰富的断言方法。最终,unittest 会生成详细的测试报告,这个框架非常简单且易于使用。
在 unittest 中,有几个核心概念:
以下是一个简单的例子:
import unittestdef login(username, password): if username == 'kira' and password == '123': res = {"code": 200, "msg": "登录成功"} return res return {"code": 400, "msg": "登录失败"}class TestLogin(unittest.TestCase): def test_login_success(self): """测试登录成功""" test_data = {"username": "kira", "password": "test"} expect_data = {"code": 200, "msg": "登录成功"} res = login(**test_data) self.assertEqual(res, expect_data) def test_login_error_with_error_password(self): """账号正确,密码错误,登录失败""" test_data = {"username": "kira", "password": "12345"} expect_data = {"code": 400, "msg": "登录失败"} res = login(**test_data) self.assertEqual(res, expect_data) # 更多测试函数类似...if __name__ == '__main__': unittest.main()
以上是一个简单的测试用例,包含了两个测试函数。运行脚本将输出测试结果。
测试脚手架 是测试用例的前置条件和后置条件,确保测试环境的初始化和清理,从而保证测试的准确性和可靠性。
import unittestclass MyTestCase(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_example(self): # 测试用例 print("test_example")if __name__ == "__main__": unittest.main()
测试用例 是最小的测试单元,用于检测特定的输入集合的特定的返回值。unittest 提供了 TestCase 基类,所有的测试类都需要继承该基类,而在该类下的函数如果以 test_ 开头,则被标识为测试函数:
class MyTestCase(unittest.TestCase): def test_addition(self): result = 2 + 3 self.assertEqual(result, 5) # 使用断言方法验证结果是否相等 def test_subtraction(self): result = 5 - 3 self.assertTrue(result == 2) # 使用断言方法验证结果是否为True # 更多测试用例函数...
以下是常用的断言方法:
可以使用这些方法进行断言,也可以直接使用原生的assert来断言,如果断言失败,测试用例会被定义为执行失败。
unittest 提供了一些方法来跳过特定的测试用例:
使用实例方法:self.skipTest() 使用和上述类似。
import sysimport unittestclass Test1(unittest.TestCase): @unittest.expectedFailure # 即使失败也会被计为成功的用例 def test_1(self): assert 1 + 1 == 3 @unittest.skip('无条件跳过') # 不管什么情况都会进行跳过 def test_2(self): print("2+2...", 4) @unittest.skipIf(sys.platform == "win32", "跳过") # 如果系统平台为 Windows 则跳过 def test_3(self): print("3+3...", 6) @unittest.skipUnless(sys.platform == "win32", "跳过") # 除非系统平台为 Windows,否则跳过 def test_4(self): print("4+4...", 8) def test_5(self): self.skipTest("跳过") print("5+5...", 10)if __name__ == "__main__": unittest.main(verbosity=2)
测试套件用于收集和组织多个测试用例,便于集中执行。
此方式适用于需要自定义组合特定测试用例的情况。
import unittestclass MyTestCase(unittest.TestCase): def test_addition(self): result = 2 + 3 self.assertEqual(result, 5)def suite(): suite = unittest.TestSuite() suite.addTest(MyTestCase('test_addition')) return suiteif __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(suite())
TestLoader 是 unittest 框架提供的加载测试用例的类。
import unittestif __name__ == '__main__': loader = unittest.defaultTestLoader # 自动加载当前模块中所有以 'test_' 开头的测试用例函数 suite = loader.loadTestsFromModule(__name__) runner = unittest.TextTestRunner() runner.run(suite)
import unittestclass MyTestCase(unittest.TestCase): def test_addition(self): result = 2 + 3 self.assertEqual(result, 5)if __name__ == '__main__': loader = unittest.defaultTestLoader # 自动加载 MyTestCase 类中的所有测试用例 suite = loader.loadTestsFromTestCase(MyTestCase) runner = unittest.TextTestRunner() runner.run(suite)
import unittestif __name__ == '__main__': loader = unittest.defaultTestLoader # 自动加载指定名称的测试用例 suite = loader.loadTestsFromName('module.MyTestCase.test_addition') runner = unittest.TextTestRunner() runner.run(suite)
import unittestif __name__ == '__main__': loader = unittest.defaultTestLoader # 自动发现并加载指定目录中的测试用例模块 suite = loader.discover(start_dir='test_directory', pattern='test_*.py', top_level_dir=None) runner = unittest.TextTestRunner() runner.run(suite)
测试运行器是用于执行和输出测试结果的组件。常用的运行器有:
import unittestif __name__ == '__main__': loader = unittest.defaultTestLoader suite = loader.discover(start_dir='tests', pattern='test_*.py') runner = unittest.TextTestRunner() result = runner.run(suite)
import unittestfrom HTMLTestRunner import HTMLTestRunnerif __name__ == '__main__': loader = unittest.defaultTestLoader suite = loader.discover(start_dir='tests', pattern='test_*.py') with open('test_report.html', 'wb') as report_file: runner = HTMLTestRunner(stream=report_file, title='Test Report', description='Test Results') result = runner.run(suite)
import unittestfrom xmlrunner import XMLTestRunnerif __name__ == '__main__': loader = unittest.defaultTestLoader suite = loader.discover(start_dir='tests', pattern='test_*.py') with open('test_report.xml', 'wb') as report_file: runner = XMLTestRunner(output=report_file) result = runner.run(suite)
你也可以自定义测试运行器。继承 unittest.TestRunner 类并实现 run() 方法,以创建自己的测试运行器。
import unittestclass MyTestRunner(unittest.TextTestRunner): def run(self, test): print("Running tests with MyTestRunner") result = super().run(test) return resultif __name__ == '__main__': loader = unittest.defaultTestLoader suite = loader.discover(start_dir='tests', pattern='test_*.py') runner = MyTestRunner() result = runner.run(suite)
通常使用 HTMLTestRunner 即可满足需求,它非常易用。
假设有一个测试函数 login:
# login.pydef login(username, password): """模拟登录校验""" if username == 'kira' and password == '123456': return {"code": 0, "msg": "登录成功"} else: return {"code": 1, "msg": "账号或密码不正确"}
根据函数的参数和逻辑,设计如下用例:
import unittestfrom login import loginclass TestLogin(unittest.TestCase): def test_login_correct(self): """测试账号密码正确""" test_data = {"username": "kira", "password": "123456"} expect_data = {"code": 0, "msg": "登录成功"} res = login(**test_data) self.assertEqual(res, expect_data) def test_login_wrong_password(self): """测试账号正确密码不正确""" test_data = {"username": "kira", "password": "123"} expect_data = {"code": 1, "msg": "账号或密码不正确"} res = login(**test_data) self.assertEqual(res, expect_data) def test_login_wrong_username(self): """测试账号错误密码正确""" test_data = {"username": "kir", "password": "123456"} expect_data = {"code": 1, "msg": "账号或密码不正确"} res = login(**test_data) self.assertEqual(res, expect_data)if __name__ == '__main__': unittest.main()
这是一个简单的测试用例,包含了三个测试函数。运行测试用例后,会输出测试结果,看完是否觉得unittest非常简单易用。ner.run(suite)
本文链接:http://www.28at.com/showinfo-26-10432-0.html不拼花哨,只拼实用:Unittest指南,干货为王!
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 基于范围的 for 循环:现代 C++ 循环控制的新思维
下一篇: 2023年需求最大的八种编程语言