Python unittest模块浅析

1,449 阅读4分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

前言

软件开发流程中,我们都听说过瀑布开发流程,哪一定对开发各个环节有一定的了解吧。

在瀑布开发流程主要分为三大部分

  1. 前期需求设计阶段
  2. 编码实现阶段
  3. 测试验证阶段

作为测试来说,我们主要是参与第3部分测试环节的验证。根据介入时间早晚一次有单元测试、集成测试等

单元测试,与RD编码阶段是紧密连接的,如何在前期编码时就把绝大多数的BUG扼杀在摇篮里。其对于产品而言是无法省略的。

对于,python来说内置库也提供我们单元测试模块-unittest,本期我们将对unittest相关的方法进行学习,Let's go~

1. unittest 模块概述

unittest 是Python内置库提供用于进行单元测试的模块,其结构与JUnitd等主流单元测试框架类似。

Unittest支持的功能

  1. 支持测试自动化
  2. 配置共享
  3. 支持测试用例聚合到测试集中
  4. 测试与报告框架独立

Unittest使用方法

  • 导入unittest模块:import unittest
  • 测试类需要继承unitest.TestCase
  • 测试用例必须以test开头
  • assert断言来判断测试结果
  • 使用HTMLTestRunner生产测试报告

2. unittest 结构组成

unitest 模块由五部分构成

  1. Testcase 测试用例

    • Testcase 对应我们平时就是一条完整的测试项。
    • 测试项包含前置条件、步骤以及预期结果。
    • 一个Testcase等价于一个测试单元
  2. Testsuit 测试套件

    • Testsuit由多个测试单元Testcase组成,可对一个功能进行完整验证
    • 可以通过addTest来将Testcase加入到Testsuit中
    • Testsuit也可以嵌套其他的Testsuit
  3. TestRunner 测试执行

    • 对测试套件提供执行策略和执行结果
    • 通过TextTextRunner().run()来执行Testsuit或者Testcase
    • TestRunner 支持使用图形界面、文本界面等表示测试执行结果
  4. TestFixture 测试前后置

    • 对于测试执行前,进行环境搭建和销毁
    • 通过Testcase的setUP()和tearDown()方法来实现

3. unittest 工作原理

通过unittest五大部分了解后,它们执行过程图所示:

  1. 创建的testcase需要继承unittest.TestCase
  2. testcase里面包含许多方法,则方法需要以test开头
  3. 使用TestLoader对Testcase加载到Testsuite
  4. TextTestRunner对Testsuit进行执行,并将够保存在TextTestResult
  5. 默认情况下,TextTestResult执行结果会输出到控制台上

4. unittest 相关方法

unittest 库常用的属性和方法:

  • 新键的测试用例都需要继承unittest.TestCase类 unittest.Testcase 提供对测试环境搭建和销毁的方法
方法作用
setUp()对测试环境进行前置操作
tearDown()对测试环境进行后置操作
setUpClass()Testcase中test方法执行前置操作
tearDownClass()Tescase中test方法执行后置操作

📢setUpClass()、tearDownClass()

  1. 必须使用@classmethod装饰器
  2. 所有case运行完后只运行一次
  • TestCase中还提供对方法进行控制的装饰器
装饰器作用
@unittest.skip(reason)跳过此步骤
@unittest.skipIf(condition,reason)当condition为真,跳过此步骤
@unittest.skipUnless(condition,reason)除非condition为真,否则跳过此步骤
@unittest.expectedFailure标记此步骤异常

5. 小试牛刀

我们根据前对unittest的相关方法的学习,哪我们来使用unittest对方法进行测试吧

  1. 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
  1. unittest单元测试脚本
import unittest
from test import mathfunc

class TestMathFunc(unittest.TestCase):
    """Test mathfuc.py"""

    def setUp(self) -> None:
        print ("-----setup")

    def tearDown(self) -> None:
        print ("----teardown")
    #setUpClass():必须使用@classmethod 装饰器,所有case运行前只运行一次
    @classmethod
    def setUpClass(cls) -> None:
        print("This Setupclass() method only called once")

    #tearDownClass():必须使用@classmethod装饰器,所有case运行完后只运行一次
    @classmethod
    def tearDownClass(cls) -> None:
        print("this teardownclass() method only called once")

    @unittest.skipUnless(3>2,"不执行")
    def test_add(self):
        """Test method add(a, b)"""
        print ("---add")
        self.assertEqual(3, mathfunc.add(1, 2))
        self.assertNotEqual(3, mathfunc.add(2, 2))

    @unittest.skip("不执行此用例")
    def test_minus(self):
        """Test method minus(a, b)"""
        print ("---minus")
        self.assertEqual(1, mathfunc.minus(3, 2))

    @unittest.skipIf(3<2,"执行此用例")
    def test_multi(self):
        """Test method multi(a, b)"""
        print ("---multi")
        self.assertEqual(6, mathfunc.multi(2, 3))
    @unittest.expectedFailure
    def test_divide(self):
        """Test method divide(a, b)"""
        #self.skipTest("不执行")
        print ("---divide")
        self.assertEqual(2, mathfunc.divide(6, 3))
        self.assertEqual(2.5, mathfunc.divide(5, 0))
if __name__ == '__main__':
    #所有用例都执行一遍
    # unittest.main()
  1. 选择执行 test_add、test_minus两个方法
if __name__ == '__main__':
    #单独运行目标关键字更新
    suite = unittest.TestSuite()

    tests = [TestMathFunc("test_add"),TestMathFunc("test_minus")]
    suite.addTests(tests)

    unittest.TextTestRunner().run(suite)

总结

本期,我们对Python提供的unittest单元测试模块,对其工作原理以及unittest执行步骤进行了解和学习。

我们在写自动化用例后,可以使用unittest测试验证我们用例正确和稳定性。

以上是本期内容,欢迎大佬们点赞评论,下期见~