unittest ——单元测试框架

源代码: Lib/unittest/__init__.py


(如果您已经熟悉测试的基本概念,您可能希望跳到 the list of assert methods

这个 unittest 单元测试框架最初是受JUnit的启发,与其他语言中的主要单元测试框架具有相似的风格。它支持测试自动化、共享测试的设置和关闭代码、将测试聚合到集合中以及独立于报告框架的测试。

为了实现这一目标, unittest 以面向对象的方式支持一些重要概念:

测试夹具

A test fixture 表示执行一个或多个测试所需的准备,以及任何相关的清理操作。例如,这可能涉及创建临时或代理数据库、目录或启动服务器进程。

测试用例

A test case 是单独的测试单元。它检查对特定输入集的特定响应。 unittest 提供基类, TestCase ,可用于创建新的测试用例。

测试套件

A test suite 是测试用例、测试套件或两者的集合。它用于聚合应该一起执行的测试。

试验转轮

A test runner 是协调测试执行并向用户提供结果的组件。运行程序可以使用图形界面、文本界面,或者返回一个特殊值来指示执行测试的结果。

参见

模块 doctest

另一个风格迥异的测试支持模块。

Simple Smalltalk Testing: With Patterns

KentBeck关于使用共享模式测试框架的原始论文 unittest .

pytest

第三方unittest框架,具有较轻的语法,用于编写测试。例如, assert func(10) == 42 .

The Python Testing Tools Taxonomy

大量的Python测试工具列表,包括功能测试框架和模拟对象库。

Testing in Python Mailing List

在Python中讨论测试和测试工具的特殊兴趣小组。

剧本 Tools/unittestgui/unittestgui.py 在Python中,源代码分发是用于测试发现和执行的GUI工具。这在很大程度上是为了便于新到单元测试的使用。对于生产环境,建议由连续集成系统驱动测试,例如 BuildbotJenkinsTravis-CIAppVeyor .

基本实例

这个 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 例外。

Signal Handling 用于提供此功能的函数。

-f, --failfast

在第一个错误或失败时停止测试运行。

-k

只运行与模式或子字符串匹配的测试方法和类。此选项可以多次使用,在这种情况下,所有与给定模式匹配的测试用例都包含在内。

包含通配符的模式 (* )与测试名称匹配,使用 fnmatch.fnmatchcase() 否则,将使用简单的区分大小写的子字符串匹配。

模式与测试加载程序导入的完全限定的测试方法名称相匹配。

例如, -k foo 比赛 foo_tests.SomeTest.test_somethingbar_tests.SomeTest.test_foo ,但不是 bar_tests.FooTest.test_something .

--locals

在回溯中显示局部变量。

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

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

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

命令行还可以用于测试发现、运行项目中的所有测试或仅运行一个子集。

测试发现

3.2 新版功能.

UnitTest支持简单的测试发现。为了与测试发现兼容,所有测试文件都必须 modulespackages (包括 namespace packages )可从项目的顶级目录导入(这意味着它们的文件名必须有效 identifiers

测试发现在 TestLoader.discover() ,但也可以从命令行使用。基本命令行用法是:

cd project_directory
python -m unittest discover

注解

作为捷径, python -m unittest 相当于 python -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 .

如果在全局安装了一个包,并尝试在该包的其他副本上进行测试发现,则导入 能够 从错误的地方发生。如果发生这种情况,测试发现将警告您并退出。

如果您以包名称而不是目录路径的形式提供起始目录,那么discover会假定从中导入的任何位置都是您想要的位置,因此不会收到警告。

测试模块和包可以通过 load_tests protocol .

在 3.4 版更改: 测试发现支持 namespace packages .

组织测试代码

单元测试的基本组成部分是 test cases ---必须设置和检查正确性的单一方案。在 unittest ,测试用例由 unittest.TestCase 实例。要创建自己的测试用例,必须编写 TestCase 或使用 FunctionTestCase .

A的测试代码 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))

注意,为了测试某些东西,我们使用 assert*() 方法由 TestCase 基类。如果测试失败,将引发异常并给出解释性消息,以及 unittest 将测试用例标识为 failure . 任何其他例外情况将被视为 errors .

测试可以是多个的,并且它们的设置可以是重复的。幸运的是,我们可以通过实现一个名为 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 . 一个新的测试用例实例被创建为一个独特的测试夹具,用于执行每个单独的测试方法。因此 setUp()tearDown()__init__() 每次测试调用一次。

建议您使用测试用例实现根据测试的特性将测试分组在一起。 unittest 为此提供了一种机制: test suite ,代表为 unittestTestSuite 类。在大多数情况下,调用 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)

注解

尽管 FunctionTestCase 可用于快速将现有测试库转换为 unittest -基于系统,不建议使用这种方法。花时间来设置适当的 TestCase 子类将使未来的测试重构变得极其容易。

在某些情况下,现有测试可能是使用 doctest 模块。如果是这样, doctest 提供了一个 DocTestSuite 可以自动生成的类 unittest.TestSuite 现有的实例 doctest 基于测试。

跳过测试和预期失败

3.1 新版功能.

UnitTest支持跳过单个测试方法,甚至跳过整个测试类。此外,它还支持将测试标记为“预期失败”,即破坏并将失败的测试,但不应计为 TestResult .

