...

unittest官网文档

unittest-单元测试框架

unittest是受JUnit启发编写的一款Python语言的单元测试框架,并与其他语言中的主流单元测试框架有着相似的风格。unittest支持自动化测,测试准备和测试清理部分代码复用,支持将测试用例组聚合成测试套件,并与报告生成框架相互独立。

为了实现这些,unittest通过面向对象的方式支持了以下一些重要的概念。

test fixture测试脚手架
test fixture表示为了开展一项或多项测试所需要进行的准备工作,以及所有相关的清理操作。举个例子,这可能包含创建临时或代理的数据库、目录,再或者启动一个服务器进程等等。

test case测试用例
一个测试用例是一个独立的测试单元。它检查输入特定的数据时的响应。 unittest 提供一个基类: TestCase ,用于新建测试用例。

test suite测试套件
test suite 是一系列的测试用例,或测试套件,或两者皆有。它用于归档需要一起执行的测试。

test runner 测试运行器
test runner 是一个用于执行和输出测试结果的组件。这个运行器可能使用图形接口、文本接口,或返回一个特定的值表示运行测试的结果。

基本示例

unittest 模块提供了一系列创建和运行测试的工具。这一段演示了这些工具的一小部分,但也足以满足大部分用户的需求。

这是一段简短的代码,来测试三种字符串方法:

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

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

继承 unittest.TestCase 就创建了一个测试用例。上述三个独立的测试是三个类的方法,这些方法的命名都以 test 开头。 这个命名约定告诉测试运行者类的哪些方法表示测试用例。

每个测试的关键是:调用 assertEqual() 来检查预期的输出; 调用 assertTrue() 或 assertFalse() 来验证一个条件;调用 assertRaises() 来验证抛出了一个特定的异常。使用这些方法而不是 assert 语句是为了让测试运行者能聚合所有的测试结果并产生结果报告。

通过 setUp() 和 tearDown() 方法,可以设置测试开始前与完成后需要执行的指令。 在 组织你的测试代码 中,对此有更为详细的描述。

最后的代码块中,演示了运行测试的一个简单的方法。 unittest.main() 提供了一个测试脚本的命令行接口。当在命令行运行该测试脚本,上文的脚本生成如以下格式的输出:

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
在调用测试脚本时添加 -v 参数使 unittest.main() 显示更为详细的信息,生成如以下形式的输出:

test_isupper (__main__.TestStringMethods) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

以上例子演示了 unittest 中最常用的、足够满足许多日常测试需求的特性。文档的剩余部分详述该框架的完整特性。

命令行界面

unittest 模块可以通过命令行运行模块、类和独立测试方法的测试:

python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

你可以传入模块名、类或方法名或他们的任意组合。

同样的,测试模块可以通过文件路径指定:

python -m unittest tests/test_something.py

这样就可以使用 shell 的文件名补全指定测试模块。所指定的文件仍需要可以被作为模块导入。路径通过去除 '.py' 、把分隔符转换为 '.' 转换为模块名。若你需要执行不能被作为模块导入的测试文件,你需要直接执行该测试文件。

在运行测试时,你可以通过添加 -v 参数获取更详细(更多的冗余)的信息。

python -m unittest -v test_module

当运行时不包含参数,开始 探索性测试

python -m unittest

用于获取命令行选项列表:

python -m unittest -h

在 3.2 版更改: 在早期版本中,只支持运行独立的测试方法,而不支持模块和类。

命令行选项
unittest支持以下命令行选项:

-b, --buffer

在测试运行时,标准输出流与标准错误流会被放入缓冲区。成功的测试的运行时输出会被丢弃;测试不通过时,测试运行中的输出会正常显示,错误会被加入到测试失败信息。

-c, --catch

当测试正在运行时, Control-C 会等待当前测试完成,并在完成后报告已执行的测试的结果。当再次按下 Control-C 时,引发平常的 KeyboardInterrupt 异常。

See Signal Handling for the functions that provide this functionality.

-f, --failfast
当出现第一个错误或者失败时,停止运行测试。

-k

只运行匹配模式或子串的测试方法和类。可以多次使用这个选项,以便包含匹配子串的所有测试用例。

包含通配符(*)的模式使用 fnmatch.fnmatchcase() 对测试名称进行匹配。另外,该匹配是大小写敏感的。

模式对测试加载器导入的测试方法全名进行匹配。

例如,-k foo 可以匹配到 foo_tests.SomeTest.test_something 和 bar_tests.SomeTest.test_foo ,但是不能匹配到 bar_tests.FooTest.test_something 。

--locals

在回溯中显示局部变量。

3.2 新版功能: 添加命令行选项 -b, -c 和 -f 。

3.5 新版功能: 命令行选项 --locals 。

3.7 新版功能: 命令行选项 -k 。

命令行亦可用于探索性测试,以运行一个项目的所有测试或其子集。

探索性测试

3.2 新版功能.

unittest支持简单的测试搜索。若需要使用探索性测试,所有的测试文件必须是 modules 或 packages (包括 namespace packages )并可从项目根目录导入(即它们的文件名必须是有效的 identifiers )。

探索性测试在 TestLoader.discover() 中实现,但也可以通过命令行使用。它在命令行中的基本用法如下:

cd project_directory
python -m unittest discover

注意: 方便起见, python -m unittestpython -m unittest discover 等价。如果你需要向探索性测试传入参数,必须显式地使用 discover 子命令。
discover 有以下选项:

-v, --verbose

更详细地输出结果。

-s, --start-directory directory

开始进行搜索的目录(默认值为当前目录 . )。

-p, --pattern pattern

用于匹配测试文件的模式(默认为 test*.py )。

-t, --top-level-directory directory

指定项目的最上层目录(通常为开始时所在目录)。

-s ,-p 和 -t 选项可以按顺序作为位置参数传入。以下两条命令是等价的:

python -m unittest discover -s project_directory -p "*_test.py"
python -m unittest discover project_directory "*_test.py"

正如可以传入路径那样,传入一个包名作为起始目录也是可行的,如 myproject.subpackage.test 。你提供的包名会被导入,它在文件系统中的位置会被作为起始目录。

警告 探索性测试通过导入测试对测试进行加载。在找到所有你指定的开始目录下的所有测试文件后,它把路径转换为包名并进行导入。如 foo/bar/baz.py 会被导入为 foo.bar.baz 。
如果你有一个全局安装的包,并尝试对这个包的副本进行探索性测试,可能会从错误的地方开始导入。如果出现这种情况,测试会输出警告并退出。

如果你使用包名而不是路径作为开始目录,搜索时会假定它导入的是你想要的目录,所以你不会收到警告。

测试模块和包可以通过 load_tests protocol 自定义测试的加载和搜索。

在 3.4 版更改: 探索性测试支持命名空间包( namespace packages )。

用例组织

单元测试的构建单位是 test cases :独立的、包含执行条件与正确性检查的方案。在 unittest 中,测试用例表示为 unittest.TestCase 的实例。通过编写 TestCase 的子类或使用 FunctionTestCase 编写你自己的测试用例。

一个 TestCase 实例的测试代码必须是完全自含的,因此它可以独立运行,或与其它任意组合任意数量的测试用例一起运行。

TestCase 的最简单的子类需要实现一个测试方法(例如一个命名以 test 开头的方法)以执行特定的测试代码:

import unittest

