26.4. unittest — 单元测试框架

源代码: Lib / unittest / __ init __。py

(如果您已经熟悉测试的基本概念,你可能想要跳到 assert 方法列表。)

unittest 单元测试框架最初灵感来自 JUnit,和其他语言的主要单元测试框架有相似的风格。它支持测试自动化,共享的设置和关闭代码测试,测试聚集成集合,以及从报告框架上进行独立测试。

要实现这一目标,unittest 在面向对象方法上支持一些重要的概念︰

测试夹具
测试夹具表示执行一个或多个测试以及任何关联的清除操作所需的准备工作。这可能涉及例如创建临时或代理数据库,目录或启动服务器进程。
测试用例
测试用例是测试的单独单元。它检查对特定输入集合的特定响应。unittest提供了一个基类,TestCase,可用于创建新的测试用例。
测试套件
测试套件是测试用例,测试套件或两者的容器。它用于聚合应该一起执行的测试。
测试跑步者
测试运行器是协调测试执行并向用户提供结果的组件。运行器可以使用图形界面,文本界面,或返回特定值来指示执行测试的结果。

也可以看看

模块doctest
另一个具有非常不同风味的测试支持模块。
简单Smalltalk测试:使用模式
Kent Beck关于使用由unittest共享的模式的测试框架的原始文章。
Nosepy.test
第三方单元测试框架具有用于书写测试的更轻量级语法。例如,断言 func(10) == 42
Python测试工具分类
广泛的Python测试工具列表,包括功能测试框架和模拟对象库。
在Python邮件列表中测试
在Python中讨论测试和测试工具的特殊兴趣小组。

Python源代码分发中的脚本Tools/unittestgui/unittestgui.py是用于测试发现和执行的GUI工具。这主要是为了易于使用那些新的单元测试。对于生产环境,建议由连续集成系统(例如BuildbotJenkinsHudson)来驱动测试。

26.4.1. Basic example

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()方法允许您定义将在每个测试方法之前和之后执行的指令。它们在Organizing test code部分中有更详细的介绍。

最后一个块显示了一种运行测试的简单方法。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功能,足以满足许多日常测试需求。本文档的其余部分探讨了第一个原则的完整功能集。

26.4.2. Command-Line Interface

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

当不带参数执行时Test Discovery开始:

python -m unittest

有关所有命令行选项的列表:

python -m unittest -h

在版本3.2中更改:在早期版本中,只能运行单个测试方法,而不是模块或类。

26.4.2.1. Command-line options

unittest支持下列命令行选项:

-b, --buffer

标准输出和标准错误流在测试运行期间进行缓冲。丢弃通过测试期间的输出。输出在测试失败或错误时正常回显,并添加到失败消息中。

-c, --catch

Control-C在测试运行期间等待当前测试结束,然后报告所有结果。第二个Control-C引发正常的KeyboardInterrupt异常。

有关提供此功能的函数,请参见信号处理

-f, --failfast

在第一个错误或故障时停止测试运​​行。

--locals

在traceback中显示局部变量。

版本3.2中的新功能:添加了命令行选项-b-c-f

版本3.5中的新功能:命令行选项--locals

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

26.4.3. Test Discovery

版本3.2中的新功能。

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

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

cd project_directory
python -m unittest discover

注意

作为一个捷径,python -m unittest等效于python t5 > -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协议自定义测试加载和发现。

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

26.4.4. Organizing test code

单元测试的基本构建块是测试用例 - 必须设置和检查正确性的单个场景。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()

测试代码的这种工作环境称为fixture

测试用例实例根据其测试的功能分组在一起。unittest提供了一种机制:测试套件,由unittestTestSuite类表示。在大多数情况下,调用unittest.main()会做正确的事情,并收集所有模块的测试用例,然后执行它们。

但是,如果您想要自定义测试套件的构建,您可以自己做:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_size'))
    suite.addTest(WidgetTestCase('test_resize'))
    return suite