跳过测试只是使用 skip() decorator 或其条件变体之一,调用 TestCase.skipTest() 在一个 setUp() 或试验方法,或提高 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() decorator。::

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

以下修饰符和异常实现测试跳过和预期的失败:

@unittest.skip(reason)

无条件跳过修饰测试。 原因 应描述跳过测试的原因。

@unittest.skipIf(condition, reason)

如果 条件 是真的。

@unittest.skipUnless(condition, reason)

跳过装饰测试,除非 条件 是真的。

@unittest.expectedFailure

将测试标记为预期的失败或错误。如果测试失败或出错,将被视为成功。如果测试通过,将被视为失败。

exception unittest.SkipTest(reason)

引发此异常以跳过测试。

通常你可以用 TestCase.skipTest() 或者一个跳过装饰的人,而不是直接提出这个问题。

跳过的测试将不会 setUp()tearDown() 绕着他们运行。跳过的类将没有 setUpClass()tearDownClass() 运行。跳过的模块将没有 setUpModule()tearDownModule() 运行。

使用子测试区分测试迭代

3.4 新版功能.

当测试之间存在非常小的差异时,例如某些参数,UnitTest允许您使用 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

如果不使用子测试,执行将在第一次失败后停止,并且错误不太容易诊断,因为 i 不会显示::

======================================================================
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 .

测试用例

class unittest.TestCase(methodName='runTest')

的实例 TestCase 类表示中的逻辑测试单元 unittest 宇宙。这个类被用作一个基类,具体的测试由具体的子类实现。这个类实现了测试运行程序所需的接口,以允许它驱动测试,以及测试代码可以用来检查和报告各种失败的方法。

的每个实例 TestCase 将运行单个基方法:名为 调用的方法名 . 在大多数用途中 TestCase 你也不会改变 调用的方法名 也不重新履行违约 runTest() 方法。

在 3.2 版更改: TestCase 可以在不提供 调用的方法名 . 这使得试验更容易 TestCase 来自交互式解释器。

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

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

setUp()

方法来准备测试夹具。这是在调用测试方法之前立即调用的;而不是 AssertionErrorSkipTest ,此方法引发的任何异常都将被视为错误而不是测试失败。默认实现什么也不做。

tearDown()

方法在调用测试方法并记录结果后立即调用。即使测试方法引发了异常,也会调用此方法,因此子类中的实现可能需要特别注意检查内部状态。任何例外,除了 AssertionErrorSkipTest ,由此方法引发的将被视为额外的错误,而不是测试失败(从而增加报告的错误总数)。只有在 setUp() 不管测试方法的结果如何,都会成功。默认实现什么也不做。

setUpClass()

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

@classmethod
def setUpClass(cls):
    ...

Class and Module Fixtures 了解更多详细信息。

3.2 新版功能.

tearDownClass()

在单个类中的测试运行后调用的类方法。 tearDownClass 以类作为唯一参数调用,并且必须作为 classmethod() ::

@classmethod
def tearDownClass(cls):
    ...

Class and Module Fixtures 了解更多详细信息。

3.2 新版功能.

run(result=None)

运行测试,将结果收集到 TestResult 对象传递为 结果 . 如果 结果 被省略或 None ,将创建一个临时结果对象(通过调用 defaultTestResult() 方法)和使用。结果对象返回到 run() 调用的人

同样的效果也可以通过简单地调用 TestCase 实例。

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

skipTest(reason)

在测试方法或 setUp() 跳过当前测试。见 跳过测试和预期失败 更多信息。

3.1 新版功能.

subTest(msg=None, **params)

返回一个上下文管理器,该管理器将封闭的代码块作为子测试执行。 msg帕拉姆 是可选的、任意的值,在子测试失败时显示,允许您清楚地识别它们。

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

使用子测试区分测试迭代 更多信息。

3.4 新版功能.

debug()

运行测试而不收集结果。这允许将测试引发的异常传播到调用方,并可用于支持在调试器下运行测试。

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

方法

检查一下

新在

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 参数,如果指定,则用作失败时的错误消息(另请参见 longMessage )。注意, msg 关键字参数不能传递给 assertRaises()assertRaisesRegex()assertWarns()assertWarnsRegex() 仅当它们用作上下文管理器时。

assertEqual(first, second, msg=None)

测试那个 第一第二 一律平等。如果比较值不相等,测试将失败。