class DefaultWidgetSizeTestCase(unittest.TestCase):
    def test_default_widget_size(self):
        widget = Widget('The widget')
        self.assertEqual(widget.size(), (50, 50))

可以看到,为了进行测试,我们使用了基类 TestCase 提供的其中一个 assert*() 方法。若测试不通过,将会引发一个带有说明信息的异常,并且 unittest 会将这个测试用例标记为测试不通过。任何其它类型的异常将会被当做错误处理。

可能同时存在多个前置操作相同的测试,我们可以把测试的前置操作从测试代码中拆解出来,并实现测试前置方法 setUp() 。在运行测试时,测试框架会自动地为每个单独测试调用前置方法。

import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def test_default_widget_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_widget_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

注意:多个测试运行的顺序由内置字符串排序方法对测试名进行排序的结果决定。
在测试运行时,若 setUp() 方法引发异常,测试框架会认为测试发生了错误,因此测试方法不会被运行。

相似的,我们提供了一个 tearDown() 方法在测试方法运行后进行清理工作。

import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()

若 setUp() 成功运行,无论测试方法是否成功,都会运行 tearDown() 。

这样的一个测试代码运行的环境被称为 test fixture 。一个新的 TestCase 实例作为一个测试脚手架,用于运行各个独立的测试方法。在运行每个测试时,setUp() 、tearDown() 和 init() 会被调用一次。

建议使用 TestCase 实现根据测试测试的功能将测试分组在一起。单元测试为此提供了一种机制:测试套件,由单元测试的TestSuite类表示。在大多数情况下,调用unittest.main()将做正确的事并收集模块的所有测试用例并执行它们。