您可以将测试用例和测试套件的定义放在与要测试的代码相同的模块中(例如widget.py),但将测试代码放在单独的模块,例如test_widget.py

  • 测试模块可以从命令行独立运行。
  • 测试代码可以更容易地与运输代码分开。
  • 有更少的诱惑改变测试代码,以适应代码测试没有一个很好的理由。
  • 测试代码的修改频率要比它测试的代码少得多。
  • 测试代码可以更容易重构。
  • 用C编写的模块的测试必须在单独的模块中,所以为什么不一致?
  • 如果测试策略更改,则不需要更改源代码。

26.4.5. Re-using old test code

一些用户会发现他们有现成的测试代码,他们希望从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类,可以从现有的doctest自动构建unittest.TestSuite测试。

26.4.6. Skipping tests and expected failures

版本3.1中的新功能。

Unittest支持跳过单独的测试方法,甚至整个测试类。此外,它支持将测试标记为“预期故障”,这种测试被破坏并且将失败,但不应被视为TestResult上的失败。

跳过测试只需使用skip() decorator或其条件变体。

基本跳过看起来像这样:

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

这是在详细模式中运行上面的示例的输出:

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

----------------------------------------------------------------------
Ran 3 tests in 0.005s

OK (skipped=3)

类可以像方法一样跳过:

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

以下装饰器实现测试跳过和预期故障:

@unittest.skip(reason)

无条件跳过装饰测试。reason应该描述为什么跳过测试。

@unittest.skipIf(condition, reason)

如果条件为真,则跳过装饰测试。

@unittest.skipUnless(condition, reason)

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

@unittest.expectedFailure

将测试标记为预期故障。如果运行时测试失败,则测试不会被视为失败。

exception unittest.SkipTest(reason)

引发此异常以跳过测试。

通常你可以使用TestCase.skipTest()或跳过一个装饰器,而不是直接提高它。

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

26.4.7. Distinguishing test iterations using subtests

版本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

26.4.8. Classes and functions

本节深入介绍unittest的API。

26.4.8.1. Test cases

class unittest.TestCase(methodName='runTest')

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

TestCase的每个实例将运行单个基本方法:名为methodName的方法。TestCase的大多数使用中,您不会更改methodName也不会重新实现默认的runTest()方法。

在版本3.2中更改: TestCase可以成功实例化,而不提供methodName这使得更容易从交互式解释器中测试TestCase

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

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

setUp()

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

tearDown()

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

setUpClass()

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

@classmethod
def setUpClass(cls):
    ...

有关详细信息,请参见类和模块夹具

版本3.2中的新功能。

tearDownClass()

在单个类中的测试之后调用的类方法已运行。tearDownClass以类作为唯一参数进行调用,必须装饰为classmethod()

@classmethod
def tearDownClass(cls):
    ...

有关详细信息,请参见类和模块夹具

版本3.2中的新功能。

run(result=None)

运行测试,将结果收集到作为结果传递的TestResult对象中。如果省略结果None,则创建临时结果对象(通过调用defaultTestResult()方法)并使用。结果对象返回到run()的调用者。

只需调用TestCase实例,可以获得相同的效果。

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

skipTest(reason)

在测试方法或setUp()期间调用此方法将跳过当前测试。有关详细信息,请参阅Skipping tests and expected failures

版本3.1中的新功能。

subTest(msg=None, **params)

返回一个执行封闭代码块作为子测试的上下文管理器。msgparams是可选的,任何值,当子测试失败时显示,允许您清楚地标识它们。

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

有关详细信息,请参见Distinguishing test iterations using subtests

版本3.4中的新功能。

debug()

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

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

方法检查新的
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) True
assertFalse(x)bool(x) False
assertIs(a, b)a b3.1
assertIsNot(a, b)a 不是 b3.1
assertIsNone(x)x 3.1
assertIsNotNone(x)x 不是 3.1
assertIn(a, b)a b3.1
assertNotIn(a, b)a 不是 b3.1
assertIsInstance(a, b)isinstance(a, b)3.2
assertNotIsInstance(a, b)不是 isinstance(a, b)3.2

所有assert方法都接受一个msg参数,如果指定,则用作失败时的错误消息(参见longMessage)。Note that the msg keyword argument can be passed to assertRaises(), assertRaisesRegex(), assertWarns(), assertWarnsRegex() only when they are used as a context manager.

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是true(或false)。

