当前位置: 首页 > news >正文

不拼花哨,只拼实用:unittest指南,干货为王!

Python为开发者提供了内置的单元测试框架 unittest,它是一种强大的工具,能够有效地编写和执行单元测试。unittest 提供了完整的测试结构,支持自动化测试的执行,能够对测试用例进行组织,并且提供了丰富的断言方法。最终,unittest 会生成详细的测试报告,这个框架非常简单且易于使用。

unittest核心概念
在 unittest 中,有四个核心概念:

TestCase(测试用例):每个测试用例实例用于封装一个或多个测试函数。
TestSuite(测试套件):这是多个测试用例的集合,用于组织和执行多个测试用例。
TestLoader(测试加载器):这是一个用于将测试用例加载到测试套件中的工具。
TextTestRunner(测试运行器):这是用于执行测试用例的运行器,负责运行测试并生成结果报告。
Fixture(环境管理机制):这是测试用例的环境搭建和销毁部分,包括前置条件和后置条件。

unittest的工作流程
编写继承自 unittest.TestCase 的测试用例类,其中每个测试函数都是一个独立的测试用例。
使用 TestLoader 加载测试用例,并将它们组织成 TestSuite 对象。
使用 TestRunner 运行 TestSuite 中的测试用例,并输出测试结果。

使用unittest初级指南
导入 unittest 模块以及被测试的文件或类。
创建一个测试类,并继承 unittest.TestCase,所有自定义的单元测试类都要继承它,作为基类。
重写 setUp 和 tearDown 方法,用于初始化和清理测试环境(如果有必要)。
定义测试函数,函数名以 test_ 开头,这样才能被识别并执行。
在测试函数中使用断言来判断测试结果是否符合预期。
调用 unittest.main() 方法运行测试用例,按照函数名的排序执行测试。
以下是一个简单的例子:

import unittestdef login(username, password):if username == 'kira' and password == '123':res = {"code": 200, "msg": "登录成功"}return resreturn {"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()

以上是一个简单的测试用例,包含了两个测试函数。运行脚本将输出测试结果。

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:632880530

unittest核心概念

测试脚手架

测试脚手架 是测试用例的前置条件和后置条件,确保测试环境的初始化和清理,从而保证测试的准确性和可靠性。

import unittestclass MyTestCase(unittest.TestCase):@classmethoddef setUpClass(cls):# 类级别的前置条件设置,整个类运行最先只执行一次print("setUpClass")@classmethoddef 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()

setUp():每个测试方法运行前执行,用于测试前置的初始化工作。
tearDown():每个测试方法结束后执行,用于测试后的清理工作。
setUpClass():所有的测试方法运行前执行,用于单元测试类运行前的准备工作。使用 @classmethod 装饰器装饰,整个测试类运行过程中只会执行一次。
tearDownClass():所有的测试方法结束后执行,用于单元测试类运行后的清理工作。使用 @classmethod 装饰器装饰,整个测试类运行过程中只会执行一次。
测试用例
测试用例 是最小的测试单元,用于检测特定的输入集合的特定的返回值。unittest 提供了 TestCase 基类,所有的测试类都需要继承该基类,而在该类下的函数如果以 test_ 开头,则被标识为测试函数:

class MyTestCase(unittest.TestCase):def test_addition(self):result = 2 + 3self.assertEqual(result, 5)  # 使用断言方法验证结果是否相等def test_subtraction(self):result = 5 - 3self.assertTrue(result == 2)  # 使用断言方法验证结果是否为True# 更多测试用例函数...

断言方法
以下是常用的断言方法:

assertEqual(a, b, msg=None):验证 a 等于 b。
assertNotEqual(a, b):验证 a 不等于 b。
assertTrue(x):验证 x 是否为 True。
assertFalse(x):验证 x 是否为 False。
assertIs(a, b):验证 a 是否是 b。
assertIsNot(a, b):验证 a 是否不是 b。
assertIsNone(x):验证 x 是否为 None。
assertIsNotNone(x):验证 x 是否不为 None。
assertIn(a, b):验证 a 是否在 b 中。
assertNotIn(a, b):验证 a 是否不在 b 中。
assertIsInstance(a, b):验证 a 是否是 b 类型的实例。
assertNotIsInstance(a, b):验证 a 是否不是 b 类型的实例。
可以使用这些方法进行断言,也可以直接使用原生的assert来断言,如果断言失败,测试用例会被定义为执行失败。

忽略特定测试方法
unittest 提供了一些方法来跳过特定的测试用例:

@unittest.skip(reason):强制跳过,reason 是跳过的原因。
@unittest.skipIf(condition, reason):当 condition 为 True 时跳过。
@unittest.skipUnless(condition, reason):当 condition 为 False 时跳过。
@unittest.expectedFailure:如果测试失败,这个测试用例不会计入失败的统计。
使用实例方法:self.skipTest() 使用和上述类似。

import sys
import 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)