然而,如果你需要自定义你的测试套件的话,你可以参考以下方法组织你的测试:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_widget_size'))
    suite.addTest(WidgetTestCase('test_widget_resize'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

你可以将测试用例和测试套件的定义放在被测代码码相同的模块(如widget.py)中, ,但将测试代码放在单独的模块(如test_widget.py)中有以下几个优点 :

  • 测试模块可以从命令行独立运行。
  • 测试代码可以更容易地与已发货代码分离。
  • 在没有充分理由的情况下更改测试代码以适应其测试的代码的诱惑较小。
  • 测试代码的修改频率应比测试的代码少得多。
  • 测试的代码可以更容易地重构。
  • 不管怎样,用 C 编写的模块的测试必须在单独的模块中,那么为什么不保持一致呢?
  • 如果测试策略发生更改,则无需更改源代码。

复用已有的测试代码

一些用户希望直接使用 unittest 运行已有的测试代码,而不需要把已有的每个测试函数转化为一个 TestCase 的子类。

因此, unittest 提供 FunctionTestCase 类。这个 TestCase 的子类可用于打包已有的测试函数,并支持设置前置与后置函数。

假定有一个测试函数:

def testSomething():
    something = makeSomething()
    assert something.name is not None
    # ...

可以创建等价的测试用例如下,其中前置和后置方法是可选的。

testcase = unittest.FunctionTestCase(testSomething,
                                     setUp=makeSomethingDB,
                                     tearDown=deleteSomethingDB)

注意:尽管函数测试案例可用于将现有测试库快速转换为基于单元测试的系统,但不建议使用此方法。花时间设置正确的TestCase子类将使未来的测试重构变得无限容易。

跳过及预期失败

3.1 新版功能.

unittest 支持跳过单个测试方法,甚至整个测试类。此外,它支持将测试标记为"预期失败",该测试已损坏且将失败,但不应算作测试结果的失败。

跳过测试只是使用skip() 修饰器或其条件变体之一、在 setUp() 或测试方法中调用TestCase.skipTest()或直接引发SkipTest的问题。

跳过测试的基本用法如下:

class MyTestCase(unittest.TestCase):

    @unittest.skip("demonstrating skipping")
    def test_nothing(self):
        self.fail("shouldn't happen")

    @unittest.skipIf(mylib.__version__ < (1, 3),
                     "not supported in this library version")
    def test_format(self):
        # Tests that work for only a certain version of the library.
        pass

    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_windows_support(self):
        # windows specific testing code
        pass

    def test_maybe_skipped(self):
        if not external_resource_available():
            self.skipTest("external resource not available")
        # test code that depends on the external resource
        pass

在详细模式下运行以上测试例子时,程序输出如下:

test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
test_maybe_skipped (__main__.MyTestCase) ... skipped 'external resource not available'
test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'

----------------------------------------------------------------------
Ran 4 tests in 0.005s

OK (skipped=4)

跳过测试类的写法跟跳过测试方法的写法相似:

@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
    def test_not_run(self):
        pass

TestCase.setUp() 也可以跳过测试。可以用于所需资源不可用的情况下跳过接下来的测试。

使用 expectedFailure() 装饰器表明这个测试预计失败。:

class ExpectedFailureTestCase(unittest.TestCase):
    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, "broken")

当要跳过测试时,通过创建在测试中调用skip() 的修饰器,可以轻松滚动自己的跳过修饰器。此修饰器将跳过测试,除非传递的对象具有特定属性:

def skipUnlessHasattr(obj, attr):
    if hasattr(obj, attr):
        return lambda func: func
    return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

The following decorators and exception implement test skipping and expected failures:

@unittest.skip(reason)

跳过被此装饰器装饰的测试。 reason 为测试被跳过的原因。

@unittest.skipIf(condition, reason)

当 condition 为真时,跳过被装饰的测试。

@unittest.skipUnless(condition, reason)

跳过被装饰的测试,除非 condition 为真。

@unittest.expectedFailure

把测试标记为预计失败。如果测试不通过,会被认为测试成功;如果测试通过了,则被认为是测试失败。

exception unittest.SkipTest(reason)

引发此异常以跳过一个测试。

通常来说,你可以使用 TestCase.skipTest() 或其中一个跳过测试的装饰器实现跳过测试的功能,而不是直接引发此异常。

被跳过的测试的 setUp() 和 tearDown() 不会被运行。被跳过的类的 setUpClass() 和 tearDownClass() 不会被运行。被跳过的模组的 setUpModule() 和 tearDownModule() 不会被运行。

使用subTest区分测试迭代

3.4 新版功能.

当测试(例如某些参数)之间差异非常小时,单元测试允许您使用subTest() 上下文管理器在测试方法的主体内区分它们。

例如,以下测试:

class NumbersTest(unittest.TestCase):

    def test_even(self):
        """
        Test that numbers between 0 and 5 are all even.
        """
        for i in range(0, 6):
            with self.subTest(i=i):
                self.assertEqual(i % 2, 0)

可以得到以下输出:

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
Without using a subtest, execution would stop after the first failure, and the error would be less easy to diagnose because the value of i wouldn't be displayed:

======================================================================
FAIL: test_even (__main__.NumbersTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

unittest中的类与函数

本节深入介绍了 unittest 的 API。

测试用例

TestCase类

class unittest.TestCase(methodName='runTest')

TestCase 类的实例表示单元测试宇宙中的逻辑测试单元。此类旨在用作基类,具体子类将实现特定测试。此类实现测试运行程序所需的接口,以允许它驱动测试,以及测试代码可用于检查和报告各种故障的方法。

TestCase 的每个实例都将运行一个基方法:名为 方法名的方法。在大多数使用TestCase 时,既不会更改方法Name,也不会重新实现默认方法。runTest()

在版本 3.2 中更改:无需提供方法Name 即可成功实例化测试用例。这使得从交互式解释器试用TestCase更加容易。

TestCase实例提供了三组方法:一组用于运行测试,另一组用于测试实现用于检查条件和报告失败,以及允许收集有关测试本身的信息的一些查询方法。

第一组(运行测试)中的方法为:

setUp()
为准备测试夹具而调用的方法。在调用测试方法之前,立即调用此调用;除了断言错误或跳过测试之外,此方法引发的任何异常都将被视为错误而不是测试失败。默认实现不执行任何操作。

tearDown()
在调用测试方法并记录结果后立即调用方法。即使测试方法引发异常,也调用此选项,因此子类中的实现可能需要特别小心地检查内部状态。此方法引发的任何异常(除断言错误或SkipTest外)将被视为附加错误,而不是测试失败(从而增加报告错误的总数)。只有在setUp() 成功时,无论测试方法的结果如何,都将调用此方法。默认实现不执行任何操作。

setUpClass()
运行在单个类中测试之前调用的类方法。 使用 类调用作为唯一的参数,并且必须修饰为一个类方法):setUpClass

@classmethod
def setUpClass(cls):
    ...

查看 类及模块级Fixtures 获取更详细的说明。

3.2 新版功能.

tearDownClass()
A class method called after tests in an individual class have run. tearDownClass is called with the class as the only argument and must be decorated as a classmethod():

@classmethod
def tearDownClass(cls):
    ...

查看 类及模块级Fixtures 获取更详细的说明。

3.2 新版功能.

run(result=None)
运行测试,将结果收集到通过结果的测试结果对象中。如果省略结果或 ,则创建一个临时结果对象(通过调用默认的TestResult()方法)并使用。将结果对象返回到run() 的调用方。None

只需调用 TestCase 实例,即可产生相同的效果。

在版本 3.3 中更改:以前的版本未返回结果。调用实例也没有调用实例。run

skipTest(reason)
在测试方法或setUp() 期间调用此项跳过当前测试。有关详细信息,请参阅跳过测试和预期失败。

3.1 新版功能.

**subTest(msg=None, params)
返回作为子测试执行封闭代码块的上下文管理器。msg和params是可选的任意值,每当子测试失败时都会显示这些值,允许您清楚地识别它们。

测试用例可以包含任意数量的子测试声明,并且它们可以任意嵌套。

有关详细信息,请参阅使用子测试区分测试迭代。

3.4 新版功能.

debug()
在不收集结果的情况下运行测试。这允许将测试提出的异常传播到调用方,并可用于支持在调试器下运行测试。

TestCase类提供了几种用于检查和报告失败的断言方法。下表列出了最常用的方法(有关更多断言方法,请参阅下表):

Method Checks that New in
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 3.1
assertIsNot(a, b) a is not b 3.1
assertIsNone(x) x is None 3.1
assertIsNotNone(x) x is not None 3.1
assertIn(a, b) a in b 3.1
assertNotIn(a, b) a not in b 3.1
assertIsInstance(a, b) isinstance(a, b) 3.2
assertNotIsInstance(a, b) not isinstance(a, b) 3.2

所有断言方法都接受msg参数,如果指定该参数,则用作失败时的错误消息(另请参阅 longMesage)。请注意,msg关键字参数可以传递到断言Raises(),断言RaisesRegex(),断言Warns(),断言WarnsRegex()只有在它们用作上下文管理器时。

assertEqual(first, second, msg=None)
测试第一个和第二个相等。如果值不相等比较,则测试将失败。

此外,如果第一和第二类型与列表、元组、命令、集、冻结集或 str 或子类寄存器与addTypeEqualityFunc()的任何类型完全相同,则将调用特定于类型的相等函数,以便生成更有用的默认错误消息(另请参阅类型特定方法的列表)。

在版本 3.1 中更改:添加了类型特定的相等函数的自动调用。

在版本 3.2 中更改:断言多林平等()添加为用于比较字符串的默认类型相等函数。

assertNotEqual(first, second, msg=None)
测试第一个和第二个不相等。如果值比较相等,则测试将失败。

assertTrue(expr, msg=None)
assertFalse(expr, msg=None)
测试expr 是否为 true(或 false)。

请注意,这等效于 而不是(用于后者)。当有更具体的方法可用时,也应避免使用此方法(例如, 而不是 ,因为它们在发生故障时提供了更好的错误消息。bool(expr) is Trueexpr is TrueassertIs(expr, True)assertEqual(a, b)assertTrue(a == b)

assertIs(first, second, msg=None)
assertIsNot(first, second, msg=None)
测试第一个和第二个计算(或不计算)到同一个对象。

3.1 新版功能.

assertIsNone(expr, msg=None)

assertIsNotNone(expr, msg=None)

测试expr是(或不是)None。

3.1 新版功能.

assertIn(member, container, msg=None)

assertNotIn(member, container, msg=None)

测试该成员在(或不在)容器中。

3.1 新版功能.

assertIsInstance(obj, cls, msg=None)

assertNotIsInstance(obj, cls, msg=None)

测试obj是(或不是)cls的实例(可以是类或类元组,如isinstance()支持的)。要检查确切的类型,请使用断言(type(obj),cls。

3.2 新版功能.

还可以使用以下方法检查异常、警告和日志消息的产生:

Method Checks that New in
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises exc and the message matches regex r 3.1
assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) raises warn 3.2
assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) raises warn and the message matches regex r 3.2
assertLogs(logger, level) The with block logs on logger with minimum level 3.4

assertRaises(exception, callable, *args, **kwds)

assertRaises(exception, *, msg=None)

测试当可调用时使用也传递给assertRaises() 的任何位置参数或关键字参数调用异常时是否引发异常。如果引发异常,则通过测试;如果引发另一个异常,则通过测试;如果未引发异常,则测试失败。若要捕获一组异常中的任何一个,可以传递包含异常类的元组作为异常传递。

如果只给出异常和可能给出msg参数,则返回上下文管理器,以便测试的代码可以内联编写,而不是作为函数编写:

with self.assertRaises(SomeException):
    do_something()

当用作上下文管理器时,assertRaises()接受附加关键字参数msg。

上下文管理器将捕获的异常对象存储在其属性中。如果意图对引发异常执行其他检查,则此功能非常有用:exception

with self.assertRaises(SomeException) as cm:
    do_something()

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

在版本 3.1 中更改:添加了使用断言() 作为上下文管理器的能力。

在版本 3.2 中更改:添加了该属性。exception

在版本 3.3 中更改:用作上下文管理器时添加了 msg 关键字参数。

assertRaisesRegex(exception, regex, callable, *args, **kwds)

assertRaisesRegex(exception, regex, *, msg=None)

与断言()一样,但也测试正则表达式在引发异常的字符串表示形式上匹配。正则表达式可能是正则表达式对象或包含适合re.search() 使用的正则表达式的字符串。例子:

self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$",
                       int, 'XYZ')

或者:

with self.assertRaisesRegex(ValueError, 'literal'):
   int('XYZ')

版本 3.1 中的新功能:在名称下添加。assertRaisesRegexp

在版本 3.2 中更改:重命名为断言RaisesRegex()。

在版本 3.3 中更改:用作上下文管理器时添加了 msg 关键字参数。

assertWarns(warning, callable, *args, **kwds)

assertWarns(warning, *, msg=None)

测试当可调用时使用也传递给assertWarns()的任何位置参数或关键字参数调用时触发警告。如果触发警告,测试通过;如果警告没有触发,则测试失败。任何异常都是错误。要捕获任何一组警告,可以传递包含警告类的元组作为警告。