此外,如果 第一第二 与list、tuple、dict、set、frozenset或str类型完全相同,还是子类注册的任何类型 addTypeEqualityFunc() 将调用特定于类型的相等函数,以生成更有用的默认错误消息(另请参见 list of type-specific methods

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

在 3.2 版更改: assertMultiLineEqual() 添加为用于比较字符串的默认类型相等函数。

assertNotEqual(first, second, msg=None)

测试那个 第一第二 不相等。如果比较值相等,测试将失败。

assertTrue(expr, msg=None)
assertFalse(expr, msg=None)

测试那个 expr 为真(或假)。

注意这相当于 bool(expr) is True 而不是 expr is True (使用) assertIs(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() )要检查确切类型,请使用 assertIs(type(obj), cls) .

3.2 新版功能.

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

方法

检查一下

新在

assertRaises(exc, fun, *args, **kwds)

fun(*args, **kwds) 引发 exc

assertRaisesRegex(exc, r, fun, *args, **kwds)

fun(*args, **kwds) 引发 exc 消息与regex匹配 r

3.1

assertWarns(warn, fun, *args, **kwds)

fun(*args, **kwds) 引发 warn

3.2

assertWarnsRegex(warn, r, fun, *args, **kwds)

fun(*args, **kwds) 引发 warn 消息与regex匹配 r

3.2

assertLogs(logger, level)

这个 with 块日志 logger 以最小 level

3.4

assertNoLogs(logger, level)

这个 with 不阻止登录

记录器 以最小 水平

3.10

assertRaises(exception, callable, *args, **kwds)
assertRaises(exception, *, msg=None)

测试在以下情况下引发异常: 可赎回的 使用还传递给 assertRaises() . 如果 exception 如果引发另一个异常,则为错误;如果未引发异常,则为失败。要捕获一组异常中的任何一个,包含异常类的元组可以作为 exception .

如果只有 exception 可能还有 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 版更改: 增加了使用的能力 assertRaises() 作为上下文管理器。

在 3.2 版更改: 增加了 exception 属性。

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

assertRaisesRegex(exception, regex, callable, *args, **kwds)
assertRaisesRegex(exception, regex, *, msg=None)

类似于 assertRaises() 但也要测试一下 正则表达式 在引发的异常的字符串表示形式上匹配。 正则表达式 可以是正则表达式对象,也可以是包含适合于使用的正则表达式的字符串 re.search() . 实例:

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

或:

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

3.1 新版功能: 在名称下添加 assertRaisesRegexp .

在 3.2 版更改: 命名至 assertRaisesRegex() .

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

assertWarns(warning, callable, *args, **kwds)
assertWarns(warning, *, msg=None)

测试在以下情况下是否触发警告: 可赎回的 使用还传递给 assertWarns() . 如果 警告 如果不是,则触发并失败。任何异常都是错误。要捕获任何一组警告,可以将包含警告类的元组作为 警告 .

如果只有 警告 可能还有 msg 给出了参数,返回一个上下文管理器,以便测试中的代码可以内联写入,而不是作为函数写入:

with self.assertWarns(SomeWarning):
    do_something()

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

上下文管理器将在其 warning 属性,以及在中触发警告的源行 filenamelineno 属性。如果打算对捕获的警告执行附加检查,这可能很有用:

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)

类似于 assertWarns() 但也要测试一下 正则表达式 匹配已触发警告的消息。 正则表达式 可以是正则表达式对象,也可以是包含适合于使用的正则表达式的字符串 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)

一个上下文管理器,用于测试是否至少有一条消息登录到 logger 或者它的一个子项,至少 level .

如果给了, 记录器 应该是一个 logging.Logger 对象或一个 str 给出了一个伐木者的名字。默认值是根记录器,它将捕获未被非传播子记录器阻止的所有消息。

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

如果至少有一条消息在 with 块匹配 loggerlevel 条件,否则失败。

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

records

列表 logging.LogRecord 匹配日志消息的对象。

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 新版功能.

assertNoLogs(logger=None, level=None)

上下文管理器,用于测试是否没有消息记录在 记录器 或者它的一个孩子,至少 水平 .

如果给出的话, logger 应该是 logging.Logger 对象或 str 给出记录器的名称。默认值是根记录器,它将捕获所有消息。

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

不像 assertLogs() ,上下文管理器将不返回任何内容。

3.10 新版功能.

还可以使用其他方法执行更具体的检查,例如:

方法

检查一下

新在

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)

ab 不管元素的顺序如何,在同一个数字中具有相同的元素。

3.2

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

测试那个 第一第二 通过计算差,四舍五入到给定的十进制数,近似(或不近似)相等 地方 (默认为7),并与零进行比较。注意,这些方法将值四舍五入到给定的 小数位数 (如 round() 功能)而非 有效数字 .

如果 三角洲 提供而不是 地方 那么两者之间的区别 第一第二 必须小于或等于(或大于) 三角洲 .

二者兼备 三角洲地方 提高 TypeError .

在 3.2 版更改: assertAlmostEqual() 自动考虑比较相等的几乎相等的对象。 assertNotAlmostEqual() 如果对象比较相等,则自动失败。增加了 三角洲 关键字参数。

assertGreater(first, second, msg=None)
assertGreaterEqual(first, second, msg=None)
assertLess(first, second, msg=None)
assertLessEqual(first, second, msg=None)

测试那个 第一 分别为>、>=、<或<=than 第二 取决于方法名称。否则,测试将失败:

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

测试A 正则表达式 搜索匹配项(或不匹配) text . 如果失败,错误消息将包括模式和 text (或模式和 text 出乎意料的匹配)。 正则表达式 可以是正则表达式对象,也可以是包含适合于使用的正则表达式的字符串 re.search() .

3.1 新版功能: 在名称下添加 assertRegexpMatches .

在 3.2 版更改: 方法 assertRegexpMatches() 已重命名为 assertRegex() .

3.2 新版功能: assertNotRegex() .