Note that this is equivalent to bool(expr) is True and not to expr is True (use assertIs(expr, True) for the latter). 当更具体的方法可用时,也应该避免这种方法。assertEqual(a, b)而不是assertTrue(a == t5 > b)),因为它们在出现故障时提供更好的错误消息。

assertIs(first, second, msg=None)
assertIsNot(first, second, msg=None)

测试第一第二计算(或不计算)到同一个对象。

版本3.1中的新功能。

assertIsNone(expr, msg=None)
assertIsNotNone(expr, msg=None)

测试expr是(或不是)无。

版本3.1中的新功能。

assertIn(first, second, msg=None)
assertNotIn(first, second, msg=None)

Test that first is (or is not) in second.

版本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 t4>3.1
assertWarns(warn, fun, *args, **kwds)fun(* args, ** kwds)引发警告3.2
assertWarnsRegex(warn, r, fun, *args, **kwds)fun(* args, ** kwds)引发警告并且邮件与regex t4>3.2
assertLogs(logger, level)with阻止日志logger,最小3.4
assertRaises(exception, callable, *args, **kwds)
assertRaises 例外msg =无

测试当调用可调用时的任何位置或关键字参数也传递到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中已更改:添加了使用assertRaises()作为上下文管理器的功能。

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

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

assertRaisesRegex(exception, regex, callable, *args, **kwds)
assertRaisesRegex 异常regexmsg = None t5>

assertRaises(),但也测试regex匹配引发异常的字符串表示。regex可以是正则表达式对象或包含适用于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 警告msg =无

测试使用也传递到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 警告regexmsg =无 t5>

assertWarns(),但也测试regex匹配触发警告的消息。regex可以是正则表达式对象或包含适用于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或其中一个子项上,至少包含给定的级别

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

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

如果在with块内发出的至少一个消息与logger条件匹配,则测试通过,否则失败。

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

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中的新功能。

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

方法检查新的
assertAlmostEqual(a, b)round(a-b, 7) == 0
assertNotAlmostEqual(a, b)round(a-b, 7) != 0
assertGreater(a, b)a > b3.1
assertGreaterEqual(a, b)a > = b3.1
assertLess(a, b)a b3.1
assertLessEqual(a, b)a b3.1
assertRegex(s, r)r.search(s)3.1
assertNotRegex(s, r)不是 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()函数)而不是有效数字

如果提供delta而不是位置,则第一第二之间的差必须小于或等于大于)delta

提供delta放置引发TypeError

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

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. 如果没有,测试将失败:

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

测试regex搜索是否与文本匹配(或不匹配)。如果失败,错误消息将包括模式和文本(或模式和文本的意外匹配的部分)。regex可以是正则表达式对象或包含适用于re.search()的正则表达式的字符串。

版本3.1中的新功能:名称assertRegexpMatches

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

版本3.2中的新功能: assertNotRegex()

assertCountEqual(first, second, msg=None)

测试序列第一包含与第二相同的元素,而不考虑它们的顺序。当它们不存在时,将生成列出序列之间的差异的错误消息。

当比较第一第二时,重复的元素不会被忽略。它验证每个元素在两个序列中是否具有相同的计数。等效于:assertEqual(Counter(list(first)), Counter(list(second))) 好。

版本3.2中的新功能。

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

addTypeEqualityFunc(typeobj, function)

注册由assertEqual()调用的特定于类型的方法,以检查两个完全相同的对象typeobj(不是子类)是否相等。函数必须包含两个位置参数和第三个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)集或frozensets3.1
assertDictEqual(a, b)dicts3.1
assertMultiLineEqual(first, second, msg=None)

测试多行字符串第一等于字符串第二当不相等时,高亮显示差异的两个字符串的diff将包含在错误消息中。在将字符串与assertEqual()进行比较时,默认使用此方法。

版本3.1中的新功能。

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

测试两个序列是否相等。如果提供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

如果设置为True,则您传递到assert methods的任何显式失败消息将附加到正常失败消息的结尾。正常消息包含有关所涉及对象的有用信息,例如来自assertEqual的消息显示两个不等对象的repr。将此属性设置为True允许您除了常规错误消息之外还有自定义错误消息。

此属性默认为True如果设置为False,则传递给assert方法的自定义消息将使正常消息静音。

