博客
关于我
搞定接口测试,从吃透【unittest测试框架】开始学
阅读量:757 次
发布时间:2019-03-22

本文共 4524 字,大约阅读时间需要 15 分钟。

什么是unittest?如何在Python中使用它?

unittest是Python内置的单元测试框架,基于Java的junit测试框架。它是Python程序员进行接口自动化测试、功能测试的首选工具之一。许多开发者会选择unittest来编写测试用例,因为它开源且无需安装,灵活性高。

下面,我将为你展示如何在Python中使用unittest以及它的使用场景。


为什么选择unittest?

unittest提供了一系列工具,帮助开发者更好地组织和运行测试用例。相比于不使用测试框架的做法,使用unittest可以解决以下问题:

  • 用例互不干扰:每一个用例都是一个独立的操作,不会干扰到其他用例的执行。
  • 提供丰富的断言功能:unittest内置了多种断言方法,支持值比较、类型检查、包含操作、空值判断等。
  • 测试准备和清理:通过setUp和tearDown方法,可以在每个用例、每个类、每个模块添加自定义操作。
  • 支持批量执行:通过discover工具,可以自动遍历并执行所有测试用例,适合大规模项目。
  • 灵活的用例组织:可以通过TestSuite和TestLoader将用例组织在不同的层级,方便管理。

  • unittest的核心组成部分

    unittest主要由以下几个部分组成:

    • TestCase:所有测试类需要继承自unittest.TestCase才能获得测试相关的属性和方法。
    • TestSuite:测试套件,用于将用例组织在一起。通过addTest方法可以添加单个用例或整个测试类。
    • TestLoader:用例加载器,负责从文件中加载测试用例。
    • TextTestRunner:用来执行测试套件,结果会保存在TextTestResult对象中。
    • TestResult:测试结果对象,用于记录和显示测试的执行结果。

    Use Case: 接口自动化测试

    下面我们以一个接口自动化测试的案例为例,来展示如何编写ittest用例。

    示例:测试用户登录功能

    我们先创建一个名为test_user_login.py的文件。

    文件内容:

    import unittestimport requestsclass TestUserLogin(unittest.TestCase):    # 用户登录接口地址    url = 'http://example.com/api/user/login/'    def test_user_login(self):        data = {            "username": "testuser",            "password": "testpass123"        }        response = requests.post(url=self.url, json=data)        # 断言响应状态码        self.assertEqual(response.status_code, 200)    def test_user_password_error(self):        data = {            "username": "testuser",            "password": "wrongpassword"        }        response = requests.post(url=self.url, json=data)        # 断言响应内容        self.assertIn("密码错误", response.text)if __name__ == '__main__':    unittest.main(verbose=2)

    在这个测试用例中:

  • 测试类TestUserLogin继承自unittest.TestCase
  • 每个用例以test_开头,方法名称也要遵循命名规则。
  • 使用了两种不同的断言方法:
    • assertEqual 用于状态码比较。
    • .assertIn 用于检查响应内容。

  • unittest断言方法

    unittest提供了丰富的断言方法,可以满足大多数测试需求。以下是一些常用的断言方法:

    • 相等性断言

      • assertEqual(a, b):断言两个值相等。
      • assertNotEqual(a, b):断言两个值不等。
    • 对象断言

      • assertedIs(a, b):断言ab是同一个对象。
      • assertIsNot(a, b):断言ab不相等。
    • 包含性断言

      • assertIn(a, b):断言a包含在b中。
      • assertNotIn(a, b):断言a不包含在b中。
    • 数量、类型和范围的断言

      • assertGreater(a, b):断言a大于b
      • assertLess(a, b):断言a小于b
      • assertGreaterEqual(a, b):断言a大于等于b
    • 真假断言

      • assertTrue(a):断言a为真。
      • assertFalse(a):断言a为假。
    • 类型判定

      • assertIsInstance(a, Type):断言aType的实例。

    如何编写更好的测试用例

    编写一个优质的测试用例需要以下几个步骤:

  • 数据准备:测试数据可以手动准备,或者通过代码自动化。
  • 环境检查:在发送请求前,检查当前环境是否符合预期。对于依赖于数据库的接口,需要进行环境检查。
  • 发送请求:使用HTTP客户端(例如requests库)发送请求。
  • 断言响应:根据预期结果,使用断言方法验证_api返回值。
  • 数据库断言:如果接口操作了数据库,应进行数据库断言。
  • 数据清理:断言结束后,需要对数据库或资源进行清理。

  • 用例组织与运行方式

    除了直接使用unittest.main()运行测试类之外,我们可以通过TestSuiteTestLoader灵活组织用例。

    方法一:使用defaultTestLoader

    import unittestdef test_function():    # 定义用例逻辑    pass# 创建测试类class TestMyFunction(unittest.TestCase):    def test_function(self):        # 测试逻辑        pass# 执行所有测试(从当前目录查找以test开头的*.py文件)unittest.main()

    方法二:手动创建TestSuite

    import unittestfrom test_user_login import TestUserLogin# 创建测试套件suite = unittest.TestSuite()# 添加测试用例suite.addTests([TestUserLogin('test_user_login_normal'), TestUserLogin('test_user_login_password_error')])# 执行测试套件unittest TextTestRunner(verbosity=3).run(suite)

    方法三:使用discover遍历测试用例

    import unittest# 创建测试套件suite = unittest.defaultTestLoader.discover('.', pattern='test*.py')# 执行测试unittest.TextTestRunner(verbosity=3).run(suite)

    细节说明:如何使用 TestLoader 进行测试

    TestLoader 是一个灵活的测试用例加载器,可以根据需要添加不同的加载策略。

    示例:从多个文件中加载测试用例。

    import unittestfrom test_user_login import TestUserLoginfrom test_user_reg import TestUserReg# 创建两个测试套件suite1 = unittest.TestSuite()suite1.addTest(TestUserLogin('test_user_login_normal'))suite2 = unittest.TestSuite()suite2.addTests([    TestUserReg('test_user_reg_normal'),    TestUserReg('test_user_reg_password_error')])# 创建一个包含两个测试套件的测试套件main_suite = unittest.TestSuite([suite1, suite2])# 运行所有用例unittest.TextTestRunner(verbosity=2).run(main_suite)

    如何在代码中使用装饰器进行单元测试?

    假设你有一个依赖于外部资源的测试用例,且不想重复运行。可以使用@skipIf装饰器跳过这些测试。

    from unittest import TestCasefrom unittest.skip import skipIfclass MyTest(TestCase):    @skipIf(lambda: False, "跳过了某些测试")    def test_something(self):        # realize的测试逻辑        pass

    你也可以通过配置python -m unittest --skipUvs参数,跳过特定的测试用例。


    if name == 'main'

    在unittest中,if __name__ == '__main__': 是执行测试的标准做法。它确保当外部模块调用该测试类时,不会执行main()函数。

    示例:

    import unittestclass TestMyClass(unittest.TestCase):    def test_my_method(self):        # 测试逻辑        passif __name__ == '__main__':    unittest.main()

    如何避免运行重复的测试用例

    在某些情况下,我们可能需要跳过某些测试。可以使用unittest.skip装饰器。

    from unittest import TestCase, skipIfimport platformclass MyTest(TestCase):    @skipIf(platform.system() != 'Linux', "仅在Linux上运行")    def test_something(self):        # 测试逻辑        pass

    总结

    通过本文的内容,你已经掌握了unittest的使用方法。无论是编写单个用例,还是组织成复杂的测试套件,unittest都能满足需求。如果你在实际开发中遇到问题,可以参考官方文档进一步学习。

    转载地址:http://fiwwk.baihongyu.com/

    你可能感兴趣的文章
    MySQL Troubleshoting:Waiting on query cache mutex
    查看>>
    mysql union orderby 无效
    查看>>
    mysql v$session_Oracle 进程查看v$session
    查看>>
    mysql where中如何判断不为空
    查看>>
    MySQL Workbench 使用手册:从入门到精通
    查看>>
    MySQL Workbench 数据库建模详解:从设计到实践
    查看>>
    MySQL Workbench 数据建模全解析:从基础到实践
    查看>>
    mysql workbench6.3.5_MySQL Workbench
    查看>>
    MySQL Workbench安装教程以及菜单汉化
    查看>>
    MySQL Xtrabackup 安装、备份、恢复
    查看>>
    mysql [Err] 1436 - Thread stack overrun: 129464 bytes used of a 286720 byte stack, and 160000 bytes
    查看>>
    MySQL _ MySQL常用操作
    查看>>
    MySQL – 导出数据成csv
    查看>>
    MySQL —— 在CentOS9下安装MySQL
    查看>>
    MySQL —— 视图
    查看>>
    mysql 不区分大小写
    查看>>
    mysql 两列互转
    查看>>
    MySQL 中开启二进制日志(Binlog)
    查看>>
    MySQL 中文问题
    查看>>
    MySQL 中日志的面试题总结
    查看>>