python 单元测试_python 单元测试 (unittest)

171f7486cdefab49048c4957bb2fa13e.png

测试驱动开发(TDD)流程和我们平时修改代码流程是一样的:

写代码->print找bug->修改->print找bug

TDD的流程:

4383318fcdf011614cd5560db74eb5e2.png

TDD三项法则:

  1. 在编写失败的单元测试之前,不要编写任何产品代码
  2. 只要有一个单元测试失败了,就不再写测试代码;
  3. 产品代码能够让当前失败的单元测试成功通过即可,不要多写

python 测试库 unittest,内置库,简洁易用。

直接举例子学习,如果测试下面的功能函数,将功能函数文件存储成mathfunc.py

def add(a, b):
    return a+b

def minus(a, b):
    return a-b

def multi(a, b):
    return a*b

def divide(a, b):
    return a/b

TestCase测试用例

通过测试用例对上面功能进行测试

import unittest

from mathfunc import add, minus, multi, divide


# 一个class继承了unittest.TestCase,便是一个测试用例
class TestMathFunc(unittest.TestCase):

    # TestCase基类方法,所有case执行之前自动执行
    @classmethod
    def setUpClass(cls) -> None: # 1
        print("这里是所有测试用例前的准备工作")

    # TestCase基类方法,所有case执行之后自动执行
    @classmethod
    def tearDownClass(cls) -> None: # 2
        print("这里是所有测试用例后的清理工作")

    # TestCase基类方法,每次执行case前自动执行
    def setUp(self) -> None: # 3
        print("这里是一个测试用例前的准备工作")

    # TestCase基类方法,每次执行case后自动执行
    def tearDown(self) -> None: # 4
        print("这里是一个测试用例后的准备工作")

    @unittest.skip("想临时跳过这个测试用例") # 5 
    def test_add(self):
        print("测试加法")
        self.assertEqual(3, add(1, 2))
        self.assertNotEqual(3, add(2, 2))  # 测试业务方法add

    def test_minus(self):
        print("测试减法")
        self.skipTest("跳过这个测试用例") # 6
        self.assertEqual(q, minus(3, 2))  # 测试业务方法multi

    def test_multi(self):
        print("测试乘法")
        self.assertEqual(6, multi(2, 3))  # 测试业务方法multi

    def test_divide(self):
        print("测试除法")
        self.assertEqual(2, divide(6, 3))  # 测试业务方法divide
        self.assertEqual(2.5, divide(5, 2))


if __name__ == '__main__':
    unittest.main(verbosity=2)

注意:

  1. 一个class继承了unittest.TestCase,便是一个测试用例
  2. 在每一个测试用例中在代码中 1, 2, 3, 4位置,重写以下函数:
    1. setUp()该测试用例执行前的设置工作、
    2. tearDown()该测试用例执行后的清理工作、
    3. setUpClass()所有测试用例前的设置工作、
    4. tearDownClass()所有测试用例执行后的清洗工作
  3. 每一个测试用例中可以通过skip,skipIf,skipUnless装饰器跳过某个测试函数,或者用TestCase.skipTest方法跳过测试函数,代码 5, 6 所示
  4. 每个测试方法均以 test 开头,否则是不被unittest识别的。每一个test开头的方法都会加载为独立的测试用例。执行顺序按函数名字典排序顺序依次执行
  5. 在unittest.main()中加 verbosity 参数可以控制输出的错误报告的详细程度,默认是 1,如果设为 0,则不输出每一用例的执行结果。如果参数为2则表示输出详细结果

TestSuite测试组

TestSuite用来控制多个测试用例和多个测试文件之间的测试顺序。(默认顺序是按函数名字典排序顺序依次执行)

import unittest