通过在调用assert方法之前将实例属性分配给TrueFalse,可以在单个测试中覆盖类设置。

版本3.1中的新功能。

maxDiff

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

maxDiff设置为None意味着diff的最大长度没有。

版本3.2中的新功能。

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

countTestCases()

返回此测试对象表示的测试数。对于TestCase实例,这总是1

defaultTestResult()

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

对于TestCase实例,这将始终是TestResult的实例; TestCase的子类必须根据需要覆盖它。

id()

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

shortDescription()

返回测试的描述,如果未提供描述,则返回None此方法的默认实现返回测试方法的docstring的第一行(如果可用)或None

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

addCleanup(function, *args, **kwargs)

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

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

版本3.1中的新功能。

doCleanups()

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

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

doCleanups()一次一个地清除堆栈清理函数的方法,因此可以随时调用。

版本3.1中的新功能。

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

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

26.4.8.1.1. Deprecated aliases

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

Method Name Deprecated alias Deprecated alias
assertEqual() failUnlessEqual assertEquals
assertNotEqual() failIfEqual assertNotEquals
assertTrue() failUnless assert_
assertFalse() failIf
assertRaises() failUnlessRaises
assertAlmostEqual() failUnlessAlmostEqual assertAlmostEquals
assertNotAlmostEqual() failIfAlmostEqual assertNotAlmostEquals
assertRegex() assertRegexpMatches
assertRaisesRegex() assertRaisesRegexp

Deprecated since version 3.1: the fail* aliases listed in the second column.

Deprecated since version 3.2: the assert* aliases listed in the third column.

Deprecated since version 3.2: assertRegexpMatches and assertRaisesRegexp have been renamed to assertRegex() and assertRaisesRegex()

26.4.8.2. Grouping tests

class unittest.TestSuite(tests=())

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

如果给出tests,它必须是单独的测试用例或其他测试套件的迭代,用于最初构建套件。提供了附加的方法以将测试用例和套件添加到容器中。

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

addTest(test)

向套件中添加TestCaseTestSuite

addTests(tests)

将所有测试从TestCaseTestSuite实例的迭代中添加到此测试套件。

这相当于对测试进行迭代,对每个元素调用addTest()

TestSuiteTestCase共享以下方法:

run(result)

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

debug()

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

countTestCases()

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

__iter__()

通过TestSuite分组的测试始终通过迭代访问。子类可以通过覆盖__iter__()来缓慢提供测试。请注意,此方法可能在单个套件上调用多次(例如,在计数测试或比较等式时),因此在TestSuite.run()之前重复迭代返回的测试必须对每个调用迭代。TestSuite.run()之后,调用者不应依赖此方法返回的测试,除非调用者使用覆盖TestSuite._removeTestAtIndex()的子类来保留测试引用。

在版本3.2中更改:在早期版本中,TestSuite直接访问测试,而不是通过迭代,因此覆盖__iter__()测试。

Changed in version 3.4: In earlier versions the TestSuite held references to each TestCase after TestSuite.run(). 子类可以通过覆盖TestSuite._removeTestAtIndex()来恢复该行为。

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

26.4.8.3. Loading and running tests

class unittest.TestLoader

TestLoader类用于从类和模块创建测试套件。通常,没有必要创建这个类的实例; unittest模块提供了一个实例,可以作为unittest.defaultTestLoader共享。然而,使用子类或实例,允许定制一些可配置属性。

TestLoader对象具有以下属性:

errors

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

版本3.5中的新功能。

TestLoader对象有以下方法:

loadTestsFromTestCase(testCaseClass)

返回一组包含在TestCase -derived testCaseClass中的所有测试用例。

为由getTestCaseNames()命名的每个方法创建一个测试用例实例。默认情况下,这些是以test开头的方法名称。如果getTestCaseNames()没有返回方法,但是实现了runTest()方法,则会为该方法创建一个测试用例。

loadTestsFromModule(module, pattern=None)

返回一组包含在给定模块中的所有测试用例。此方法在模块中搜索从TestCase派生的类,并为为类定义的每个测试方法创建类的实例。

注意

虽然使用TestCase派生类的层次结构可以方便地共享fixture和辅助函数,但是在不打算直接实例化的基类上定义测试方法对此方法并不适用。但是,当夹具不同并且在子类中定义时,这样做是有用的。

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

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

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