3.5 新版功能: 名字 assertNotRegexpMatches 是的不推荐使用的别名 assertNotRegex() .

assertCountEqual(first, second, msg=None)

测试那个序列 第一 包含的元素与 第二 不管他们的顺序如何。否则,将生成一条错误消息,列出序列之间的差异。

重复元素是 not 比较时忽略 第一第二 . 它验证两个序列中每个元素的计数是否相同。相当于: assertEqual(Counter(list(first)), Counter(list(second))) 但也适用于一系列不可清洗的物体。

3.2 新版功能.

这个 assertEqual() 方法将同一类型的对象的相等性检查分派给不同类型的特定方法。这些方法已经为大多数内置类型实现,但也可以使用 addTypeEqualityFunc()

addTypeEqualityFunc(typeobj, function)

注册由调用的特定于类型的方法 assertEqual() 检查两个对象是否完全相同 Type Objo (不是子类)比较相等。 function 必须采用两个位置参数和第三个msg=none关键字参数,就像 assertEqual() 做。必须提高 self.failureException(msg) 当检测到前两个参数之间的不等式时——可能会提供有用的信息,并在错误消息中详细解释这些不等式。

3.1 新版功能.

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

方法

用于比较

新在

assertMultiLineEqual(a, b)

字符串

3.1

assertSequenceEqual(a, b)

序列

3.1

assertListEqual(a, b)

列表

3.1

assertTupleEqual(a, b)

元组

3.1

assertSetEqual(a, b)

集合或冻结集合

3.1

assertDictEqual(a, b)

迪茨

3.1

assertMultiLineEqual(first, second, msg=None)

测试多行字符串 第一 等于字符串 第二 . 当不等于突出显示差异的两个字符串的diff时,错误消息中将包含差异。在将字符串与 assertEqual() .

3.1 新版功能.

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

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

此方法不是由直接调用的 assertEqual() 但是它被用来实现 assertListEqual()assertTupleEqual() .

3.1 新版功能.

assertListEqual(first, second, msg=None)
assertTupleEqual(first, second, msg=None)

测试两个列表或元组是否相等。如果不是,则构造一条错误消息,只显示两者之间的差异。如果其中一个参数的类型错误,也会引发错误。在将列表或元组与 assertEqual() .

3.1 新版功能.

assertSetEqual(first, second, msg=None)

测试两组是否相等。如果不是,则会构造一条错误消息,列出集合之间的差异。在比较集合或冻结集合与 assertEqual() .

如果其中一个 第一第二 没有一个 set.difference() 方法。

3.1 新版功能.

assertDictEqual(first, second, msg=None)

测试两个词典是否相等。如果没有,则会构造一条错误消息,显示字典中的差异。默认情况下,此方法将用于比较调用中的字典 assertEqual() .

3.1 新版功能.

最后 TestCase 提供以下方法和属性:

fail(msg=None)

无条件地发出测试失败信号, msgNone 对于错误消息。

failureException

此类属性提供测试方法引发的异常。如果一个测试框架需要使用一个专门的异常(可能是为了携带额外的信息),那么它必须将这个异常子类化,以便“公平地”使用这个框架。此属性的初始值为 AssertionError .

longMessage

这个类属性决定当一个自定义失败消息作为msg参数传递给一个失败的assertxy调用时会发生什么。 True 是默认值。在这种情况下,自定义消息将附加到标准故障消息的末尾。当设置为 False ,自定义消息将替换标准消息。

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

在每次测试调用之前,类设置都会被重置。

3.1 新版功能.

maxDiff

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

设置 maxDiffNone 意味着没有差异的最大长度。

3.2 新版功能.

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

countTestCases()

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

defaultTestResult()

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

为了 TestCase 实例,这将始终是 TestResult 子类 TestCase 必要时应覆盖此项。

id()

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

shortDescription()

返回测试说明,或 None 如果没有提供说明。此方法的默认实现返回测试方法的docstring的第一行(如果可用),或者 None .

在 3.1 版更改: 在3.1中,这被更改为将测试名称添加到简短描述中,即使存在docstring。这导致了与UnitTest扩展的兼容性问题,并将添加测试名称移动到 TextTestResult 在Python 3.2中。

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

添加要在其之后调用的函数 tearDown() 清除测试期间使用的资源。函数将按与添加顺序相反的顺序调用 (LIFO )调用它们时,会将任何参数和关键字参数传递到 addCleanup() 当它们被添加时。

如果 setUp() 失败,意味着 tearDown() 未调用,则仍将调用添加的任何清理函数。

3.1 新版功能.

doCleanups()

在以下时间之后无条件调用此方法 tearDown() ,或之后 setUp() 如果 setUp() 引发异常。

它负责调用由 addCleanup() .如果需要调用清理函数 先前的tearDown() 然后你可以调用 doCleanups() 你自己。

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

3.1 新版功能.

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

添加要在其之后调用的函数 tearDownClass() 清理测试类期间使用的资源。函数将按与添加顺序相反的顺序调用 (LIFO )调用它们时,会将任何参数和关键字参数传递到 addClassCleanup() 当它们被添加时。

如果 setUpClass() 失败,意味着 tearDownClass() 未调用,则仍将调用添加的任何清理函数。

3.8 新版功能.