from tests.test_mathfunc import TestMathFunc
from tests.HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':
    suite = unittest.TestSuite()

    tests = [TestMathFunc("test_multi"), TestMathFunc("test_divide")]  # 添加测试用例列表
    # 添加一组测试用例
    suite.addTests(tests)
    # 添加一个测试用例
    suite.addTest(TestMathFunc("test_add"))

    # loadTestsFromName(),传入'模块名.TestCase名'
    # 传入单个
    suite.addTests(unittest.TestLoader().loadTestsFromName("test_mathfunc.TestMathFunc"))
    # 传入一个列表
    suite.addTests(unittest.TestLoader().loadTestsFromNames(["test_mathfunc.TestMathFunc"]))

    # loadTestsFromTestCase(),传入TestCase
    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
    # 

    # suite中也可以套suite

    # 将测试结果输出到测试报告中
    # with open('UnittestTextReport.txt', 'w', encoding="utf-8") as f:
    #     runner = unittest.TextTestRunner(stream=f, verbosity=2)
    #     runner.run(suite)

    # 将测试结果输出到测试报告html中
    # with open('HTMLReport.html', 'w') as f:
    #     runner = HTMLTestRunner(stream=f,
    #                             title='MathFunc Test Report',
    #                             description='generated by HTMLTestRunner.',
    #                             verbosity=2
    #                             )
    #     runner.run(suite)



    # 直接将结果输出控制台
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

注意:

  1. 多种方法将多个测试用例打包,一起测试
  2. 测试报告,可以打印txt, html和输出控制台。其中html的输出需要加载HTMLTestRunner.py模块

unittest ddt数据驱动

当我们想对一个功能使用多次测试数据时候,这时候使用DDT来完成,DDT是 “Data-Driven Tests”的缩写。

dd.ddt:

装饰类,也就是继承自TestCase的类。

ddt.data:

装饰测试方法。参数是一系列的值。

ddt.file_data:

装饰测试方法。参数是文件名。文件可以是json 或者 yaml类型。

注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。

如果文件中是列表,每个列表的值会作为测试用例参数,同时作为测试用例方法名后缀显示。

如果文件中是字典,字典的key会作为测试用例方法的后缀显示,字典的值会作为测试用例参数。

ddt.unpack:

传递的是复杂的数据结构时使用。比如使用元组或者列表,添加unpack之后,ddt会自动把元组或者列表对应到多个参数上。

直接举个用例子说明:

from mathfunc import add
import unittest
from ddt import ddt, data, unpack

@ddt  # 1
class TestMathFunc(unittest.TestCase):

    @data([1, 2, 3], [2, 2, 3])  # 2 测试两组数据
    @unpack  # 3 相当于把第一组数据[1, 2, 3]分别传参给num1, num2, correct
    def test_add(self, num1, num2, correct):
        print("测试加法")
        result = add(num1, num2)
        self.assertEqual(correct, result)  # 测试业务方法add


if __name__ == '__main__':
    unittest.main(verbosity=2)

注意:

  1. 代码1处装饰类,也就是继承自TestCase的类。
  2. 代码2处采用@ddt进行装饰,测试方法上装饰@data(),data可以是数值,也可以是字符串。测试方法后会被ddt加一个后缀,ddt会尝试把测试数据转化为后缀附在测试方法后,组成一个新的名字。
    data 可以传入列表,元组和字典都可以;
  3. 代码3就是解包,分别传参了到相应参数。

我们还可以直接传入json或者yaml文件,这里我们只用json举例子,新建一个文件test_data.json

[
  {
    "num1": 2,
    "num2": 3,
    "correct": 6
  },
  {
    "num1": 2,
    "num2": 3,
    "correct": 5
  }
]

file_data的用法学习

import unittest
from ddt import ddt, file_data
from mathfunc import multi

@ddt  # 1
class TestMathFunc(unittest.TestCase):

    @file_data("test_data.json")
    def test_multi(self, num1, num2, correct):
        print("测试乘法")
        result = multi(num1, num2)
        self.assertEqual(correct, result)  # 测试业务方法multi

参考链接:

  1. https://zhuanlan.zhihu.com/p/29968920
  2. https://blog.csdn.net/luanpeng825485697/article/details/79459771
  3. https://www.cnblogs.com/miniren/p/7099187.html
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值