测试套件
测试套件用于收集和组织多个测试用例,便于集中执行。

通过 unittest.main() 方法直接加载单元测试的测试模块,这是一种简单的加载方式。所有测试用例的执行顺序按照方法名的字符串表示的 ASCII 码升序排序,通过命名时使用 test_01_xxx 来指定执行顺序。
将所有的单元测试用例 TestCase 加载到测试套件 Test Suite 集合中,然后一次性加载所有测试对象。
通过 TestSuite 对象收集
此方式适用于需要自定义组合特定测试用例的情况。

import unittestclass MyTestCase(unittest.TestCase):def test_addition(self):result = 2 + 3self.assertEqual(result, 5)def suite():suite = unittest.TestSuite()suite.addTest(MyTestCase('test_addition'))return suiteif __name__ == '__main__':runner = unittest.TextTestRunner()runner.run(suite())

通过 TestLoader 对象收集

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 + 3self.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)

测试运行器

测试运行器是用于执行和输出测试结果的组件。常用的运行器有:

  • unittest.TextTestRunner:这是 unittest 框架中默认的测试运行器,会在命令行输出测试结果。通过调用 run() 方法运行测试套件,并将测试结果打印到控制台。
import unittestif __name__ == '__main__':loader = unittest.defaultTestLoadersuite = loader.discover(start_dir='tests', pattern='test_*.py')runner = unittest.TextTestRunner()result = runner.run(suite)
  • HTMLTestRunner:这是一个第三方库,能够生成漂亮的 HTML 测试报告,需要进行安装。你可以通过搜索获取相关文件进行安装。
import unittest
from HTMLTestRunner import HTMLTestRunnerif __name__ == '__main__':loader = unittest.defaultTestLoadersuite = 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)
  • XMLTestRunner:这是另一个第三方库,用于生成 XML 格式的测试报告。
import unittest
from xmlrunner import XMLTestRunnerif __name__ == '__main__':loader = unittest.defaultTestLoadersuite = 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.defaultTestLoadersuite = loader.discover(start_dir='tests', pattern='test_*.py')runner = MyTestRunner()result = runner.run(suite)

通常使用 HTMLTestRunner 即可满足需求,它非常易用。

实战一个测试案例

假设有一个测试函数 login

# login.py
def login(username, password):"""模拟登录校验"""if username == 'kira' and password == '123456':return {"code": 0, "msg": "登录成功"}else:return {"code": 1, "msg": "账号或密码不正确"}

设计用例

根据函数的参数和逻辑,设计如下用例

编写测试用例并运行

import unittest
from 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)

下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

 

资料获取方式 :

http://www.lryc.cn/news/143792.html

相关文章:

  • mysql 获取json数组中某个字段根据下标
  • 深入理解Redis缓存穿透、击穿、雪崩及解决方案
  • java八股文面试[java基础]——字节码
  • 新能源汽车技术的最新进展和未来趋势
  • 知虾shopee数据分析工具:shopee出单的商机利器
  • python——ydata-profiling介绍与使用
  • (纯c)数据结构之------>链表(详解)
  • postman接口自动化测试框架实战!
  • Apache Doris 入门教程35:多源数据目录
  • 响应式web-PC端web与移动端web(H5)兼容适配 选型方案
  • Redis持久化之RDB解读
  • 四维图新 minemap实现地图漫游效果
  • centos7安装MySQL8
  • 【IMX6ULL驱动开发学习】10.Linux I2C驱动实战:AT24C02驱动设计流程
  • 【C++】详解声明和定义
  • 掌握C/C++协程编程,轻松驾驭并发编程世界
  • MyBatis-Plus的分页配置类
  • 排序算法-选择排序(Java)
  • SpringBoot 怎么返回html界面
  • watch computed 和 method
  • 数据结构,线性表有哪些
  • 服务间通过Feign相互调用报错,参数是MultiparFile、参数是POJO报错
  • Flutter系列文章-Flutter应用优化
  • opencv案例03 -基于OpenCV实现二维码生成,发现,定位,识别
  • 叠螺式污泥脱水机的要点及价格分析
  • Visual Studio中Linux开发头文件intellisense问题的解决办法
  • 如何以CPU方式启动Stable Diffusion WebUI?
  • HTTP 框架修炼之道 | 青训营
  • 【活动】怎么维护电脑?
  • Linux安装Docker