classmethod doClassCleanups()

在以下时间之后无条件调用此方法 tearDownClass() ,或之后 setUpClass() 如果 setUpClass() 引发异常。

它负责调用由添加的所有清理函数 addClassCleanup() 。如果需要调用清理函数 之前tearDownClass() 然后你就可以打电话给 doClassCleanups() 你自己。

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

3.8 新版功能.

class unittest.IsolatedAsyncioTestCase(methodName='runTest')

此类提供类似于 TestCase 并且还接受协程作为测试函数。

3.8 新版功能.

coroutine asyncSetUp()

方法来准备测试设备。这是在 setUp() . 在调用测试方法之前立即调用;而不是 AssertionErrorSkipTest ,此方法引发的任何异常都将被视为错误而不是测试失败。默认实现什么也不做。

coroutine asyncTearDown()

方法在调用测试方法并记录结果后立即调用。这是以前叫的 tearDown() . 即使测试方法引发异常,也会调用此函数,因此子类中的实现在检查内部状态时可能需要特别小心。任何例外,除了 AssertionErrorSkipTest ,由此方法引发的将被视为额外的错误,而不是测试失败(从而增加报告的错误总数)。只有在 asyncSetUp() 不管测试方法的结果如何,都会成功。默认实现什么也不做。

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

此方法接受可以用作清理函数的协同程序。

run(result=None)

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

说明顺序的示例:

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"] .

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

此类实现 TestCase 接口,它允许测试运行程序驱动测试,但不提供测试代码可以用来检查和报告错误的方法。这用于使用遗留测试代码创建测试用例,允许将其集成到 unittest -基于测试框架。

不推荐使用的别名

出于历史原因, TestCase 方法有一个或多个别名,现在已弃用。下表列出了正确的名称及其不推荐使用的别名:

方法名称

不推荐使用的别名

不推荐使用的别名

assertEqual()

故障排除

断言

assertNotEqual()

失效相等

断言笔记

assertTrue()

故障除非

assert_

assertFalse()

故障排除

assertRaises()

故障解除引发

assertAlmostEqual()

失败,除非是最重要的

断言最高级

assertNotAlmostEqual()

失败

断言不等于

assertRegex()

断言regexpmatches

assertNotRegex()

断言NotRegExpMatches

assertRaisesRegex()

断言RaisesRegExp

3.1 版后已移除: 第二列中列出的fail*别名已被弃用。

3.2 版后已移除: 第三列中列出的assert*别名已被弃用。

3.2 版后已移除: assertRegexpMatchesassertRaisesRegexp 已重命名为 assertRegex()assertRaisesRegex() .

3.5 版后已移除: 这个 assertNotRegexpMatches 名称已弃用,取而代之的是 assertNotRegex() .

分组测试

class unittest.TestSuite(tests=())

此类表示单个测试用例和测试套件的聚合。类提供测试运行程序所需的接口,以允许它像其他测试用例一样运行。运行一个 TestSuite 实例与在套件上迭代相同,分别运行每个测试。

如果 测验 如果给定,它必须是单个测试用例或其他将用于最初构建该套件的测试套件的不可重复项。稍后将提供其他方法向集合中添加测试用例和套件。

TestSuite 对象的行为很像 TestCase 对象,但它们实际上不实现测试。相反,它们被用来将测试聚合到应该一起运行的测试组中。可以使用一些附加方法将测试添加到 TestSuite 实例:

addTest(test)

添加 TestCaseTestSuite 到套房。

addTests(tests)

添加来自ITerable的所有测试 TestCaseTestSuite 此测试套件的实例。

这相当于迭代 测验 呼唤 addTest() 对于每个元素。

TestSuite 与共享以下方法 TestCase

run(result)

运行与此套件关联的测试,将结果收集到作为 结果 . 注意,与 TestCase.run()TestSuite.run() 要求传入结果对象。

debug()

运行与此套件关联的测试,而不收集结果。这允许将测试引发的异常传播到调用方,并可用于支持在调试器下运行测试。

countTestCases()

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

__iter__()

按a分组的测试 TestSuite 总是通过迭代访问。子类可以通过覆盖 __iter__() . 请注意,此方法可以在单个套件上多次调用(例如,当计算测试或比较是否相等时),因此之前通过重复迭代返回的测试 TestSuite.run() 每个调用迭代必须相同。后 TestSuite.run() ,除非调用方使用重写的子类,否则调用方不应依赖此方法返回的测试。 TestSuite._removeTestAtIndex() 保留测试引用。

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

在 3.4 版更改: 在早期版本中, TestSuite 保留对每个的引用 TestCase 之后 TestSuite.run() . 子类可以通过重写 TestSuite._removeTestAtIndex() .

在A的典型用法中 TestSuite 对象 run() 方法由 TestRunner 而不是由最终用户测试。

加载和运行测试

class unittest.TestLoader

这个 TestLoader 类用于从类和模块创建测试套件。通常,不需要创建此类的实例; unittest 模块提供了一个可以共享为 unittest.defaultTestLoader . 但是,使用子类或实例可以自定义某些可配置属性。

TestLoader 对象具有以下属性:

errors