如果只给出警告和msg参数,则返回上下文管理器,以便测试的代码可以内联编写,而不是作为函数编写:

with self.assertWarns(SomeWarning):
    do_something()

当用作上下文管理器时,断言警告()接受附加关键字参数msg。

上下文管理器将捕获的警告对象存储在其属性中,以及触发 和 属性中触发警告的源行。如果意图对捕获的警告执行其他检查,这非常有用:warningfilenamelineno

with self.assertWarns(SomeWarning) as cm:
    do_something()

self.assertIn('myfile.py', cm.filename)
self.assertEqual(320, cm.lineno)

此方法在调用时无论警告筛选器是否就位,都有效。

版本 3.2 中的新版本。

在版本 3.3 中更改:用作上下文管理器时添加了 msg 关键字参数。

assertWarnsRegex(warning, regex, callable, *args, **kwds)

assertWarnsRegex(warning, regex, *, msg=None)

与断言警告()一样,但也测试正则表达式在触发警告的消息上匹配。正则表达式可能是正则表达式对象或包含适合re.search() 使用的正则表达式的字符串。例子:

self.assertWarnsRegex(DeprecationWarning,
                      r'legacy_function\(\) is deprecated',
                      legacy_function, 'XYZ')

或者:

with self.assertWarnsRegex(RuntimeWarning, 'unsafe frobnicating'):
    frobnicate('/etc/passwd')

3.2 新版功能.

在版本 3.3 中更改:用作上下文管理器时添加了 msg 关键字参数。

assertLogs(logger=None, level=None)

上下文管理器,以测试至少一条消息记录器或其子级之一,至少具有给定级别。

如果给定,记录器应为日志记录。记录器对象或提供记录器名称的 str。默认值是根记录器,它将捕获所有消息。

如果给定,级别应为数字日志记录级别或其字符串等效级别(例如 或 )。默认值为 。"ERROR"logging.ERRORlogging.INFO

如果块内发出的至少一条消息与记录器和级别条件匹配,则测试通过,否则失败。with

上下文管理器返回的对象是记录帮助程序,用于保留匹配日志消息的跟踪。它有两个属性:

records
日志记录的列表。匹配日志消息的日志记录对象。

output
具有匹配消息的格式化输出的str对象的列表。

示例:

with self.assertLogs('foo', level='INFO') as cm:
   logging.getLogger('foo').info('first message')
   logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
                             'ERROR:foo.bar:second message'])

3.4 新版功能.

还有其他方法用于执行更具体的检查,例如:

方法 示例 新增版本
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b 3.1
assertGreaterEqual(a, b) a >= b 3.1
assertLess(a, b) a < b 3.1
assertLessEqual(a, b) a <= b 3.1
assertRegex(s, r) r.search(s) 3.1
assertNotRegex(s, r) not r.search(s) 3.2
assertCountEqual(a, b) a and b have the same elements in the same number, regardless of their order. 3.2

assertAlmostEqual(first, second, places=7, msg=None, delta=None)

assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)

通过计算差值、舍入到给定的十进制位数(默认值 7)和与零进行比较来测试第一个和第二个大致相等(或不大致)相等。请注意,这些方法将值舍入到给定的十进制位数(即如舍入()函数)而不是有效数字。

如果提供增量而不是地点,则第一和第二之间的差值必须小于或等于(或大于)增量。

供应三角洲和地方提出了一个类型Error。

在版本 3.2 中更改:断言AlmostEqual()会自动考虑几乎相等的比较相等的对象。断言非同方()自动失败,如果对象比较相等。添加了增量关键字参数。

assertGreater(first, second, msg=None)

assertGreaterEqual(first, second, msg=None)

assertLess(first, second, msg=None)

assertLessEqual(first, second, msg=None)

Test that first is respectively >, >=, < or <= than second depending on the method name. If not, the test will fail:

>>>
>>> self.assertGreaterEqual(3, 4)
AssertionError: "3" unexpectedly not greater than or equal to "4"

3.1 新版功能.

assertRegex(text, regex, msg=None)

assertNotRegex(text, regex, msg=None)

测试正则表达式搜索是否匹配(或不匹配)文本。如果发生故障,错误消息将包括模式和文本(或模式和文本意外匹配的部分)。正则表达式可能是正则表达式对象或包含适合re.search() 使用的正则表达式的字符串。

版本 3.1 中的新功能:在名称下添加。assertRegexpMatches

在版本 3.2 中更改:该方法已重命名为断言Regex()。assertRegexpMatches()

版本 3.2 中的新版本:断言无Regex()。

版本 3.5 中的新功能:名称是断言NotRegex() 的弃用别名。assertNotRegexpMatches

assertCountEqual(first, second, msg=None)

测试该序列首先包含与第二个相同的元素,而不管它们的顺序如何。如果它们没有,将生成一条错误消息,列出序列之间的差异。

比较第一个和第二个元素时,不会忽略重复元素。它验证每个元素在两个序列中是否具有相同的计数。等效于 :但也适用于不可ashash 的对象的序列。assertEqual(Counter(list(first)), Counter(list(second)))

版本 3.2 中的新版本。

断言平等() 方法将相同类型对象的相等性检查调度到不同的类型特定方法。这些方法已经实现为大多数内置类型,但也可以注册新方法使用addTypeEqualityFunc():

addTypeEqualityFunc(typeobj, function)

注册由assertEqual() 调用的类型特定方法,以检查两个类型obj(非子类)的对象是否比较相等。函数必须具有两个位置参数和第三个 msg=None 关键字参数,就像断言平等() 一样。当检测到前两个参数之间的不等式时,它必须提高自我.failureException(msg)——可能提供有用的信息,并在错误消息中详细解释不等式。

3.1 新版功能.

断言Equal()自动使用的类型特定方法的列表总结如下表。请注意,通常不需要直接调用这些方法。

方法 用于比较 新增版本
assertMultiLineEqual(a, b) strings 3.1
assertSequenceEqual(a, b) sequences 3.1
assertListEqual(a, b) lists 3.1
assertTupleEqual(a, b) tuples 3.1
assertSetEqual(a, b) sets or frozensets 3.1
assertDictEqual(a, b) dicts 3.1

assertMultiLineEqual(first, second, msg=None)

测试多行字符串是否等于字符串第二。如果不等于,则突出显示差异的两个字符串的差异将包含在错误消息中。默认情况下,在将字符串与断言平等() 进行比较时,此方法是使用。

3.1 新版功能.

assertSequenceEqual(first, second, msg=None, seq_type=None)

测试两个序列相等。如果seq_type,则第一和第二个都必须是seq_type否则将引发故障。如果序列不同,则构造一条错误消息,显示两者之间的差异。

此方法不是由断言质量() 直接调用的,但它用于实现断言列表qual() 和断言三等()。

3.1 新版功能.

assertListEqual(first, second, msg=None)

assertTupleEqual(first, second, msg=None)

测试两个列表或元组相等。如果没有,则构造一条错误消息,仅显示两者之间的差异。如果任一参数的类型错误,也会引发错误。默认情况下,当将列表或元组与断言Equal() 进行比较时,使用这些方法。

3.1 新版功能.

assertSetEqual(first, second, msg=None)

测试两组相等。如果没有,则构造一条错误消息,列出集之间的差异。默认情况下,在将集或冻结集与断言平等() 进行比较时,此方法是使用。