loadTestsFromName(name, module=None)

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

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

For example, if you have a module SampleTests containing a TestCase-derived class SampleTestCase with three test methods (test_one(), test_two(), and test_three()), the specifier 'SampleTests.SampleTestCase' would cause this method to return a suite which will run all three test methods. 使用说明符'SampleTests.SampleTestCase.test_two'会导致它返回一个只运行test_two()测试方法的测试套件。说明符可以指未导入的模块和包;它们将作为副作用导入。

该方法可选地相对于给定的模块解析名称

在版本3.5中已更改:如果在遍历名称时发生ImportErrorAttributeError,那么将引发该错误当运行时会返回。这些错误包含在由self.errors累积的错误中。

loadTestsFromNames(names, module=None)

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

getTestCaseNames(testCaseClass)

返回在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)测试发现需要确保在调用期间只检查包一次,即使load_tests函数本身调用loader.discover

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

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

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

版本3.2中的新功能。

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

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

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

testMethodPrefix

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

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

sortTestMethodsUsing

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

suiteClass

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

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

class unittest.TestResult

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

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

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

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

errors

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

failures

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

skipped

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

版本3.1中的新功能。

expectedFailures

包含2元组的TestCase实例和保存格式化回迹的字符串的列表。每个元组表示测试用例的预期故障。

unexpectedSuccesses

包含标记为预期故障但已成功的TestCase实例的列表。

shouldStop

当测试的执行应由stop()停止时,设置为True

testsRun

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

buffer

If set to true, sys.stdout and sys.stderr will be buffered in between startTest() and stopTest() being called. 如果测试失败或错误,收集的输出将只会被回送到真实的sys.stdoutsys.stderr任何输出也附加到故障/错误消息。

版本3.2中的新功能。

failfast

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

版本3.2中的新功能。

tb_locals

如果设置为true,那么局部变量将显示在traceback中。

版本3.5中的新功能。

wasSuccessful()

如果所有运行的测试都已通过,则返回True,否则返回False

在版本3.4中更改:如果在标记有expectedFailure()装饰器的测试中存在任何unexpectedSuccesses,则返回False

stop()

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

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

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

startTest(test)

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

stopTest(test)

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

startTestRun()

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

版本3.1中的新功能。

stopTestRun()

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

版本3.1中的新功能。

addError(test, err)

当测试用例测试时调用引发意外异常。errsys.exc_info()(type, value, t6)返回的形式的元组> traceback)

The default implementation appends a tuple (test, formatted_err) to the instance’s errors attribute, where formatted_err is a formatted traceback derived from err.

addFailure(test, err)

当测试用例测试发生故障时调用。errsys.exc_info()(type, value, t6)返回的形式的元组> traceback)

The default implementation appends a tuple (test, formatted_err) to the instance’s failures attribute, where formatted_err is a formatted traceback derived from err.

addSuccess(test)

当测试用例测试成功时调用。

默认实现什么也不做。

addSkip(test, reason)

当跳过测试用例测试时调用。reason是测试给出的跳过原因。

默认实现将tuple (测试, 原因)附加到实例的skipped属性。

addExpectedFailure(test, err)

当测试用例测试失败时调用,但标记为expectedFailure()装饰器。

The default implementation appends a tuple (test, formatted_err) to the instance’s expectedFailures attribute, where formatted_err is a formatted traceback derived from err.

addUnexpectedSuccess(test)

当测试用例测试被标记为expectedFailure()装饰器时调用,但成功。

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

addSubTest(test, subtest, outcome)

当子测验完成时调用。test是对应于测试方法的测试用例。subtest是描述子测试的自定义TestCase实例。

如果结果None,则子成功。否则,它失败,并且结果sys.exc_info()返回的形式的元组:(type, 值, traceback)

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

版本3.4中的新功能。

class unittest.TextTestResult(stream, descriptions, verbosity)

TextTestRunner使用的TestResult的具体实现。

版本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时构造runners变化。