加载测试时遇到的非致命错误的列表。加载器在任何时候都不能复位。致命错误由向调用方引发异常的相关方法发出信号。非致命错误也由运行时会引发原始错误的合成测试指示。

3.5 新版功能.

TestLoader 对象具有以下方法:

loadTestsFromTestCase(testCaseClass)

返回包含在 TestCase 衍生的 testCaseClass .

为每个方法创建一个测试用例实例 getTestCaseNames() . 默认情况下,这些是以 test .如果 getTestCaseNames() 不返回任何方法,但返回 runTest() 方法实现后,将为该方法创建一个单独的测试用例。

loadTestsFromModule(module, pattern=None)

返回包含在给定模块中的所有测试用例的套件。此方法搜索 模块 对于派生自 TestCase 并为为为类定义的每个测试方法创建类的实例。

注解

当使用的层次结构 TestCase -派生类在共享fixture和helper函数时很方便,在不打算直接实例化的基类上定义测试方法不能很好地使用此方法。然而,当固定装置不同并且在子类中定义时,这样做是有用的。

如果模块提供 load_tests 函数将调用它来加载测试。这允许模块自定义测试加载。这就是 load_tests protocol . 这个 模式 参数作为第三个参数传递给 load_tests .

在 3.2 版更改: 支持 load_tests 补充。

在 3.5 版更改: 无证和非官方的 use_load_tests 默认参数已弃用并被忽略,但由于向后兼容性,它仍然被接受。该方法现在还接受只包含关键字的参数 模式 传递给 load_tests 作为第三个参数。

loadTestsFromName(name, module=None)

返回一组给定字符串说明符的所有测试用例。

说明符 name 是一个“点式名称”,可以解析为模块、测试用例类、测试用例类内的测试方法,或者 TestSuite 实例,或返回 TestCaseTestSuite 实例。这些检查按这里列出的顺序应用;也就是说,可能的测试用例类上的方法将被选为“测试用例类中的测试方法”,而不是“可调用对象”。

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

该方法可选地解决 name 相对于给定的 模块 .

在 3.5 版更改: 如果一个 ImportErrorAttributeError 遍历时发生 name 然后将返回一个在运行时引发该错误的合成测试。这些错误包括在self.errors累积的错误中。

loadTestsFromNames(names, module=None)

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

getTestCaseNames(testCaseClass)

返回在中找到的方法名的排序序列 试验箱 ;这应该是 TestCase .

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

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

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

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

如果一个包(包含名为 __init__.py )如果找到,将检查包的 load_tests 功能。如果存在,则将调用 package.load_tests(loader, tests, pattern) . 测试发现会注意确保在调用期间仅检查一次包的测试,即使加载测试函数本身调用 loader.discover .

如果 load_tests 存在,则发现存在 not 再回到包中, load_tests 负责加载包中的所有测试。

故意不将模式存储为加载器属性,以便包可以继续发现自己。 top_level_dir 存储如此 load_tests 不需要将此参数传递给 loader.discover() .

start_dir 可以是点式模块名,也可以是目录。

3.2 新版功能.

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

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

的以下属性 TestLoader 可以通过对实例进行子类化或赋值来配置:

testMethodPrefix

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

这种影响 getTestCaseNames() 以及所有 loadTestsFrom*() 方法。

sortTestMethodsUsing

在对方法名进行排序时用于比较的函数 getTestCaseNames() 以及所有 loadTestsFrom*() 方法。

suiteClass

从测试列表构造测试套件的可调用对象。结果对象上不需要任何方法。默认值是 TestSuite 类。

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

testNamePatterns