如果第一个或第二个方法没有方法,则失败。set.difference()

3.1 新版功能.

assertDictEqual(first, second, msg=None)

测试两个字典是否相等。如果没有,将构造一条错误消息,显示字典中的差异。默认情况下,此方法将用于比较调用中的字典,以断言平等()。
3.1 新版功能.

最后,测试用例提供了以下方法和属性:

fail(msg=None)

无条件地使用 msg或错误消息发出测试失败信号。None

failureException

此类属性提供测试方法引发异常。如果测试框架需要使用专用异常(可能携带其他信息),则必须将此异常子分类,以便对框架"公平"。此属性的初始值为断言Error。

longMessage

此类属性确定当自定义失败消息作为 msg 参数传递到失败的 assertXYY 调用时会发生什么情况。 是默认值。在这种情况下,自定义消息将追加到标准失败消息的末尾。当设置为 时,自定义消息将替换标准消息。TrueFalse

可以通过将实例属性 self.longMessage 分配给或调用断言方法之前在单个测试方法中重写类设置。TrueFalse

类设置在每次测试调用之前重置。

3.1 新版功能.

maxDiff

此属性通过报告失败差异的断言方法控制差异输出的最大长度。它默认为 80*8 个字符。受此属性影响的断言方法为断言序列平等()(包括委托给它的所有序列比较方法)、断言DictEqual() 和断言MultiLineEqual()。

设置为 表示没有差异的最大长度。maxDiffNone

版本 3.2 中的新版本。

测试框架可以使用以下方法来收集有关测试的信息:

countTestCases()

返回此测试对象表示的测试数。对于TestCase实例,这始终为 。1

defaultTestResult()

返回应用于此测试用例类的测试结果类的实例(如果没有向run() 方法提供其他结果实例)。

对于TestCase实例,这始终是TestResult 的实例;测试用例的子类应覆盖此项。

id()

返回标识特定测试用例的字符串。这通常是测试方法的全名,包括模块和类名。

shortDescription()

返回测试的说明,或者未提供说明。此方法的默认实现返回测试方法的文档字符串(如果可用)或 的第一行。NoneNone

在版本 3.1 中更改:在 3.1 中,这被更改以将测试名称添加到简短描述中,即使在存在文档字符串的情况下。这就导致与单元测试扩展的兼容性问题,并且将测试名称添加到 Python 3.2中的TextTest 结果。

addCleanup(function, *args, **kwargs)

此方法在拆解() 之后或设置组()后无条件调用,如果setUp()引发异常。

它负责调用通过addCleanup() 添加的所有清理函数。如果您需要在拆解()之前调用清理函数,那么您可以自己调用doCleanups()。

doCleanups()将方法一次从清理函数堆栈中弹出,因此可以随时调用它。

3.1 新版功能.

doCleanups()

此方法在拆解() 之后或设置组()后无条件调用,如果setUp()引发异常。

它负责调用通过addCleanup() 添加的所有清理函数。如果您需要在拆解()之前调用清理函数,那么您可以自己调用doCleanups()。

doCleanups()将方法一次从清理函数堆栈中弹出,因此可以随时调用它。

3.1 新版功能.

classmethod addClassCleanup(function, /, *args, **kwargs)

添加在拆解类() 后调用的函数来清理测试类中使用的资源。函数将按与添加顺序相反的顺序调用 (LIFO)。在添加它们时,使用传递给addClassCleanup() 的任何参数和关键字参数来调用它们。

如果setUpClass()失败,这意味着不调用拆解类(),则仍将调用添加的任何清理函数。

3.8 新版功能.

classmethod doClassCleanups()

此方法在拆解类() 之后或设置的UpClass()引发异常后无条件调用。

它负责调用 中添加的所有清理函数。如果您需要在拆解类()之前调用清理函数,那么您可以调用自己。 addCleanupClass()doCleanupsClass()

doCleanupsClass()一次从清理函数堆栈中弹出方法,因此可以随时调用它。

3.8 新版功能.

class unittest.IsolatedAsyncioTestCase(methodName='runTest')

此类提供类似于 TestCase 的API,并接受作为测试函数的coroutine。

3.8 新版功能.

coroutine asyncSetUp()

为准备测试夹具而调用的方法。这在 调用后。在调用测试方法之前,立即调用此调用;除了断言错误或跳过测试之外,此方法引发的任何异常都将被视为错误而不是测试失败。默认实现不执行任何操作。setUp()

coroutine asyncTearDown()

在调用测试方法并记录结果后立即调用方法。这在 之前调用。即使测试方法引发异常,也调用此选项,因此子类中的实现可能需要特别小心地检查内部状态。此方法引发的任何异常(除断言错误或SkipTest外)将被视为附加错误,而不是测试失败(从而增加报告错误的总数)。只有在异步集()成功时,无论测试方法的结果如何,都将调用此方法。默认实现不执行任何操作。tearDown()

addAsyncCleanup(function, /, *args, **kwargs)

此方法接受可用作清理函数的Coroutine。

run(result=None)

设置一个新的事件循环来运行测试,将结果收集到作为结果通过的测试结果对象中。如果省略结果或 ,则创建临时结果对象(通过调用 方法)并使用。将结果对象返回到run() 的调用方。在测试结束时,事件循环中的所有任务将被取消。NonedefaultTestResult()

说明订单的示例:

from unittest import IsolatedAsyncioTestCase

events = []


class Test(IsolatedAsyncioTestCase):


    def setUp(self):
        events.append("setUp")

    async def asyncSetUp(self):
        self._async_connection = await AsyncConnection()
        events.append("asyncSetUp")

    async def test_response(self):
        events.append("test_response")
        response = await self._async_connection.get("https://example.com")
        self.assertEqual(response.status_code, 200)
        self.addAsyncCleanup(self.on_cleanup)

    def tearDown(self):
        events.append("tearDown")

    async def asyncTearDown(self):
        await self._async_connection.close()
        events.append("asyncTearDown")

    async def on_cleanup(self):
        events.append("cleanup")

if __name__ == "__main__":
    unittest.main()

运行测试后,将包含 。events["setUp", "asyncSetUp", "test_response", "asyncTearDown", "tearDown", "cleanup"]

FunctionTestCase类

class unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)

此类实现TestCase 接口的部分,该部分允许测试运行程序驱动测试,但不提供测试代码可用于检查和报告错误的方法。这用于使用旧式测试代码创建测试用例,允许将它集成到基于单元测试的测试框架中。

用例组织

TestSuite类

class unittest.TestSuite(tests=())

此类表示单个测试用例和测试套件的聚合。该类提供测试运行程序所需的接口,以允许它作为任何其他测试用例运行。运行TestSuite实例与在套件上遍机相同,单独运行每个测试。

如果提供了测试,它必须是单个测试用例或其他测试套件的可重复性,这些测试用例或最初将用于构建套件。提供了其他方法,以稍后将测试用例和套件添加到集合中。

TestSuite对象的行为与TestCase对象非常类似,只是它们实际上不实现测试。相反,它们用于将测试聚合到应一起运行的测试组中。一些其他方法可用于将测试添加到TestSuite实例:

addTest(test)
向套件添加测试用例或测试套件。

addTests(tests)
将可重复的 TestCase 和TestSuite实例的所有测试添加到此测试套件中。

这相当于在测试中进行遍溯,为每个元素调用 addTest()。

TestSuite与TestCase 共享以下方法:

