– 单元测试框架 – 开发工具(Python教程)(参考资料)
unittest– 单元测试框架
源代码: Lib / unittest / __ init__.py
(如果您已经熟悉测试的基本概念,可能需要跳到断言方法列表.)
unittest单元测试框架最初受JUnit启发,与其他语言的主要单元测试框架具有相似的风格。它支持测试自动化,共享测试的设置和关闭代码,将测试集合到集合中,以及测试与报告框架的独立性.
为了达到这个目的,unittest以面向对象的方式支持一些重要的概念:
- 测试夹具
- A test fixture表示执行一个或多个测试所需的准备工作,以及任何关联清理操作。这可能涉及,例如,创建临时或代理数据库,目录或启动服务器进程.
- 测试用例
- A test case是单独的测试单位。它检查对特定输入集的特定响应。
unittest提供基类,TestCase,可用于创建新的测试用例. - test suite
- A test suite是测试用例,测试套件或两者的集合。它用于聚合应该一起执行的测试.
- 试验跑者
- A test runner是一个组件,它协调测试的执行并向用户提供结果。跑步者可以使用图形界面,文本界面,或返回一个特殊值来表示执行测试的结果.
另见
- 模块
doctest - 另一个具有不同风味的测试支持模块
- 简单的Smalltalk测试:带图案
- Kent Beck使用模式共享来测试框架的原始论文
unittest. - Nose和pytest
- 第三方单元测试框架,具有较轻的写法测试语法。例如,
assert func(10) == 42. - Python测试工具分类法
- 包含功能测试框架和模拟对象库的Python测试工具的广泛列表.
- 在Python邮件列表中测试
- Python中用于讨论测试和测试工具的特殊兴趣小组
脚本Tools/unittestgui/unittestgui.py在Python源代码发行版中是一个用于测试发现和执行的GUI工具。这主要是为了便于那些新的单元测试使用。对于生产环境,建议测试由持续集成系统驱动,如Buildbot,Jenkinsor Hudson。
基本示例
unittest模块提供了一组丰富的工具来构建和运行测试。本节演示了一小部分工具可以满足大多数用户的需求.
这是一个测试三个字符串方法的简短脚本:
import unittestclass 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.000sOK
将-v选项传递给测试脚本将指示unittest.main()启用更高级别的冗长,并产生以下输出:
test_isupper (__main__.TestStringMethods) ... oktest_split (__main__.TestStringMethods) ... oktest_upper (__main__.TestStringMethods) ... ok----------------------------------------------------------------------Ran 3 tests in 0.001sOK
上面的例子显示了最常用的unittest足以满足许多日常测试需求的功能。文档的其余部分探讨了第一原理的完整功能集.
命令 – 线程接口
可以从命令行使用unittest模块从模块,类甚至单独的测试方法运行测试:
python -m unittest test_module1 test_module2python -m unittest test_module.TestClasspython -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-
在testrun期间缓冲标准输出和标准错误流。通过测试期间的输出被丢弃。输出通常在测试失败或错误时回显并添加到故障消息中.
-c,--catch-
Control-C在测试运行期间等待当前测试结束然后报告所有结果到目前为止。第二个 Control-C 引发正常
KeyboardInterrupt异常查看信号处理以获取提供此功能的功能.
-f,--failfast-
在第一个错误或失败时停止测试运行.
-k-
只运行与模式或子字符串匹配的测试方法和类。此选项可以多次使用,在这种情况下,所有测试用例都与给定模式匹配被包含在内。
包含通配符的模式(
*)使用fnmatch.fnmatchcase()匹配测试名称;否则使用简单区分大小写的子串匹配模式与测试加载器导入的完全限定的测试方法名称匹配.
例如,
-k foo匹配foo_tests.SomeTest.test_something,bar_tests.SomeTest.test_foo,但不是bar_tests.FooTest.test_something.
--locals-
显示局部变量在tracebacks.
版本3.2中的新功能:添加了命令行选项-b, -c和-f.
版本3.5:命令行选项--locals.
版本3.7中新增:命令行选项-k.
命令行也可以用于测试发现,运行项目中的所有测试或只是一个子集.
测试发现
版本3.2.
Unittest支持简单的测试发现。为了兼容testdiscovery,所有测试文件必须是 modules 或包(包括命名空间包)可以从项目的顶级目录导入(这意味着他们的文件名必须是有效的身份标识).
测试发现在TestLoader.discover(),但也可以从命令行使用。基本的命令行用法是:
cd project_directorypython -m unittest discover
discover子命令有以下选项:
-v,--verbose-
详细输出
-s,--start-directorydirectory-
目录开始发现(
.默认)
-p,--patternpattern-
模式匹配测试文件(
test*.py默认)
-t,--top-level-directorydirectory-
项目的顶级目录(默认为开始目录)
-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.
如果你有一个全局安装的包,并尝试在包的不同副本上进行测试发现,那么导入could发生在错误的地方。如果发生这种情况,测试发现会警告你并退出.
如果您将起始目录作为包名提供而不是通过apath到目录,那么发现假定它导入的任何位置是您想要的位置,因此您将无法获得警告.
测试模块和软件包可以通过load_tests协议自定义测试加载和发现.
版本3.4更改:测试发现支持命名空间包.
组织测试代码
单元测试的基本构建块是test cases – 必须设置并检查正确性的单一场景。在unittest中,测试用例用unittest.TestCase实例。要创建自己的测试用例,必须编写TestCase或使用FunctionTestCase.
的测试代码TestCase实例应完全自我包含,以便它可以单独运行或与任何其他测试用例任意组合运行.
最简单的TestCase子类将简单地实现一个测试方法(即一个名称以test开头的方法),以便执行特定的测试代码:
import unittestclass 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 unittestclass 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 unittestclass WidgetTestCase(unittest.TestCase): def setUp(self): self.widget = Widget("The widget") def tearDown(self): self.widget.dispose()
如果setUp()成功,tearDown()会测试测试方法是否成功.
测试代码的工作环境叫做test fixture。创建一个新的TestCase实例作为用于执行每个单独测试方法的唯一测试夹具。因此setUp(), tearDown()和__init__()每次测试都会被调用一次
建议您使用TestCase实现将测试分组,以根据他们测试的功能进行分组。unittest提供了一个机制:test suite,由unittest表示TestSuite类。在大多数情况下,调用unittest.main()将是正确的事情,并为您收集所有模块的测试用例并执行它们.
但是,如果您想自定义测试套件的构建,您可以做你自己:
def suite(): suite = unittest.TestSuite() suite.addTest(WidgetTestCase("test_default_widget_size")) suite.addTest(WidgetTestCase("test_widget_resize")) return suiteif __name__ == "__main__": runner = unittest.TextTestRunner() runner.run(suite())
你可以将测试用例和测试套件的定义放在与他们要测试的代码相同的模块中(例如widget.py),但是放置测试代码有很多优点在一个单独的模块中,例如test_widget.py:
重新使用旧的测试代码
有些用户会发现他们现有的测试代码需要来自unittest,而不需要转换旧的测试代码函数到TestCase子类
为此,unittest提供了一个FunctionTestCase类。这个TestCase的子类可以用来包装现有的测试功能。也可以提供设置和拆卸功能.
给出以下测试功能:
def testSomething(): something = makeSomething() assert something.name is not None # ...
可以创建如下的等效测试用例实例,可选设置和拆卸方法:
testcase = unittest.FunctionTestCase(testSomething, setUp=makeSomethingDB, tearDown=deleteSomethingDB)
在某些情况下,现有的测试可能是使用doctest模块编写的。如果是这样的话,doctest提供一个DocTestSuite可自动构建的类unittest.TestSuite来自现有的实例doctest基于测试.
跳过测试和预期的失败
版本3.1.
Unittest支持跳过单个测试方法甚至整个类测试。此外,它支持将测试标记为“预期的失败”,这是一个被破坏并将失败的测试,但不应该被视为失败的TestResult.
跳过测试只是使用skip() 装饰器或其中一个条件变体.
基本跳过看起来像这样:
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.005sOK (skipped=3)
可以像方法一样跳过类:
@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)-
无条件地跳过装饰测试。reason应该说明为什么要跳过测试.
@unittest.skipIf(condition, reason)-
如果condition是真的。
@unittest.skipUnless(condition, reason)-
跳过装饰测试,除非condition是真的。
@unittest.expectedFailure-
将测试标记为预期的失败。如果测试失败,将被认为是成功的。如果测试通过,将被视为失败.
- exception
unittest.SkipTest(reason ) -
提出这个异常是为了跳过测试.
通常你可以使用
TestCase.skipTest()或其中一个跳过装饰器而不是直接提升它.
试验不会有setUp() 要么 tearDown()在他们周围跑来跑去。被骗的班级不会有setUpClass()要么 tearDownClass()run.Skipped模块没有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.
API的测试用例
- class
unittest.TestCase(methodName=”runTest”) -
TestCase类的实例代表了逻辑测试在unittest宇宙。此类旨在用作基类,具体测试由具体子类实现。该类实现了测试运行器所需的接口,以允许它驱动测试,以及测试代码可用于检查和报告各种故障的方法.每个
TestCase将运行一个基本方法:methodnamed methodName。在TestCase,你不会改变methodName也没有重新实现默认runTest()方法。版本3.2:
TestCase中的更改可以成功实例化而不提供methodName。这样可以更容易地从交互式解释器中试验TestCase.TestCase实例提供了三组方法:一组用于运行测试,另一组用于测试实现以检查条件和报告失败,一些查询方法允许收集有关测试本身的信息.第一组中的方法(运行测试)是:
setUp()-
调用准备测试夹具的方法。在调用测试方法之前立即调用它;除了
AssertionError或SkipTest之外,此方法引发的任何异常都将被视为错误而非测试失败。默认实现什么都不做.
tearDown()-
方法在调用测试方法后立即调用并记录结果。即使测试方法引发了异常,也会调用此方法,因此子类中的实现可能需要特别注意检查内部状态。除此之外的任何异常,除了
AssertionError或SkipTest之外,都会被认为是一个额外的错误而不是测试失败(从而增加了报告的错误总数)。只有在setUp()成功时才会调用此方法,无论测试方法的结果如何。默认实现无效.
setUpClass( )-
运行在单个类中的测试之前调用的类方法.
setUpClass以类作为唯一参数调用,并且必须装饰为classmethod():@classmethoddef setUpClass(cls): ...
有关详细信息,请参阅类和模块夹具.
版本3.2.
tearDownClass()-
在单个类中测试后调用的类方法已经运行了
tearDownClass被调用,类是唯一的参数,必须装饰为classmethod():@classmethoddef tearDownClass(cls): ...
有关详细信息,请参阅类和模块夹具.
新版本3.2.
run(result=None)-
运行测试,将结果收集到
TestResultobjectpassed为result。如果省略result或None,则创建一个临时结果对象(通过调用defaultTestResult()方法)并使用。结果对象返回run()‘scaller.只需调用
TestCaseinstance.在版本3.3中更改即可获得相同的效果:以前版本的
run没有返回结果。没有打过一个实例.
skipTest(reason)-
在测试方法中调用它或
setUp()跳过当前测试。见跳过测试和预期的失败以获取更多信息.新版本3.1.
subTest(msg=None, **params)-
返回一个上下文管理器,它执行封闭的代码块asubtest。msg和params是可选的,任意值,只要子测试失败就会显示,允许你清楚地识别它们.
测试用例可以包含任意数量的子测试声明,并且可以任意嵌套.
参见使用子测试区分测试迭代以获取更多信息.
版本3.4.
debug()-
运行测试而不收集结果。这允许测试引发的异常传播给调用者,并可用于支持调试器下的运行测试.
TestCaseclass提供了几种断言方法来检查和报告失败。下表列出了最常用的方法(有关更多断言方法,请参阅下表):方法 检查 @中的新内容 assertEqual(a, b)a == bassertNotEqual(a, b)a != bassertTrue(x)bool(x) is TrueassertFalse(x)bool(x) is FalseassertIs(a, b)a is b3.1 assertIsNot(a, b)a is not b3.1 assertIsNone(x)x is None3.1 assertIsNotNone(x)x is not None3.1 assertIn(a, b)a in b3.1 assertNotIn(a, b)a not in b3.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)-
测试first和second是平等的。如果数值不相等,则测试失败.
此外,如果first和second是完全相同的类型和一个oflist,tuple,dict,set,frozenset或str或子类注册的任何类型
addTypeEqualityFunc()将调用特定于类型的相等函数以生成更有用的defaulterror消息(另请参阅类型特定方法列表)。更改版本3.1:添加了类型特定的相等功能的自动调用.
在版本3.2中添加:
assertMultiLineEqual()添加为比较字符串的默认类型相等功能.
assertNotEqual(first, second, msg=None)-
测试first和second不相等。如果值docompare相等,测试将失败.
assertTrue(expr, msg=None )assertFalse(expr, msg=None )-
测试expr是真(或假).
请注意,这相当于
bool(expr) is True而不是expris True(使用assertIs(expr, True)为后者)。当有更具体的方法可用时,也应该避免这种方法(例如assertEqual(a, b)而不是assertTrue(a == b)),因为它们在失败的情况下提供了更好的错误信息.
assertIs(first, second, msg=None )assertIsNot(first, second, msg=None)-
测试first和second评估(或不评估)相同的对象.
新版3.1.
assertIsNone(expr, msg=None)assertIsNotNone(expr, msg=None)-
测试expr是(或不是)
None.版本3.1.
assertIn(first, second, msg=None)assertNotIn(first, second, msg=None)-
测试first是(或不是)在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并且消息匹配正则表达式r3.1 assertWarns(warn, fun, *args, **kwds)fun(*args, **kwds)提升warn3.2 assertWarnsRegex(warn, r, fun, *args, **kwds)fun(*args, **kwds)提出warn并且消息与正则表达式匹配r3.2 assertLogs(logger, level)with阻止logger登录level3.4 assertRaises(exception, callable, *args, **kwds)assertRaises(exception, *, msg=None)-
使用也传递给callable的任何位置或关键字参数调用
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.exceptionself.assertEqual(the_exception.error_code, 3)
在3.1版中更改:添加了使用
assertRaises()作为上下文管理器的功能.版本3.2更改:添加了
exception属性更改版本3.3:添加了msg keyword参数用作上下文管理器时
assertRaisesRegex(exception, regex, callable, *args, **kwds)assertRaisesRegex(exception, regex, *, msg=None )-
喜欢
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(warning, *, msg=None)-
使用也传递给callable的任何位置或关键字参数调用
assertWarns()时,测试是否触发警告。如果warning如果不是,则触发并失败。任何异常都是错误。为了捕获任何一组警告,包含警告类的元组可以传递为warnings.如果只有warning和可能的msg给出了参数,返回一个上下文管理器,以便测试中的代码可以写成内联而不是函数:
with self.assertWarns(SomeWarning): do_something()
当用作上下文管理器时,
assertWarns()接受附加的关键字参数msg.上下文管理器会将捕获的警告对象存储在其
warning属性,以及触发filename和lineno如果打算执行额外的checkson警告捕获,这可能很有用: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()还试验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或其中一个子节点上,至少给出了level.
如果给出,logger应该是
logging.Logger对象或str给出记录器的名称。默认是rootlogger,它将捕获所有消息.如果给定,level应该是数字日志级别或等效字符串(例如
"ERROR"要么logging.ERROR)。默认是logging.INFO.如果
with块匹配logger和level条件,否则失败.上下文管理器返回的对象是一个记录助手,它记录匹配的日志消息。它有两个属性:
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) == 0assertNotAlmostEqual(a, b)round(a-b, 7) != 0assertGreater(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)not 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)-
通过计算差值来测试first和second大约(或不大约)相等,舍入到给定的十进制数places(默认为7),并与零比较。请注意,这些方法将值舍入为decimal places的给定数量(即
round()函数),而不是significant digits.如果delta提供而不是places那么first和second必须小于或等于(或大于)delta.
供应delta和places提起
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)-
测试first分别是&gt ;,&gt; =,&lt;或&lt; = than second取决于方法名称。如果没有,测试将失败:
>>> 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搜索匹配(或不匹配)text。如果失败,错误信息将包括模式和text(或者模式和意外匹配的text部分)。regex可能是一个正则表达式对象或一个包含一个适用于
re.search().的regularrexpression的字符串。版本3.1中的新增内容:名称
assertRegexpMatches.更改版本3.2:方法
assertRegexpMatches()已重命名为assertRegex().版本3.2中新增:
assertNotRegex().版本3.5中新增:name
assertNotRegexpMatches是一个弃用的别名assertNotRegex().
assertCountEqual(first, second, msg=None)-
测试序列first包含与second相同的元素,无论它们的顺序如何。如果没有,将生成列出序列之间差异的错误消息.
比较not和first时,忽略了重复的元素second。它验证每个元素在两个序列中是否具有相同的计数。相当于:
assertEqual(Counter(list(first)), Counter(list(second)))但也适用于不可用对象的序列.新版本3.2.
assertEqual()方法调度对象的等式检查相同类型的不同类型的特定方法。这些方法已经针对大多数内置类型实现,但也可以使用addTypeEqualityFunc():addTypeEqualityFunc(typeobj, function)-
注册新方法由
assertEqual()调用的特定于类型的方法来检查两个完全相同的对象typeobj(不是子类)compareequal。function必须采用两个位置参数和第三个msg = Nonekeyword参数,就像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)tatsles 3.1 assertSetEqual(a, b)sets or frozensets 3.1 assertDictEqual(a, b)dicts 3.1 assertMultiLineEqual(first, second, msg=None)-
测试多行字符串first是否等于字符串second。当不等于两个字符串的差异时,突出显示差异将包含在错误消息中。默认情况下使用此方法时,将字符串与
assertEqual().比较新版本3.1.
assertSequenceEqual(first, second, msg=None, seq_type=None)-
测试两个序列是否相等。如果提供了seq_type,first和second都必须是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)-
测试两组是否相等。如果没有,则构造一个错误消息,列出这些集之间的差异。比较set或frozensets与
assertEqual().时,如果first或second中的任何一个没有
set.difference()方法,则默认使用此方法.版本3.1.
assertDictEqual(first, second, msg=None)-
测试两个词典是否相等。如果不是,则构造一条错误消息,显示字典中的差异。默认情况下,此方法将用于比较字典和
assertEqual().版本3.1.
中的新内容最后
TestCase提供了以下方法和属性:fail(msg=None)-
表示测试失败无条件地,带有msg或
None的错误信息.
failureException-
此类属性提供测试方法引发的异常。如果atest框架需要使用专门的异常,可能需要携带附加信息,它必须将此异常子类化,以便与框架“playfair”。该属性的初始值是
AssertionError.
longMessage-
此类属性确定将自定义失败消息作为msg参数传递给失败的assertXYY调用时发生的情况.
True是默认值。在这种情况下,自定义消息被附加到标准失败消息的末尾。当设置为False时,自定义消息将替换标准消息.通过在调用assert方法之前将实例属性self.longMessage赋值给
True或False,可以在各个测试方法中覆盖类设置.在每次测试呼叫之前,类设置被重置.
版本3.1.
maxDiff-
此属性控制assertmethods输出的diffs的最大长度,这些方法报告失败时的差异。它默认为80 * 8个字符。受此属性影响的断言方法是
assertSequenceEqual()(包括委托给它的所有序列比较方法),assertDictEqual()和assertMultiLineEqual().设置
maxDiff到None意味着没有最大长度的数据版本3.2.
测试框架可以使用以下方法收集测试信息:
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(),oraftersetUp()如果setUp()提出异常.负责调用
addCleanup()添加的所有清理功能。如果需要清理函数prior到tearDown()那么你可以调用doCleanups()yourselfdoCleanups()一次一个地从一堆清理功能中弹出方法,所以可以随时调用它.新版3.1.
- class
unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None) -
这个类实现
TestCase接口whichallow测试运行器来驱动测试,但不提供测试代码可用于检查和报告错误的方法。这用于创建使用遗留测试代码的测试用例,允许它集成到基于unittest的测试框架中.
删除别名
由于历史原因,有些TestCase方法有一个或多个现已弃用的。下表列出了正确的名称及其弃用的别名:
方法名称 不推荐的别名 不推荐的别名 assertEqual()failUnlessEqual assertEquals assertNotEqual()failIfEqual assertNotEquals assertTrue()failUnless 断言_ assertFalse()failIf assertRaises()failUnlessRaises assertAlmostEqual()failUnlessAlmostEqual assertAlmostEquals assertNotAlmostEqual()failIfAlmostEqual assertNotAlmostEquals assertRegex()assertRegexpMatches assertNotRegex()assertNotRegexpMatches assertRaisesRegex()assertRaisesRegexp 自版本后不推荐使用3.1:第二栏中列出的失败*别名.
自版本3.2:第三栏中列出的断言*别名.
自版本3.2:
assertRegexpMatches和assertRaisesRegexp已重命名为assertRegex()和assertRaisesRegex().自版本3.5以来不推荐使用:
assertNotRegexpMatches名称有利于assertNotRegex().
分组测试
- class
unittest.TestSuite(tests=()) -
此类表示各个测试用例和测试套件的集合。该类提供了测试运行器所需的接口,以允许它在任何其他测试用例中运行。运行
TestSuite实例与套件相同,单独运行每个测试.如果给出tests,它必须是可迭代的单个测试用例或其他套件最初将用于构建套件。提供了其他方法,以便稍后将测试用例和套件添加到集合中.
TestSuite对象的行为与TestCase对象非常相似,除非它们实际上没有实现测试。相反,它们用于将测试聚合成应该一起运行的测试组。一些额外的方法可用于添加测试TestSuite实例的部分:addTest(test)-
在套房里加一个
TestCase或TestSuite.
addTests(tests)-
将
TestCase和TestSuite实例的迭代中的所有测试添加到这个测试套件中.这相当于迭代tests,调用
addTest()foreach element.
TestSuite与TestCase:run(result)-
运行与此套件关联的测试,将结果收集到作为result传递的测试结果对象中。请注意,与
TestCase.run(),TestSuite.run()不同,要求将结果对象传入.
debug()-
运行与此套件关联的测试而不收集结果。这允许测试引发的异常传播到调用者,并可用于支持在调试器下运行测试.
countTestCases()-
返回此测试对象所代表的测试次数,包括所有个人测试和子测试.
__iter__()-
测试分组按
TestSuite总是通过迭代访问。子类可以通过覆盖__iter__()。注意,在单个套件上可以多次调用此方法(例如,在计算测试或比较相等性时),因此在TestSuite.run()必须与每次调用迭代相同。在TestSuite.run()之后,调用者不应该依赖此方法返回的测试,除非调用者使用覆盖TestSuite._removeTestAtIndex()的asubclass来保存测试引用.在版本3.2中更改:在早期版本中
TestSuite直接通过迭代访问测试,所以重写__iter__()不足以提供测试.版本3.4更改:在早期版本中
TestSuite每个人都提到了TestCase之后TestSuite.run()。子类可以通过覆盖TestSuite._removeTestAtIndex().
在
TestSuite对象,run()方法是由TestRunner而不是最终用户测试工具调用的.
加载和运行测试
- class
unittest.TestLoader -
TestLoaderclass用于从类和模块创建测试套件。通常,不需要创建此类的实例;unittest模块提供了一个可以共享的实例unittest.defaultTestLoader。但是,使用子类或实例可以自定义一些可配置的属性.TestLoader对象具有以下属性:errors-
加载测试时遇到的非致命错误列表。在任何时候都不会被加载器重置。相关方法通过向调用者引发异常来发出致命错误信号。合成测试也表明非致命错误会在运行时引起原始错误.
版本3.5中的新功能
TestLoader对象有以下方法:loadTestsFromTestCase(testCaseClass)-
返回包含在
TestCase衍生testCaseClass.为
getTestCaseNames()命名的每个方法创建一个测试用例实例。默认情况下,这些是使用test开始的方法名称。如果getTestCaseNames()返回nomethods,但是runTest()方法实现后,为该方法创建一个单独的测试用例.
loadTestsFromModule(module, pattern=None)-
返回给定模块中包含的所有测试用例的套件。这个方法在module中搜索从
TestCase派生的类,并为每个为类定义的测试方法创建一个类的实例.注意
使用层次结构
TestCase– 派生类可以很方便地共享fixture和helper函数,在基类上定义不打算直接实例化的testmethods并不适合这种方法。但是,当灯具不同并在子类中定义时,这样做会很有用.如果一个模块提供了一个
load_tests函数,它将被称为toload测试。这允许模块自定义测试加载。这是load_tests协议。pattern参数作为第三个参数传递给load_tests.在版本3.2中更改:支持
load_tests添加更改版本3.5:无证的非官方的use_load_tests默认参数isdeprecated并被忽略,尽管它仍然被接受用于向后兼容性。该方法现在也接受一个只有关键字的参数pattern,它作为第三个参数传递给
load_tests.
loadTestsFromName(name, module=None)-
返回一个给出字符串说明符的所有测试用例的套件
说明符name是一个“点名”,可以解析为模块,测试用例类,测试方法测试用例类,
TestSuite实例,或者是一个返回TestCase或TestSuite实例的可调用对象。这些检查按照此处列出的顺序进行;也就是说,可能的测试用例类的方法将被选为“测试用例类中的测试方法”,而不是“可调用对象”.例如,如果你有一个模块
SampleTests包含一个TestCase– 派生类SampleTestCase有三个testmethods(test_one(),test_two()和test_three()),thepecpecifier"SampleTests.SampleTestCase"会导致这个方法可以返回一个运行所有三种测试方法的套件。使用说明符"SampleTests.SampleTestCase.test_two"会导致它返回一个只运行test_two()测试方法的测试套件。说明符可以指未导入的模块和包;它们将作为副作用进口.该方法可选择解决name相对于给定的module.
在版本3.5中更改:如果
ImportError要么AttributeError遍历时发生name那么一个合成测试会在运行时引发错误。这些错误包含在self.errors.
loadTestsFromNames(names, module=None)-
累积的错误中。与
loadTestsFromName(),但需要一系列名称而不是单个名称。返回值是一个测试套件,支持为每个名称定义的所有测试.
getTestCaseNames(testCaseClass)-
返回testCaseClass中找到的方法名称的排序序列;这应该是
TestCase.
discover(start_dir, pattern=”test*.py”, top_level_dir=None)-
通过从指定的开始目录中递归到子目录中查找所有测试模块,并返回包含它们的TestSuite对象。只测试与pattern将被加载。(使用shell样式匹配。)只能加载可导入的模块名称(即validPython标识符).
所有测试模块必须可从项目的顶层导入。如果起始目录不是顶级目录,则必须单独指定顶级目录.
如果导入模块失败,例如由于语法错误,则会将其记录为单个错误,并且将继续发现。如果导入失败是由于
SkipTest被引发时,它将被记录为跳过而不是错误.如果找到包(包含名为
__init__.py的文件的目录),将检查包的是否load_tests功能。如果存在,那么它将被称为package.load_tests(loader, tests, pattern)。测试发现需要注意确保一个包只在aninvocation期间检查一次测试,即使load_tests函数本身调用loader.discover.如果
load_tests存在,那么发现会not递入包装,load_tests负责加载包装中的所有测试.故意不将模式存储为加载器属性,以便包可以继续自己发现。top_level_dir存储所以
load_tests不需要将这个参数传递给loader.discover().start_dir可以是虚线模块名称和目录.
新版本3.2.
更改版本3.4:模块提升
SkipTest导入时记录为跳过,而不是错误。发现适用于命名空间包.Paths在导入之前进行排序,这样即使底层文件系统的排序不依赖于文件名,执行顺序也是一样的.在版本3.5中改变:找到的包现在检查
load_tests,不管它们的路径是否匹配pattern,因为包名不能与默认模式匹配.
//的以下属性
TestLoader可以通过实例上的子类或赋值来配置:testMethodPrefix-
给出方法名称前缀的字符串,它将被解释为testmethods。默认值为
"test".这会影响
getTestCaseNames()以及loadTestsFrom*()methods.
sortTestMethodsUsing-
在
getTestCaseNames()和loadTestsFrom*()方法中对它们进行排序时用于比较方法名称的功能
suiteClass-
可调用对象,从测试列表构造测试套件。需要在结果对象上的Nomethods。默认值是
TestSuite类。这影响了所有
loadTestsFrom*()方法。
testNamePatterns-
测试方法必须匹配的Unix shell样式通配符测试名称模式列表,以包含在测试套件中(参见
-v选项).如果此属性不是
None(默认值),要包含在测试套件中的所有测试方法必须与此列表中的一个模式匹配。请注意,匹配始终使用fnmatch.fnmatchcase()执行,因此不同于传递给-v选项,简单子串模式必须使用*通配符转换这会影响所有
loadTestsFrom*()方法.新版本3.7.
- class
unittest.TestResult -
该类用于编译有关哪些测试成功以及哪些测试失败的信息.
A
TestResultobject存储一组测试的结果。TestCase和TestSuite课程确保正确记录结果;测试作者不需要担心记录测试的结果.建立在
unittest之上的测试框架可能需要访问TestResult通过为报告目的运行一组测试而生成的对象;为此目的,TestResult方法返回TestRunner.run()实例.TestResult在检查运行一组测试的结果时,实例具有以下属性:errors-
包含2元组
TestCase实例和stringsholding格式化回溯。每个元组代表一个测试,它引起了一个异常的异常.
failures-
一个包含2元组
TestCase实例和stringsholding格式化回溯。每个元组代表一个测试,其中使用TestCase.assert*()方法显着地发出故障信息
skipped-
包含2元组
TestCase实例和字符串保留跳过测试的原因.新版本3.1.
expectedFailures-
包含2元组
TestCase实例和stringsholding格式化回溯。每个元组代表测试用例的预期失败.
unexpectedSuccesses-
包含
TestCase被标记为预期失败但是成功的实例
shouldStop-
设置为
True当执行测试时应该停止stop().
testsRun-
到目前为止测试的总数.
buffer-
如果设置为true,
sys.stdout和sys.stderr将被缓冲在startTest()和stopTest()被调用之间。收集的输出只会回显到真实的sys.stdout和sys.stderr如果测试失败或错误。任何输出也附加到故障/错误消息.新版本3.2.
failfast-
如果设置为真
stop()将在第一次失败或错误时调用,停止测试运行.新版本3.2.
tb_locals-
如果设置为true,则局部变量将显示在tracebacks.
3.5版本中的新功能
wasSuccessful// ()-
返回
True如果到目前为止所有测试都已通过,否则返回False.版本3.4更改:返回
False如果有unexpectedSuccesses来自用expectedFailure()decorator.
stop()-
可以通过将
shouldStop属性设置为True.TestRunner对象应该尊重这个标志,并且在没有任何额外的测试的情况下返回.例如,这个功能被
TextTestRunner当用户通过键盘发出中断信号时停止测试框架的类。提供TestRunner实现的交互式工具可以以类似的方式使用它.
以下方法
TestResultclass用于维护内部数据结构,可以在子类中扩展以支持其他报告要求。这对于在运行测试时支持交互式报告的构建工具特别有用.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被忽略时调用。reason是测试跳过的原因.
默认实现附加一个元组
(test, reason)到实例的skipped属性。
addExpectedFailure(test, err)-
在测试用例时调用test失败,但标有
expectedFailure()decorator.默认实现附加一个元组
(test, formatted_err)到实例的expectedFailures属性,formatted_err是一个源自err.
addUnexpectedSuccess(test)-
在测试用例时调用test用
expectedFailure()装饰器标记,但是成功了默认实现将测试附加到实例的
unexpectedSuccesses属性
addSubTest(test, subtest, outcome/)-
当子测试结束时调用。test是与测试方法相对应的测试用例。subtest是一个定制的
TestCase实例描述子测试如果outcome是
None,分测试成功了。否则,它失败了,其中outcome是由sys.exc_info():(type, value, traceback).当结果为asccess时,默认实现不执行任何操作,并将子测试失败记录为正常故障.
版本3.4.
- class
unittest.TextTestResult(stream, descriptions, verbosity) -
的具体实现
TestResult用于TextTestRunner.版本3.2中的新功能:此课程以前被命名为
_TextTestResult。旧名stillexists作为别名,但已被弃用.
unittest.defaultTestLoader-
的实例
TestLoader要分享的课程。如果需要对TestLoader进行nocustomization,可以使用这个实例而不是重复创建新实例.
- class
unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None, *, tb_locals=False ) -
将结果输出到流的基本测试运行器实现。如果stream是
None,则默认为sys.stderr用作输出流。这个类有一些可配置的参数,但基本上非常简单。运行测试套件的图形应用程序应该提供替代实现。这样的实现应该接受**kwargs作为在将功能添加到unittest时构建runners的接口改变默认这个运行器显示
DeprecationWarning,PendingDeprecationWarning,ResourceWarning和ImportWarning即使它们是默认被忽略。由引起的弃用警告弃用了unittestmethods 也是特殊的,当警告过滤器是"default"或"always"时,它们只出现一次模块,以避免过多的警告信息。可以使用Python的-Wd或-Wa选项覆盖此行为(请参阅警告控制)并将warnings留给None.在版本3.2中更改:添加了
warnings参数在版本3.2中更改:默认流设置为
sys.stderr在实例化时间大于导入时间更改版本3.5:添加了tb_locals参数.
_makeResult()-
这个方法返回
TestResult使用的run()的实例。它不是要直接调用,而是可以重写的子类来提供自定义TestResult._makeResult()实例化类或者callable在TextTestRunner构造函数中作为resultclass参数传递。如果没有提供TextTestResult,则默认为resultclass。结果类用以下参数实例化:stream, descriptions, verbosity
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)-
从module并运行它们;这主要是为了使测试模块可以方便地执行。此函数的最简单用途是在测试脚本的末尾包含以下行:
if __name__ == "__main__": unittest.main()
你可以通过传递verbosityargument来运行带有更详细信息的测试:
if __name__ == "__main__": unittest.main(verbosity=2)
defaultTest如果没有通过argv指定测试名称,则参数可以是单个测试的名称,也可以是要运行的测试名称的无法使用的参数。如果没有指定或
None并且没有通过argv,在module中找到的所有测试都运行了argv参数可以是传递给程序的选项列表,其中第一个元素是程序名称。如果没有指定或
None,sys.argv使用了testRunner参数可以是测试运行器类,也可以是已创建的实例。默认情况下
main调用sys.exit()用退出代码表示测试成功或失败.testLoader参数必须是
TestLoaderinstance,默认为defaultTestLoader.main支持通过传入参数exit=False从交互式解释器中使用。这将在标准输出上显示结果而不调用sys.exit():>>> from unittest import main>>> main(module="test_module", exit=False)
failfast, catchbreak和buffer参数与同名命令行选项具有相同的效果.
warnings参数指定运行测试时应该使用的警告过滤器。如果没有指定,它将保持
None如果-W选项被传递给 python (参见警告控制),否则将设置为"default".调用
main实际上返回TestProgram类的实例。这样可以将测试结果存储为result属性更改版本3.1: exit参数已添加.
在版本3.2中更改:添加了verbosity, failfast, catchbreak, buffer和warnings参数
在版本3.4中更改: defaultTest参数被更改为也接受一个可迭代的测试名称.
load_tests协议
版本3.2.
模块或包可以通过实现一个名为load_tests.
如果测试模块定义load_tests它会被TestLoader.loadTestsFromModule()使用以下参数:
load_tests(loader, standard_tests, pattern)
其中pattern直接从loadTestsFromModule传递。它默认为None.
它应该返回TestSuite.
loader是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中更改:发现不再检查包名称是否匹配pattern由于包名称与默认模式匹配的不可能性
类和模块夹具
类和模块级夹具在TestSuite。当测试套件遇到来自新类的测试时tearDownClass()从上一个类(如果有的话)调用,然后从新类调用setUpClass()。
同样,如果测试来自与之前测试不同的模块,那么tearDownModule从上一个模块运行,然后setUpModule来自新模块
经过所有测试后,最终tearDownClass和tearDownModule跑了
请注意,共享装置不能很好地利用testparallelization等[潜在]功能,并且会破坏测试隔离。它们应该小心使用.
unittest测试加载器创建的测试的默认顺序是将来自相同模块和类的测试分组在一起。这将导致setUpClass / setUpModule(等)每个类和模块只调用一次。如果您将订单随机化,以便来自不同模块和类的测试彼此相邻,那么这些共享夹具功能可能会在单次测试运行中多次出现.
共享装置不适用于具有非标准订购的套件。对于不希望支持共享夹具的框架,仍然存在BaseTestSuite
如果在其中一个共享夹具功能期间引发任何异常,则将测试报告为错误。因为没有相应的测试实例,所以创建了_ErrorHolder对象(具有与TestCase相同的接口)来表示错误。如果你只是使用标准的unittest测试运行器,那么这个细节并不重要,但是如果你是一个框架作者它可能是相关的
setUpClass和tearDownClass
这些必须作为类方法实现:
import unittestclass 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异常然后该类将被报告为已跳过而不是作为错误
setUpModule和tearDownModule
这些应该实现为函数:
def setUpModule(): createConnection()def tearDownModule(): closeConnection()
如果引发异常a setUpModule然后将运行模块中的所有测试,并且tearDownModule将不会运行。如果异常是SkipTest异常,那么模块将被报告为已跳过而不是错误.
信号处理
版本3.2中的新功能.
单元测试的-c/--catch命令行选项,以及catchbreak参数unittest.main(),在测试运行期间提供对控制-C的更友好的处理。启用catch breakbehavior后,control-C将允许当前正在运行的测试完成,然后测试运行将结束并报告所有结果。一个secondcontrol-c将以通常的方式引发KeyboardInterrupt
control-c处理信号处理程序试图保持与安装自己的signal.SIGINT处理程序的代码orte兼容。如果unittest处理程序被调用但是isn’t已安装的signal.SIGINT处理程序,即。它已被被测系统替换并委托给它,然后它调用默认处理程序。这通常是代码替换已安装的处理程序并委托给它的预期行为。对于需要unittest control-c处理禁用的个别测试,可以使用removeHandler()装饰器.
框架作者有一些实用功能可以在测试中启用控制功能frameworks.
unittest.installHandler()-
安装control-c处理程序。当收到
signal.SIGINT时(通常是响应用户按下control-c)所有注册的结果都有stop()被叫
unittest.registerResult// (result)-
注册
TestResult对象以进行control-c处理。注册aresult商店是一个弱的参考,所以它不会阻止收集垃圾的结果.注册
TestResult如果没有启用control-chandling,对象没有副作用,因此测试框架可以无条件地注册它们创建的结果,无论是否启用处理.
unittest.removeResult(result )-
删除已注册的结果。一旦结果被删除,那么
stop()将不再被调用该结果对象响应一个control-c.
unittest.removeHandler(function=None)-
在没有参数的情况下调用此函数会删除已安装的control-c处理程序。此函数也可以用作测试decoratorto在执行测试时临时删除处理程序:
@unittest.removeHandlerdef test_signal_handling(self): ...