测试方法必须匹配才能包含在测试套件中的unix shell样式通配符测试名称模式列表(请参见 -v 选择权。

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

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

3.7 新版功能.

class unittest.TestResult

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

A TestResult 对象存储一组测试的结果。这个 TestCaseTestSuite 类确保结果被正确地记录;测试作者不需要担心记录测试结果。

测试框架构建在 unittest 可能需要访问 TestResult 为报告目的运行一组测试生成的对象;a TestResult 实例由返回 TestRunner.run() 方法。

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

errors

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

failures

包含2个元组的列表 TestCase 保存格式化跟踪的实例和字符串。每个元组表示一个测试,其中使用 TestCase.assert*() 方法。

skipped

包含2个元组的列表 TestCase 包含跳过测试原因的实例和字符串。

3.1 新版功能.

expectedFailures

包含以下元素的2元组的列表 TestCase 实例和包含格式化回溯的字符串。每个元组表示测试用例的预期失败或错误。

unexpectedSuccesses

包含以下内容的列表 TestCase 标记为预期失败但成功的实例。

shouldStop

设置为 True 测试执行应在何时停止 stop() .

testsRun

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

buffer

如果设置为真, sys.stdoutsys.stderr 将在两者之间缓冲 startTest()stopTest() 正在被调用。收集到的输出将仅回显到 sys.stdoutsys.stderr 如果测试失败或错误。任何输出也附加到故障/错误消息上。

3.2 新版功能.

failfast

如果设置为真 stop() 将在第一次失败或错误时调用,停止测试运行。

3.2 新版功能.

tb_locals

如果设置为真,那么局部变量将显示在回溯中。

3.5 新版功能.

wasSuccessful()

返回 True 如果到目前为止运行的所有测试都已通过,否则返回 False .

在 3.4 版更改: 返回 False 如果有 unexpectedSuccesses 从标记有 expectedFailure() decorator。

stop()

可以调用此方法,通过设置 shouldStop 属性到 True . TestRunner 对象应尊重此标志并返回,而不运行任何其他测试。

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

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

startTest(test)

当测试用例 test 就要运行了。

stopTest(test)

在测试用例之后调用 test 已执行,无论结果如何。

startTestRun()

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

3.1 新版功能.

stopTestRun()

在执行所有测试后调用一次。

3.1 新版功能.

addError(test, err)

当测试用例 test 引发意外的异常。 err 是由返回的窗体的元组 sys.exc_info()(type, value, traceback) .

默认实现附加一个元组 (test, formatted_err) 到实例的 errors 属性,其中 formatted_err 是从 err .

addFailure(test, err)

当测试用例 test 表示故障。 err 是由返回的窗体的元组 sys.exc_info()(type, value, traceback) .

默认实现附加一个元组 (test, formatted_err) 到实例的 failures 属性,其中 formatted_err 是从 err .

addSuccess(test)

当测试用例 test 成功了。

默认实现什么也不做。

addSkip(test, reason)

当测试用例 test 跳过。 原因 是测试跳过的原因。

默认实现附加一个元组 (test, reason) 到实例的 skipped 属性。

addExpectedFailure(test, err)

当测试用例 test 失败或错误,但用 expectedFailure() 装饰师。

默认实现附加一个元组 (test, formatted_err) 到实例的 expectedFailures 属性,其中 formatted_err 是从 err .

addUnexpectedSuccess(test)

当测试用例 test 被标记为 expectedFailure() 但成功了。

默认实现将测试附加到实例的 unexpectedSuccesses 属性。

addSubTest(test, subtest, outcome)

当子测试完成时调用。 test 是与测试方法相对应的测试用例。 子测验 是习俗 TestCase 描述子测试的实例。

如果 结果None ,子测试成功。否则,它将失败,并出现一个异常,其中 结果 是由返回的窗体的元组 sys.exc_info()(type, value, traceback) .

当结果成功时,默认实现什么也不做,并将子测试失败记录为正常失败。

3.4 新版功能.

class unittest.TextTestResult(stream, descriptions, verbosity)

具体实施 TestResult 用于 TextTestRunner .

3.2 新版功能: 这个类以前是命名的 _TextTestResult . 旧名称仍作为别名存在,但已弃用。

unittest.defaultTestLoader

的实例 TestLoader 要共享的类。如果没有自定义 TestLoader 如果需要,可以使用此实例,而不是重复创建新实例。

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

将结果输出到流的基本测试运行程序实现。如果 流动None 默认情况下, sys.stderr 用作输出流。这个类有一些可配置的参数,但本质上非常简单。运行测试套件的图形应用程序应该提供替代实现。这样的实现应该接受 **kwargs 当特性添加到UnitTest时,构造运行程序的接口将发生更改。

默认情况下,此运行程序显示 DeprecationWarningPendingDeprecationWarningResourceWarningImportWarning 即使他们是 ignored by default . 由以下原因引起的拒绝警告: deprecated unittest methods 也有特殊情况,当警告过滤器 'default''always' ,它们在每个模块中只出现一次,以避免出现过多的警告消息。可以使用python的 -Wd-Wa 选项(见) Warning control )然后离开 警告None .

在 3.2 版更改: 增加了 warnings 参数。

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

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

_makeResult()

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

_makeResult() 实例化传入的类或可调用的 TextTestRunner 作为 resultclass 参数。它默认为 TextTestResult resultclass 提供。结果类是用以下参数实例化的:

stream, descriptions, verbosity
run(test)

此方法是 TextTestRunner . 此方法需要 TestSuiteTestCase 实例。一 TestResult 是通过调用 _makeResult() 然后运行测试并将结果打印到stdout。

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)

这个 默认测试 参数是单个测试的名称,或者是在没有通过指定测试名称的情况下要运行的测试名称的iterable。 argv . 如果未指定或 None 并且没有通过以下方式提供测试名称: argv ,中找到的所有测试 模块 正在运行。

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

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

这个 测试加载器 参数必须是 TestLoader 实例,默认为 defaultTestLoader .

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

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

这个 故障快速诱捕缓冲区 参数与相同的名称具有相同的效果 command-line options .

这个 警告 参数指定 warning filter 这应该在运行测试时使用。如果没有指定,它将保留 None 如果A -W 选项传递给 python (见 Warning control )否则将设置为 'default' .

调用 main 实际返回 TestProgram 类。它将运行的测试结果存储为 result 属性。

在 3.1 版更改: 这个 exit 已添加参数。

在 3.2 版更改: 这个 冗长故障快速诱捕缓冲区警告 已添加参数。

在 3.4 版更改: 这个 默认测试 参数也被更改为接受一个不可重复的测试名称。

负载测试协议

3.2 新版功能.

模块或包可以通过实现一个名为 load_tests .

如果测试模块定义 load_tests 它将由 TestLoader.loadTestsFromModule() 参数如下:

load_tests(loader, standard_tests, pattern)

在哪里? 模式 直接从 loadTestsFromModule . 它默认为 None .