run(result)
运行与此套件关联的测试,将结果收集到测试结果对象中,以结果传递给。请注意,与TestCase.run() 不同,TestSuite.run()要求将结果对象传递。

debug()
在不收集结果的情况下运行与此套件关联的测试。这允许将测试提出的异常传播到调用方,并可用于支持在调试器下运行测试。

countTestCases()
返回此测试对象表示的测试数,包括所有单独的测试和子套件。

iter()
由TestSuite 分组的测试始终通过迭代进行访问。子类可以通过重写__iter__() 来懒洋洋地提供测试。请注意,此方法可能在单个套件上多次调用(例如,在计算测试或比较相等性时),因此,在 TestSuite.run() 之前重复迭代返回的测试对于每个调用迭代必须相同。在TestSuite.run() 之后,调用方不应依赖此方法返回的测试,除非调用方使用重写的子类来保留测试引用。TestSuite._removeTestAtIndex()

在版本 3.2 中更改:在较早的版本中,TestSuite直接访问测试,而不是通过__iter__访问,因此重写 iter()不足以提供测试。

在版本 3.4 中更改:在较早的版本中,TestSuite在TestSuite.run() 之后对每个测试用例进行了引用。 子类可以通过重写 来还原该行为。TestSuite._removeTestAtIndex()

在TestSuite 对象的典型用法中,run()方法由 一个而不是最终用户测试工具调用。TestRunner

用例加载及运行

TestLoader类

class unittest.TestLoader

加载测试时遇到的非致命错误的列表。任何点都不由加载器重置。致命错误由相关的方法发出信号,向调用方引发异常。非致命错误也由综合测试指示,该测试将在运行时引发原始错误。

3.5 新版功能.

测试加载器对象具有以下方法:

errors
加载测试时遇到的非致命错误的列表。任何点都不由加载器重置。致命错误由相关的方法发出信号,向调用方引发异常。非致命错误也由综合测试指示,该测试将在运行时引发原始错误。

3.5 新版功能.

测试加载器对象具有以下方法:

loadTestsFromTestCase(testCaseClass)
返回 TestCase 派生中包含的所有测试用例的套件。testCaseClass

为 getTestCaseNames() 命名的每个方法创建一个测试用例实例。默认情况下,这些是以 开头的方法名称。如果getTestCaseNames()不返回任何方法,但该方法已实现,则改为为该方法创建单个测试用例。testrunTest()

loadTestsFromModule(module, pattern=None)
返回给定模块中包含的所有测试用例套件。此方法搜索模块中派生自TestCase 的类,并为为类定义的每个测试方法创建类的实例。

注意:虽然在共享固件和帮助器函数时,使用 TestCase 派生类的层次结构可能很方便,但定义不直接实例化的基类的测试方法对此方法没有很好的作用。但是,当夹具不同且在子类中定义时,这样做非常有用。

如果模块提供函数,将调用它来加载测试。这允许模块自定义测试加载。这是load_tests协议。模式参数作为 第三个参数传递到 。load_testsload_tests

在版本 3.2 中更改:支持添加。load_tests

在版本 3.5 中更改:未记录的和非官方use_load_tests参数被弃用和忽略,尽管它仍然被接受为向后兼容性。该方法现在还接受作为第三个参数传递给的关键字参数模式。load_tests

loadTestsFromName(name, module=None)
返回给定字符串说明符的所有测试用例的套件。

指定名称是一个"虚名",可以解析为模块、测试用例类、测试用例类中的测试方法、TestSuite 实例或返回TestCase或TestSuite实例的可调用对象。这些检查按此处列出的顺序应用;也就是说,可能测试用例类上的方法将被拾取为"测试用例类中的测试方法",而不是"可调用对象"。

例如,如果您有一个模块包含具有三种测试方法 (, 和) 的TestCase派生类,则说明符将导致此方法返回将运行所有三种测试方法的套件。使用指定程序将导致它返回仅运行测试方法的测试套件。说明符可以引用尚未导入的模块和包;它们将被导入作为副作用。SampleTestsSampleTestCasetest_one()test_two()test_three()'SampleTests.SampleTestCase''SampleTests.SampleTestCase.test_two'test_two()

方法可以选择解析相对于给定模块的名称。

在版本 3.5 中更改:如果在遍历名称时发生了ImportError或 属性错误,则将在运行时引发该错误的综合测试。这些错误包含在 self.错误累积的错误中。

loadTestsFromNames(names, module=None)

与loadTestsFromName()类似,但采用一系列名称而不是单个名称。返回值是一个测试套件,它支持为每个名称定义的所有测试。

getTestCaseNames(testCaseClass)

与loadTestsFromName()类似,但采用一系列名称而不是单个名称。返回值是一个测试套件,它支持为每个名称定义的所有测试。

discover(start_dir, pattern='test*.py', top_level_dir=None)

通过从指定的开始目录重复到子目录来查找所有测试模块,并返回包含这些模块的 TestSuite 对象。将仅加载与模式匹配的测试文件。(使用 shell 样式模式匹配。将只加载可导入的模块名称(即有效的 Python 标识符)。

所有测试模块都必须从项目的顶层导入。如果 start 目录不是顶级目录,则必须单独指定顶级目录。

如果导入模块失败(例如由于语法错误),则这将被记录为单个错误,并且发现将继续。如果导入失败是由于引发 SkipTest,它将记录为跳过而不是错误。

如果找到包(包含名为 )的文件目录),将检查该包是否为函数。如果存在,则将调用 。测试发现需要注意确保包在调用期间只检查一次测试,即使load_tests函数本身调用。init.pyload_testspackage.load_tests(loader, tests, pattern)loader.discover

如果存在,则发现不会重复到包中,则负责加载包中的所有测试。load_testsload_tests

该模式故意不存储为加载器属性,以便包可以继续发现本身。top_level_dir存储,因此不需要将此参数传递给 。load_testsloader.discover()

start_dir可以是虚线模块名称以及目录。

版本 3.2 中的新版本。

在版本 3.4 中更改:在导入时引发 SkipTest的模块将记录为跳过,而不是错误。发现适用于命名空间包。路径在导入之前进行排序,以便执行顺序相同,即使基础文件系统的顺序不依赖于文件名。

在版本 3.5 中更改:现在检查找到的包,而不管其路径是否与模式匹配,因为包名称不可能与默认模式匹配。load_tests

测试加载器的以下属性可以通过子类或实例上的赋值进行配置:

testMethodPrefix
字符串提供将被解释为测试方法的方法名称的前缀。默认值为 。'test'

这会影响getTestCaseNames()和所有方法。loadTestsFrom*()

sortTestMethodsUsing
在getTestCaseNames() 和所有方法中对方法名称进行排序时,用于比较方法名称的函数。loadTestsFrom*()

suiteClass
从测试列表中构造测试套件的可调用对象。不需要对生成的对象使用任何方法。默认值是TestSuite 类。

这会影响所有方法。loadTestsFrom*()

testNamePatterns
测试方法必须匹配才能包含在测试套件中的 Unix shell 样式通配符名称模式的列表(请参阅选项)。-v

如果此属性不是(默认值),则测试套件中包含的所有测试方法必须匹配此列表中的一个模式。请注意,匹配始终使用fnmatch.fnmatchcase()执行,因此与传递给选项的模式不同,必须使用通配符转换简单的子字符串模式。None-v*

这会影响所有方法。loadTestsFrom*()

3.7 新版功能.

TestResult类

