26.4. unittest
— 单元测试框架¶
源代码: Lib / unittest / __ init __。py
(如果您已经熟悉测试的基本概念,你可能想要跳到 assert 方法列表。)
unittest
单元测试框架最初灵感来自 JUnit,和其他语言的主要单元测试框架有相似的风格。它支持测试自动化,共享的设置和关闭代码测试,测试聚集成集合,以及从报告框架上进行独立测试。
要实现这一目标,unittest
在面向对象方法上支持一些重要的概念︰
- 测试夹具
- 测试夹具表示执行一个或多个测试以及任何关联的清除操作所需的准备工作。这可能涉及例如创建临时或代理数据库,目录或启动服务器进程。
- 测试用例
- 测试用例是测试的单独单元。它检查对特定输入集合的特定响应。
unittest
提供了一个基类,TestCase
,可用于创建新的测试用例。 - 测试套件
- 测试套件是测试用例,测试套件或两者的容器。它用于聚合应该一起执行的测试。
- 测试跑步者
- 测试运行器是协调测试执行并向用户提供结果的组件。运行器可以使用图形界面,文本界面,或返回特定值来指示执行测试的结果。
也可以看看
- 模块
doctest
- 另一个具有非常不同风味的测试支持模块。
- 简单Smalltalk测试:使用模式
- Kent Beck关于使用由
unittest
共享的模式的测试框架的原始文章。 - Nose和py.test
- 第三方单元测试框架具有用于书写测试的更轻量级语法。例如,
断言 func(10) == 42
。 - Python测试工具分类
- 广泛的Python测试工具列表,包括功能测试框架和模拟对象库。
- 在Python邮件列表中测试
- 在Python中讨论测试和测试工具的特殊兴趣小组。
Python源代码分发中的脚本Tools/unittestgui/unittestgui.py
是用于测试发现和执行的GUI工具。这主要是为了易于使用那些新的单元测试。对于生产环境,建议由连续集成系统(例如Buildbot,Jenkins或Hudson)来驱动测试。
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支持简单的测试发现。为了与测试发现兼容,所有测试文件必须是从顶层可导入的modules或packages(包括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
提供了一种机制:测试套件,由unittest
的TestSuite
类表示。在大多数情况下,调用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()
方法。TestCase
实例提供三组方法:一组用于运行测试,另一组用于测试实现以检查条件和报告故障,以及一些查询方法,允许收集关于测试本身的信息。第一组中的方法(运行测试)是:
-
setUp
()¶ 方法称为准备测试夹具。这在调用测试方法之前立即调用;除了
AssertionError
或SkipTest
之外,此方法引发的任何异常都将被视为错误,而不是测试失败。默认实现什么也不做。
-
tearDown
()¶ 方法调用后立即调用测试方法并记录结果。这被称为即使测试方法引发了一个异常,因此在子类中的实现可能需要特别小心检查内部状态。由此方法引发的任何异常,除了
AssertionError
或SkipTest
之外的任何异常都将被视为附加错误,而不是测试失败(因此增加报告的错误总数)。仅当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)¶ 返回一个执行封闭代码块作为子测试的上下文管理器。msg和params是可选的,任何值,当子测试失败时显示,允许您清楚地标识它们。
测试用例可以包含任意数量的子测试声明,它们可以任意嵌套。
有关详细信息,请参见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 是 b
3.1 assertIsNot(a, b)
a 是 不是 b
3.1 assertIsNone(x)
x 是 无
3.1 assertIsNotNone(x)
x 是 不是 无
3.1 assertIn(a, b)
a 在 b
3.1 assertNotIn(a, b)
a 不是 在 b
3.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 toassertRaises()
,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 toexpr is True
(useassertIs(expr, True)
for the latter). 当更具体的方法可用时,也应该避免这种方法。assertEqual(a, b)
而不是assertTrue(a == t5 > b)
),因为它们在出现故障时提供更好的错误消息。
-
assertIs
(first, second, msg=None)¶ -
assertIsNot
(first, second, msg=None)¶ 测试第一和第二计算(或不计算)到同一个对象。
版本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)
引发excassertRaisesRegex(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
( 异常,regex,msg = 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
属性中,以及触发filename
和lineno
属性中警告的源行。如果意图是对捕获的警告执行额外检查,这可能是有用的: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
( 警告,regex,msg =无 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
对象的列表。
例:
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)
不是 r.search(s)
3.2 assertCountEqual(a, b)
a和b在相同的数字中具有相同的元素,无论它们的顺序如何 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)
集或frozensets 3.1 assertDictEqual(a, b)
dicts 3.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)¶ 对于错误消息,无条件地以msg或
None
发送测试失败。
-
failureException
¶ 这个类属性给出了测试方法引发的异常。如果一个测试框架需要使用一个专门的异常,可能携带附加信息,它必须子类化这个异常,以便与框架“公平”。此属性的初始值为
AssertionError
。
-
longMessage
¶ 如果设置为
True
,则您传递到assert methods的任何显式失败消息将附加到正常失败消息的结尾。正常消息包含有关所涉及对象的有用信息,例如来自assertEqual的消息显示两个不等对象的repr。将此属性设置为True
允许您除了常规错误消息之外还有自定义错误消息。此属性默认为
True
。如果设置为False,则传递给assert方法的自定义消息将使正常消息静音。通过在调用assert方法之前将实例属性分配给
True
或False
,可以在单个测试中覆盖类设置。版本3.1中的新功能。
-
maxDiff
¶ 此属性控制由失败时报告差异的assert方法输出的diffs的最大长度。默认值为80 * 8个字符。受此属性影响的断言方法为
assertSequenceEqual()
(包括委派给它的所有序列比较方法),assertDictEqual()
和assertMultiLineEqual()
将
maxDiff
设置为None意味着diff的最大长度没有。版本3.2中的新功能。
测试框架可以使用以下方法来收集关于测试的信息:
-
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
andassertRaisesRegexp
have been renamed toassertRegex()
andassertRaisesRegex()
26.4.8.2. Grouping tests¶
- class
unittest.
TestSuite
(tests=())¶ 此类表示单个测试用例和测试套件的聚合。该类提供了测试运行器所需的接口,以允许它作为任何其他测试用例运行。运行
TestSuite
实例与在套件上进行迭代相同,单独运行每个测试。如果给出tests,它必须是单独的测试用例或其他测试套件的迭代,用于最初构建套件。提供了附加的方法以将测试用例和套件添加到容器中。
TestSuite
对象的行为非常类似于TestCase
对象,除非它们实际上没有实现测试。相反,它们用于将测试聚合到应该一起运行的测试组中。一些其他方法可用于向TestSuite
实例添加测试:-
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 eachTestCase
afterTestSuite.run()
. 子类可以通过覆盖TestSuite._removeTestAtIndex()
来恢复该行为。
-
26.4.8.3. Loading and running tests¶
- class
unittest.
TestLoader
¶ TestLoader
类用于从类和模块创建测试套件。通常,没有必要创建这个类的实例;unittest
模块提供了一个实例,可以作为unittest.defaultTestLoader
共享。然而,使用子类或实例,允许定制一些可配置属性。TestLoader
对象具有以下属性:-
errors
¶ 加载测试时遇到的非致命错误的列表。不由装载器在任何点复位。致命错误由相关的调用者引发异常的方法发出信号。非致命错误也由合成测试指示,其将在运行时引发原始错误。
版本3.5中的新功能。
TestLoader
对象有以下方法:-
loadTestsFromTestCase
(testCaseClass)¶ 返回一组包含在
TestCase
-derivedtestCaseClass
中的所有测试用例。为由
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
实例的“点名”一个可返回TestCase
或TestSuite
实例的可调用对象。这些检查按照此处列出的顺序应用;也就是说,可能的测试用例类上的方法将被选取为“测试用例类中的测试方法”,而不是“可调用对象”。For example, if you have a module
SampleTests
containing aTestCase
-derived classSampleTestCase
with three test methods (test_one()
,test_two()
, andtest_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中已更改:如果在遍历名称时发生
ImportError
或AttributeError
,那么将引发该错误当运行时会返回。这些错误包含在由self.errors累积的错误中。-
loadTestsFromNames
(names, module=None)¶ 类似于
loadTestsFromName()
,但是接受一系列名称而不是单个名称。返回值是一个测试套件,它支持为每个名称定义的所有测试。
-
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*()
方法中对方法名称进行排序时用于比较方法名称的函数。
-
- class
unittest.
TestResult
¶ 此类用于编译有关哪些测试已成功以及哪些测试失败的信息。
TestResult
对象存储一组测试的结果。TestCase
和TestSuite
类确保结果被正确记录;测试作者不需要担心记录测试的结果。构建在
unittest
之上的测试框架可能需要访问通过运行一组测试来生成报告的TestResult
对象;为此,通过TestRunner.run()
方法返回TestResult
实例。TestResult
实例具有以下属性,当检查运行一组测试的结果时,这些属性将是感兴趣的:-
testsRun
¶ 到目前为止运行的测试的总数。
-
buffer
¶ If set to true,
sys.stdout
andsys.stderr
will be buffered in betweenstartTest()
andstopTest()
being called. 如果测试失败或错误,收集的输出将只会被回送到真实的sys.stdout
和sys.stderr
。任何输出也附加到故障/错误消息。版本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)¶ 当测试用例测试时调用引发意外异常。err是
sys.exc_info()
:(type, value, t6)返回的形式的元组> traceback)
。The default implementation appends a tuple
(test, formatted_err)
to the instance’serrors
attribute, where formatted_err is a formatted traceback derived from err.
-
addFailure
(test, err)¶ 当测试用例测试发生故障时调用。err是
sys.exc_info()
:(type, value, t6)返回的形式的元组> traceback)
。The default implementation appends a tuple
(test, formatted_err)
to the instance’sfailures
attribute, where formatted_err is a formatted traceback derived from err.
-
addSuccess
(test)¶ 当测试用例测试成功时调用。
默认实现什么也不做。
-
addExpectedFailure
(test, err)¶ 当测试用例测试失败时调用,但标记为
expectedFailure()
装饰器。The default implementation appends a tuple
(test, formatted_err)
to the instance’sexpectedFailures
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
andImportWarning
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的主要公共接口。此方法采用
TestSuite
或TestCase
实例。通过调用_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)
failfast,catchbreak和缓冲参数与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
。
loader是TestLoader
执行加载的实例。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
。
在所有测试运行后,运行最后的tearDownClass
和tearDownModule
。
请注意,共享夹具不能很好地与测试并行化的潜在特性一起工作,并且它们会破坏测试隔离。他们应该小心使用。
由单元测试装载器创建的测试的默认顺序是将来自相同模块和类的所有测试分组在一起。这将导致每个类和模块只调用一次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()
如果你想要基本类上的setUpClass
和tearDownClass
,那么你必须自己调用它们。TestCase
中的实现为空。
如果在setUpClass
期间引发异常,那么类中的测试不会运行,并且tearDownClass
不会运行。跳过的类不会有setUpClass
或tearDownClass
运行。如果异常是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.
registerResult
(result)¶ 为控制c处理注册
TestResult
对象。注册结果会存储一个弱引用,因此它不会阻止结果被垃圾回收。如果未启用控制c处理,则注册
TestResult
对象没有副作用,因此测试框架可以无条件地注册它们创建的所有结果,而与是否启用处理无关。
-
unittest.
removeHandler
(function=None)¶ 当调用无参数时,如果已安装control-c处理程序,则此函数将删除它。该功能还可以用作测试装饰器,以在执行测试时暂时移除处理程序:
@unittest.removeHandler def test_signal_handling(self): ...