它应该返回 TestSuite .

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

典型 load_tests 从特定集合加载测试的函数 TestCase 类可能如下所示:

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.discover() ,然后是包裹 __init__.py 将检查 load_tests . 如果该函数不存在,则发现将重新出现在包中,就像它只是另一个目录一样。否则,包测试的发现将保留到 load_tests 使用以下参数调用:

load_tests(loader, standard_tests, pattern)

这应该返回 TestSuite 表示包中的所有测试。 (standard_tests 将只包含从中收集的测试 __init__.py

因为模式被传递到 load_tests 该包可以自由地继续(并且可能修改)测试发现。“无所事事” load_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 版更改: 发现不再检查包名称是否匹配 模式 因为包名称不可能与默认模式匹配。

类和模块夹具

类和模块级设备实现于 TestSuite . 当测试套件遇到来自新类的测试时, tearDownClass() 从上一个类(如果有)调用,后跟 setUpClass() 从新类。

同样,如果一个测试来自与前一个测试不同的模块,那么 tearDownModule 从上一个模块运行,然后 setUpModule 来自新模块。

在所有的测试完成后 tearDownClasstearDownModule 正在运行。

请注意,共享设备不能很好地与 [潜在的] 像测试并行化和破坏测试隔离之类的特性。使用时应小心。

UnitTest测试加载程序创建的测试的默认顺序是将同一模块和类中的所有测试组合在一起。这将导致 setUpClass / setUpModule (等)在每个类和模块中被调用一次。如果您随机化顺序,使来自不同模块和类的测试彼此相邻,那么这些共享的fixture函数可以在单个测试运行中多次调用。

共享设备不适用于非标准订购的套房。一 BaseTestSuite 对于不希望支持共享设备的框架仍然存在。

如果在某个共享夹具功能期间出现任何异常,则将测试报告为错误。因为没有对应的测试实例 _ErrorHolder 对象(具有与 TestCase )创建以表示错误。如果您只是使用标准的UnitTest测试运行程序,那么这个细节并不重要,但是如果您是框架作者,那么它可能是相关的。

设置类和拆卸类

这些必须作为类方法实现:

import unittest

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

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

如果你想要 setUpClasstearDownClass 在调用的基类上,您必须自己调用它们。中的实现 TestCase 是空的。

如果在 setUpClass 那么类中的测试就不会运行, tearDownClass 不运行。跳过的类将没有 setUpClasstearDownClass 运行。如果例外是 SkipTest 异常,则该类将被报告为已跳过而不是错误。

设置模块和拆卸模块

这些应该作为函数来实现:

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

如果在 setUpModule 然后模块中的任何测试都不会运行,并且 tearDownModule 不会运行。如果例外是 SkipTest 异常,则模块将被报告为已跳过而不是错误。

要添加即使在发生异常时也必须运行的清理代码,请使用 addModuleCleanup

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

添加要在其之后调用的函数 tearDownModule() 清理测试类期间使用的资源。函数将按与添加顺序相反的顺序调用 (LIFO )调用它们时,会将任何参数和关键字参数传递到 addModuleCleanup() 当它们被添加时。

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

3.8 新版功能.

unittest.doModuleCleanups()

此函数在以下时间之后无条件调用 tearDownModule() ,或之后 setUpModule() 如果 setUpModule() 引发异常。

它负责调用由 addCleanupModule() .如果需要调用清理函数 先前的tearDownModule() 然后你可以调用 doModuleCleanups() 你自己。

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

3.8 新版功能.

信号处理

3.2 新版功能.

这个 -c/--catch 用于UnitTest的命令行选项,以及 catchbreak 参数到 unittest.main() ,在测试运行期间提供对Control-C更友好的处理。启用catch break行为后,control-c将允许当前运行的测试完成,然后测试运行将结束并报告到目前为止的所有结果。第二个控制器C将引发 KeyboardInterrupt 以通常的方式。

Control-C处理信号处理程序试图与安装自己的代码或测试保持兼容。 signal.SIGINT 处理程序。如果 unittest 调用了处理程序,但 不是 安装的 signal.SIGINT 处理程序,即它已经被被被测试的系统替换并委托给,然后它调用默认的处理程序。这通常是替换已安装处理程序并委托给它的代码所期望的行为。对于需要 unittest Control-C处理已禁用 removeHandler() 可以使用装饰器。

框架作者可以使用一些实用程序函数在测试框架中启用Control-C处理功能。

unittest.installHandler()

安装Control-C处理程序。当A signal.SIGINT 收到(通常是响应用户按control-c)所有注册结果 stop() 调用。

unittest.registerResult(result)

注册A TestResult 用于Control-C处理的对象。注册结果会存储对它的弱引用,因此它不会阻止对结果进行垃圾收集。

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

unittest.removeResult(result)

删除已注册的结果。一旦结果被删除,那么 stop() 将不再对该结果对象调用以响应Control-C。

unittest.removeHandler(function=None)

在没有参数的情况下调用此函数时,如果已安装了Control-C处理程序,则该函数将删除它。此函数还可用作测试装饰器,以便在执行测试时临时删除处理程序::

@unittest.removeHandler
def test_signal_handling(self):
    ...