class unittest.TestResult
此类用于编译有关哪些测试已成功和哪些测试失败的信息。

测试结果对象存储一组测试的结果。测试案例和测试设置类可确保正确记录结果;测试作者无需担心记录测试结果。

在单元测试之上构建的测试框架可能希望访问通过运行一组测试来报告目的生成的TestResult对象; a 测试结果实例由 方法为此返回。TestRunner.run()

测试结果实例具有以下属性,在检查运行一组测试的结果时,这些属性将感兴趣:

errors
包含 2 元数的TestCase实例和字符串保存格式化的回溯的列表。每个元组表示引发意外异常的测试。

failures
包含 2 元数的TestCase实例和字符串保存格式化的回溯的列表。每个元组表示使用方法显式发出故障信号的测试。TestCase.assert*()

skipped
包含 2 个 tup 的TestCase实例和字符串的列表,其中包含跳过测试的原因。

3.1 新版功能.

expectedFailures
包含 2 元数的TestCase实例和字符串保存格式化的回溯的列表。每个元组表示测试用例的预期失败。

unexpectedSuccesses
包含TestCase 实例的列表,这些实例被标记为预期失败,但成功。

shouldStop
设置为何时执行测试应停止停止()。True

testsRun
到目前为止运行的测试总数。

buffer
如果设置为 true,并且将在调用的startTest() 和 stopTest() 之间进行缓冲。收集的输出将只回显到实际,如果测试失败或错误。任何输出也附加到失败/错误消息。sys.stdoutsys.stderrsys.stdoutsys.stderr

版本 3.2 中的新版本。

failfast
如果设置为 true stop(),将在第一次失败或错误时调用,则停止测试运行。
3.2 新版功能.

tb_locals

如果设置为 true,则局部变量将显示在回溯中。

3.5 新版功能.

wasSuccessful()
如果到目前为止运行的所有测试都通过,则返回 ,否则返回 。TrueFalse

在版本 3.4 中更改:如果使用预期失败()修饰器标记的测试出现任何意外成功,则返回。False

stop()

可以通过将 "应该停止"属性设置为 来调用此方法来表示正在运行的测试集应中止。 对象应尊重此标志并返回而不运行任何其他测试。TrueTestRunner

例如,当用户从键盘发出中断信号时,TextTestRunner类使用此功能来停止测试框架。提供实现的交互式工具可以以类似的方式使用。TestRunner

TestResult 类的以下方法用于维护内部数据结构,并可以扩展为子类以支持其他报告要求。这在构建在运行测试时支持交互式报告的工具时特别有用。

startTest(test)

在测试用例测试即将运行时调用。

stopTest(test)
无论是否执行测试用例测试后调用。

startTestRun()
在执行任何测试之前调用一次。

3.1 新版功能.

stopTestRun()
执行所有测试后调用一次。

3.1 新版功能.

addError(test, err)
当测试用例测试引发意外异常时调用。错误是sys. exc_info () 的表格的元组。(type, value, traceback)

默认实现将元组追加到实例的错误属性中,其中 formatted_err从 err 派生的格式化回溯。(test, formatted_err)

addFailure(test, err)
当测试用例测试发出故障信号时调用。错误是sys. exc_info () 的表格的元组。(type, value, traceback)

默认实现将元组追加到实例的故障属性中,其中 formatted_err从 err 派生的格式化回溯。(test, formatted_err)

addSuccess(test)
测试用例测试成功时调用。

默认实现不执行任何操作。

addSkip(test, reason)
跳过测试用例测试时调用。原因是测试给出跳过的原因。

默认实现将元组追加到实例跳过的属性。(test, reason)

addExpectedFailure(test, err)
在测试用例测试失败时调用,但用预期的失败() 修饰器标记。

默认实现将元组追加到实例的预期Failures属性中,formatted_err从 err 派生的格式化回溯。(test, formatted_err)

addUnexpectedSuccess(test)
在测试用例测试标记为预期失败() 修饰器时调用,但成功。

默认实现将测试追加到实例的意外成功属性。

addSubTest(test, subtest, outcome)
子测试结束时调用。测试是与测试方法对应的测试用例。子测试是描述子测试的自定义测试用例实例。

如果结果是"无",则子测试成功。否则,它失败,但结果为 sys.exc_info: 返回的窗体的元组。(type, value, traceback)

当结果成功时,默认实现不执行任何操作,并且将子测试失败记录为正常失败。

3.4 新版功能.

TextTestResult类

class unittest.TextTestResult(stream, descriptions, verbosity)
文本测试运行者使用的测试结果的具体实现。

版本 3.2 中的新功能:此类以前名为 。旧名称仍作为别名存在,但已弃用。_TextTestResult

defaultTestLoader对象

unittest.defaultTestLoader
要共享的测试加载器类的实例。如果不需要对 TestLoader 进行自定义,则可以使用此实例,而不是重复创建新实例。

TextTestRunner类

class unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None, *, tb_locals=False)

将结果输出到流的基本测试流道实现。如果流为 ,则默认 sys.stderr用作输出流。此类有几个可配置的参数,但本质上非常简单。运行测试套件的图形应用程序应提供备用实现。当功能添加到单元测试时,此类实现应接受为构造流道更改的接口。None**kwargs

默认情况下,此运行程序显示弃用警告、待定预测警告、资源警告和导入警告,即使默认情况下它们被忽略。弃用单元测试方法导致的弃用警告也是特例,当警告筛选器为 或 时,它们每个模块只会出现一次,以避免警告消息太多。可以使用 Python 或选项(请参阅警告控件)重写此行为,并将警告留给。'default''always'-Wd-WaNone

在版本 3.2 中更改:添加了参数。warnings

在版本 3.2 中更改:默认流在实例化时间设置为 sys.stderr,而不是导入时间。

在版本 3.5 中更改:添加了tb_locals参数。

_makeResult()

此方法返回由run()使用的实例。它不打算直接调用,但可以在子类中重写以提供自定义 。TestResultTestResult

_makeResult()实例化在构造函数中传递的类或可调用的类作为参数。如果提供"否",则默认为 TextTest结果。结果类使用以下参数实例化:TextTestRunnerresultclassresultclass

stream, descriptions, verbosity

run(test)
This method is the main public interface to the TextTestRunner. This method takes a TestSuite or TestCase instance. A TestResult is created by calling _makeResult() and the test(s) are run and the results printed to stdout.

unittest.main

unittest.main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None)

一个命令行程序,从模块加载一组测试并运行它们;这主要用于使测试模块便于执行。此函数的最简单用途是在测试脚本末尾包含以下行:

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

您可以通过传递详细参数来运行具有更多详细信息的测试:

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

默认值Test参数是单个测试的名称,或者是要运行的测试名称的可重复,如果未通过argv指定测试名称。如果未指定或未通过argv提供测试名称,则模块中找到的所有测试都运行。None

argv参数可以是传递给程序的选项列表,第一个元素是程序名称。如果未指定 或 ,则使用sys.argv的值。None

testRunner参数可以是测试运行程序类,也可以是已创建的实例。默认情况下调用sys.exit(),其退出代码指示测试运行成功或失败。main

测试Loader参数必须为测试加载器实例,并默认为默认测试加载器。

main支持通过传递参数从交互式解释器使用 。这会在标准输出上显示结果,而不调用sys.exit():exit=False

>>>
>>> from unittest import main
>>> main(module='test_module', exit=False)

