Loading

Unittest框架的从零到壹(一)

前言

Python中有非常多的单元测试框架,如unittest、pytest、nose、doctest等,Python2.1及其以后的版本已经将unittest作为一个标准模块放入Python开发包中。并且在pytest框架中,是可以兼容运行unittest的代码的,简单来说,就是学一顶俩。并且unittest也是比较简单上手的,等unittest篇完结后,我们再开一个pytest篇。成为自动化测试大神指日可待🙊

认识断言

单元测试本质上就是通过一段代码去验证另外一段代码,那么这段验证的代码里,有一个起到关键作用的关键字,就是assert-断言。assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。下面举例说明一下用法

  • 来看看语法格式,一般assert后面跟一个条件和一个断言失败信息

    比如assert 1 == -1,'报错就打印我出来'

    断言失败就会抛出AssertionError异常,并且把自定义的断言失败信息打印出来

    上面这条语句就等价于

    if not 1 == -1:
    		print("报错就打印我出来")
        raise AssertionError
    

    看到这里的话应该很清晰了,所谓断言就是判断一个条件,条件不成立就会抛出异常,称之为断言失败,反之就是断言成功。

代码初体验

了解基本情况后,开始动手敲敲代码吧,始终贯彻代码驱动学习理念,只看是永远学不会的!当然了天才除外👏🏻

先来创个项目,项目名就叫Study_unittest,直白易懂

image-20190928104758064

先创第一个py文件,名就叫calculator.py,在这里面创建计算器类。

#计算器类
class Calculator:
    "”用于完成两个数的加、减、乘、除"""

    def __init__(self,a,b):
        self.a=int(a)
        self.b=int(b)

    # 加法
    def add(self):
        return self.a + self.b

    #减法
    def sub(self):
        return self.a - self.b

    #乘法
    def mul(self):
        return self.a * self.b

    #除法
    def div(self):
        return self.a / self.b

在定义好上面的 alculator.py程序之后,该程序就相当于一个模块,接下来为该模块编写单元测试代码。

创建test_calculator.py文件,下面就是测试用例的代码:

import unittest
from calculator import Calculator

class TestCalculator(unittest.TestCase):

    def test_add(self):
        c = Calculator(1, 2)
        result = c.add()
        self.assertEqual(result, 3)

    def test_sub(self):
        c = Calculator(5, 1)
        result = c.sub()
        self.assertEqual(result, 4)

    def test_mul(self):
        c = Calculator(5, 1)
        result = c.sub()
        self.assertEqual(result, 6)
    
    def test_div(self):
        c = Calculator(6, 2)
        result = c.sub()
        self.assertEqual(result, 3)
        
if __name__ == '__main__':
    unittest.main()

由上得知,unittest 要求单元测试类必须继承 unittest.TestCase,该类中的测试方法需要满足如下要求:

  • 测试方法不应该有返回值。
  • 测试方法不应该有任何参数。
  • 测试方法应以test 开头。

运行结果如下:

image-20190928144251167

本次统计运行了4条测试用例,运行时间为0.139s,失败(failures)了1条测试用例,成功(successes)了3条测试用例。失败的测试用例也有清晰说明用例名称以及错误的位置。

断言方法

  • unittest.TestCase 内置了大量 assertXXX 方法来执行断言,其中最常用的断言方法如表 1 所示。

    断言方法 检查条件
    assertEqual(a, b) a == b
    assertNotEqual(a, b) a != b
    assertTrue(x) bool(x) is True
    assertFalse(x) bool(x) is False
    assertIs(a, b) a is b
    assertIsNot(a, b) a is not b
    assertIsNone(x) x is None
    assertIsNotNone(x) x is not None
    assertIn(a, b) a in b
    assertNotIn(a, b) a not in b
    assertlsInstance(a, b) isinstance(a, b)
    assertNotIsInstance(a, b) not isinstance(a, b)

    ​ 表 1 TestCase 中最常用的断言方法

  • 除了上面这些断言方法,如果程序要对异常、错误、警告和日志进行断言判断,TestCase 提供了如表 2 所示的断言方法。

    断言方法 检查条件
    assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) 引发 exc 异常
    assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) 引发 exc 异常,且异常信息匹配 r 正则表达式
    assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) 引发 warn 警告
    assertWamsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) 引发 warn 警告,且警告信息匹配 r 正则表达式
    assertLogs(logger, level) With 语句块使用日志器生成 level 级别的日志

    ​ 表 2 TestCase 包含的与异常、错误、警告和日志相关的断言方法

  • TestCase 还包含了如表 3 所示的断言方法用于完成某种特定检查。

    断言方法 检查条件
    assertAlmostEqual(a, b) round(a-b, 7) == 0
    assertNotAlmostEqual(a, b) round(a-b, 7) != 0
    assertGreater(a, b) a > b
    assertGreaterEqual(a, b) a >= b
    assertLess(a, b) a < b
    assertLessEqual(a, b) a <= b
    assertRegex(s, r) r.search(s)
    assertNotRegex(s, r) not r.search(s)
    assertCountEqual(a, b) a、b 两个序列包含的元素相同,不管元素出现的顺序如何

    ​ 表 3 TestCase 包含的用于完成某种特定检查的断言方法

  • 当测试用例使用 assertEqual() 判断两个对象是否相等时,如果被判断的类型是字符串、序列、列表、元组、集合、字典,则程序会自动改为使用如表 4 所示的断言方法进行判断。换而言之,如表 4 所示的断言方法其实没有必要使用,unittest 模块会自动应用它们。

断言方法 用于比较的类型
assertMultiLineEqual(a, b) 字符串(string)
assertSequenceEqual(a, b) 序列(sequence)
assertListEqual(a, b) 列表(list)
assertTupleEqual(a, b) 元组(tuple)
assertSetEqual(a, b) 集合(set 或 frozenset)
assertDictEqual(a, b) 字典(dict)

​ 表 4 TestCase 包含的针对特定类型的断言方法

运行测试

在编写完测试用例之后,可以使用如下两种方式来运行它们:

  1. 通过代码调用测试用例。程序可以通过调用 unittest.main() 来运行当前源文件中的所有测试用例。例如,在上面的测试用例中增加如下代码:

    if __name__ == '__main__':
        unittest.main()
    
  2. 使用 unittest 模块运行测试用例。使用该模块的语法格式如下:

    python -m unittest 测试文件
    

    在使用 python -m unittest 命令运行测试用例时,如果没有指定测试用例,该命令将自动查找并运行当前目录下的所有测试用例。因此,程序也可直接使用如下命令来运行所有测试用例:

    py -m unittest
    

相信通过本篇文章,你对unittest有了基本的认识,该系列的文章也会做到简洁通俗明了,让大家更容易上手。

这一期就到这里了,下一期内容来介绍unittest的四大重点。喜欢的朋友可以收藏下来方便以后查看~

posted @ 2019-09-29 09:50  x1you  阅读(2267)  评论(0编辑  收藏  举报