By default this runner shows DeprecationWarning, PendingDeprecationWarning, ResourceWarning and ImportWarning even if they are ignored by default. deprecated unittest methods导致的弃用警告也是特殊情况,当警告过滤器为'default''always'时,每个模块只出现一次,以避免过多的警告消息。此行为可以使用-Wd-Wa选项覆盖,并将警告替换为None

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

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

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

_makeResult()

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

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

stream, descriptions, verbosity
run(test)

此方法是TextTestRunner的主要公共接口。此方法采用TestSuiteTestCase实例。通过调用_makeResult()创建TestResult,并运行测试,并将结果打印到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)

如果没有通过argv指定测试名称,则defaultTest参数是单个测试的名称或要运行的测试名称的可迭代。如果未指定或None且没有通过argv提供测试名称,则会运行模块中找到的所有测试。

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

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

testLoader参数必须是TestLoader实例,默认为defaultTestLoader

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

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

failfastcatchbreak缓冲参数与same-name 命令行选项具有相同的效果。

警告参数指定在运行测试时应使用的warning filter如果未指定,则如果将-W选项传递给python,则将保持None,否则将设置为'default'

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

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

Changed in version 3.2: The verbosity, failfast, catchbreak, buffer and warnings parameters were added.

在版本3.4中更改: defaultTest参数已更改为也接受测试名称的可迭代。

26.4.8.3.1. load_tests协议

版本3.2中的新功能。

模块或包可以通过实现称为load_tests的函数来定制在正常测试运行或测试发现期间从它们加载测试的方式。

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

load_tests(loader, standard_tests, pattern)

其中模式loadTestsFromModule直接传递。默认为None

它应该返回TestSuite

loaderTestLoader执行加载的实例。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

If discovery is started in a directory containing a package, either from the command line or by calling TestLoader.discover(), then the package __init__.py will be checked for load_tests. 如果该函数不存在,发现将递归到包中,就像它只是另一个目录。否则,发现程序包的测试将保留到load_tests,它使用以下参数调用:

load_tests(loader, standard_tests, pattern)

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

因为模式被传递到load_tests,所以程序包可以自由地继续(并潜在地修改)测试发现。对于测试包,“do nothing”的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版本中已更改:由于包名称不可能匹配默认模式,发现不再检查包名称是否与模式匹配。

26.4.9. Class and Module Fixtures

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

类似地,如果测试来自与先前测试不同的模块,则运行来自先前模块的tearDownModule,接着从新模块运行setUpModule

在所有测试运行后,运行最后的tearDownClasstearDownModule

请注意,共享夹具不能很好地与测试并行化的潜在特性一起工作,并且它们会破坏测试隔离。他们应该小心使用。

由单元测试装载器创建的测试的默认顺序是将来自相同模块和类的所有测试分组在一起。这将导致每个类和模块只调用一次setUpClass / setUpModule(etc)。如果随机化订单,使得来自不同模块和类的测试彼此相邻,则这些共享夹具函数可以在单个测试运行中被多次调用。

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

如果在一个共享夹具函数中出现任何异常,则测试报告为错误。因为没有相应的测试实例创建一个_ErrorHolder对象(与TestCase具有相同的接口)来表示错误。如果你只是使用标准单元测试运行器,那么这个细节并不重要,但如果你是一个框架作者,它可能是相关的。

26.4.9.1. setUpClass和tearDownClass

这些必须实现为类方法:

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异常,那么类将被报告为已跳过,而不是错误。

26.4.9.2. setUpModule和tearDownModule

这些应作为功能实现:

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

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

26.4.10. Signal Handling

版本3.2中的新功能。

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

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

框架作者有几个实用函数,用于在测试框架内启用控制c处理功能。

unittest.installHandler()

安装control-c处理程序。当接收到signal.SIGINT(通常响应于用户按下control-c)所有注册的结果都会调用stop()

unittest.registerResult(result)

为控制c处理注册TestResult对象。注册结果会存储一个弱引用,因此它不会阻止结果被垃圾回收。

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

unittest.removeResult(result)

删除已注册的结果。一旦结果被移除,则对于响应控制c的stop()将不再对该结果对象进行调用。

unittest.removeHandler(function=None)

当调用无参数时,如果已安装control-c处理程序,则此函数将删除它。该功能还可以用作测试装饰器,以在执行测试时暂时移除处理程序:

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