故障快、catchbreak 和缓冲区参数的效果与同名命令行选项相同。

警告参数指定在运行测试时应使用的警告筛选器。如果未指定,则如果选项传递到 python(请参阅警告控件),它将保留,否则它将设置为 。None-W'default'

调用实际上返回类的实例。这将存储作为属性运行的测试的结果。mainTestProgramresult

在版本 3.1 中更改:添加了退出参数。

在版本 3.2 中更改:增加了详细性、故障快、即入、缓冲和警告参数。

在版本 3.4 中更改:默认测试参数已更改为也接受可重复的测试名称。

load_tests 协议

3.2 新版功能.

模块或包可以通过实现名为 的函数自定义在正常测试运行或测试发现期间如何从它们加载测试。load_tests

如果测试模块定义,它将由TestLoader.loadTestsFromModule() 调用,并具有以下参数:load_tests

load_tests(loader, standard_tests, pattern)

其中模式直接从 中传递。它默认为 。loadTestsFromModuleNone

它应该返回一个测试套房。

加载器是执行加载的测试加载器的实例。standard_tests是默认情况下从模块加载的测试。测试模块通常只想从标准测试集添加或删除测试。在加载包作为测试发现的一部分时,使用第三个参数。

从一组特定的 TestCase 类加载测试的典型函数可能看起来像:load_tests

test_cases = (TestCase1, TestCase2, TestCase3)

def load_tests(loader, tests, pattern):
    suite = TestSuite()
    for test_class in test_cases:
        tests = loader.loadTestsFromTestCase(test_class)
        suite.addTests(tests)
    return suite

如果在包含包的目录中启动发现,请从命令行或调用TestLoader.discovery()来检测 该包。如果该函数不存在,则发现将重复到包中,就像它只是另一个目录一样。否则,将最多使用以下参数调用包测试的发现:init.pyload_testsload_tests

load_tests(loader, standard_tests, pattern)

这应返回一个表示包中所有测试的 TestSuite。(将仅包含从 收集的测试。standard_tests__init__.py

因为模式被传递到包中可以自由继续(并可能修改)测试发现。测试包的"不执行任何操作"功能可看起来像:load_testsload_tests

def load_tests(loader, standard_tests, pattern):
    # top level directory cached on loader instance
    this_dir = os.path.dirname(__file__)
    package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
    standard_tests.addTests(package_tests)
    return standard_tests

在 3.5 版更改:由于无法匹配默认模式的包名称,Discovery 不再检查包名称是否匹配模式。

类及模块级Fixtures

类和模块级夹具在TestSuite 中实现。当测试套件遇到来自新类的测试时,则调用上一个类(如果有)的测试,然后是新类的测试。tearDownClass()setUpClass()

同样,如果测试来自与上一个测试不同的模块,则运行与上一个模块的测试,然后是新模块。tearDownModulesetUpModule

在所有测试都运行到最终并运行之后。tearDownClasstearDownModule

请注意,共享固件不能很好地与 [潜在] 功能(如测试并行化)发挥好,并且它们打破了测试隔离。应小心使用。

单元测试测试加载程序创建的测试的默认顺序是将来自同一模块和类的所有测试分组在一起。这将导致 / (等) 每个类和模块被调用一次。如果随机化顺序,以便不同模块和类的测试彼此相邻,则这些共享固件函数可能在单个测试运行中多次调用。setUpClasssetUpModule

共享夹具不适用于非标准订购的套件。对于不想支持共享固件的框架,仍然存在。BaseTestSuite

如果在共享固件功能之一期间出现任何异常,则测试报告为错误。因为没有相应的测试实例,所以创建一个对象(与测试案例具有相同的接口)来表示错误。如果您只是使用标准单元测试测试运行程序,则此详细信息并不重要,但如果您是框架作者,则它可能相关。_ErrorHolder

setUpClass和tearDownClass

这些必须实现为类方法:

import unittest

class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls._connection = createExpensiveConnectionObject()

    @classmethod
    def tearDownClass(cls):
        cls._connection.destroy()

如果想要调用 和 基类,则必须自己调用它们。测试用例中的实现为空。setUpClasstearDownClass

如果在 期间引发异常,则类中的测试不运行,并且 不运行 。跳过的类将不具有或运行。如果异常是SkipTest异常,则类将报告为已跳过,而不是错误。setUpClasstearDownClasssetUpClasstearDownClass

setUpModule和tearDownModule

应作为函数实现这些功能:

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

如果在 中引发异常,则模块中没有任何测试将运行,并且 不会运行 。如果异常是SkipTest异常,则模块将报告为已跳过,而不是错误。setUpModuletearDownModule

若要添加即使在异常情况下也必须运行的清理代码,请使用 :addModuleCleanup

unittest.addModuleCleanup(function, /, *args, **kwargs)

添加一个函数,以在测试类期间使用清理资源。函数将按与添加顺序相反的顺序调用 (LIFO)。在添加它们时,使用传递给addModuleCleanup() 的任何参数和关键字参数来调用它们。tearDownModule()

如果失败,这意味着不调用,则仍将调用添加的任何清理函数。setUpModule()tearDownModule()

3.8 新版功能.

unittest.doModuleCleanups()

此函数在 之后或引发异常后无条件调用。tearDownModule()setUpModule()setUpModule()

它负责调用 中添加的所有清理函数。如果需要之前调用清理函数,可以自己调用doModuleCleanups()。 addCleanupModule()tearDownModule()

doModuleCleanups()将方法一次从清理函数堆栈中弹出,因此可以随时调用它。

3.8 新版功能.

信号量处理

3.2 新版功能.

-c/-catch

命令行选项到单元测试,以及到单元测试.main()的参数,在测试运行期间提供更友好的控制-C 处理。启用捕获中断行为控制-C 将允许当前正在运行的测试完成,然后测试运行将结束并报告到目前为止的所有结果。第二个控件 c 将按通常方式引发键盘中断。catchbreak

Ctrl-C 处理信号处理程序尝试与安装自己的信号的代码或测试保持兼容。SIGINT处理程序。如果处理程序被调用,但不是已安装的信号。SIGINT处理程序,即已被受测试的系统替换并委派给,然后调用默认处理程序。这通常是替换已安装的处理程序并将其委托给该处理程序的代码的预期行为。对于需要禁用控制-c 处理的单个测试,可以使用 removeHandler()修饰器。unittestunittest

框架作者有几个实用函数,用于在测试框架中启用 control-c 处理功能。

unittest.installHandler()

设置 Ctrl-C处理程序。当信号。收到SIGINT(通常响应用户按 Ctrl-C)所有已注册结果都已调用stop()。

unittest.registerResult(result)

注册一个测试结果对象以进行Ctrl-C 处理。注册结果会存储对它的弱引用,因此它不会阻止对结果进行垃圾回收。

如果未启用Ctrl-C处理,则注册 TestResult 对象没有副作用,因此测试框架可以无条件地注册它们创建的所有结果,而与是否启用处理不同。

unittest.removeResult(result)

删除已注册的结果。删除结果后,将不再对该结果对象调用stop()以响应 control-c。

unittest.removeHandler(function=None)

在没有参数调用时,此函数将删除Ctrl-C 处理程序(如果已安装)。此函数还可用作测试修饰器,以在执行测试时临时删除处理程序:

@unittest.removeHandler
def test_signal_handling(self):
    ...
posted @ 2020-07-13 10:08  韩志超  阅读(6515)  评论(0编辑  收藏  举报