25.5. test —用于 Python 的回归测试包

Note

test软件包仅供 Python 内部使用。它被记录为 Python 核心开发人员的利益。不建议在 Python 标准库之外使用此软件包,因为此处提到的代码可以更改,也可以在不考虑 Python 版本之间删除的情况下删除。

test软件包包含所有针对 Python 的回归测试以及test.supporttest.regrtest模块。 test.support用于增强测试,而test.regrtest用于驱动测试套件。

test软件包中名称以test_开头的每个模块都是针对特定模块或Function的测试套件。所有新测试都应使用unittestdoctest模块编写。一些较早的测试是使用“传统”测试样式编写的,该样式将打印输出与sys.stdout进行比较;这种测试风格被认为已弃用。

See also

  • Module unittest

  • 编写 PyUnit 回归测试。

  • Module doctest

  • 测试嵌入在文档字符串中。

25.5.1. 为测试包编写单元测试

使用unittest模块的测试最好遵循一些准则。一种是pass以test_开头并以被测试模块的名称结尾来命名测试模块。测试模块中的测试方法应以test_开头,并以对该方法进行测试的描述结尾。这是必需的,以便测试驱动程序将这些方法识别为测试方法。另外,不应包括该方法的文档字符串。Comments(例如# Tests function returns only True or False)应用于提供测试方法的文档。这样做是因为如果文档字符串存在则将其打印出来,因此未说明正在运行的测试。

通常使用基本样板:

import unittest
from test import support

class MyTestCase1(unittest.TestCase):

    # Only use setUp() and tearDown() if necessary

    def setUp(self):
        ... code to execute in preparation for tests ...

    def tearDown(self):
        ... code to execute to clean up after tests ...

    def test_feature_one(self):
        # Test feature one.
        ... testing code ...

    def test_feature_two(self):
        # Test feature two.
        ... testing code ...

    ... more test methods ...

class MyTestCase2(unittest.TestCase):
    ... same structure as MyTestCase1 ...

... more test classes ...

def test_main():
    support.run_unittest(MyTestCase1,
                         MyTestCase2,
                         ... list other tests ...
                         )

if __name__ == '__main__':
    test_main()

此样板代码允许测试套件由test.regrtest运行,也可以作为脚本独立运行。

回归测试的目标是try破坏代码。这导致需要遵循一些准则:

class TestFuncAcceptsSequences(unittest.TestCase):

    func = mySuperWhammyFunction

    def test_func(self):
        self.func(self.arg)

class AcceptLists(TestFuncAcceptsSequences):
    arg = [1, 2, 3]

class AcceptStrings(TestFuncAcceptsSequences):
    arg = 'abc'

class AcceptTuples(TestFuncAcceptsSequences):
    arg = (1, 2, 3)

See also

  • 测试驱动开发

  • 肯特·贝克(Kent Beck)写的一本关于在代码之前编写测试的书。

25.5.2. 使用命令行界面运行测试

借助-m选项,可以将test.regrtest模块作为脚本运行,以驱动 Python 的回归测试套件:python -m test.regrtest .单独运行脚本会自动开始运行test软件包中的所有回归测试.pass查找包中所有名称以test_开头的模块,导入它们并执行test_main()(如果存在)来完成此操作.要执行的测试的名称也可以传递给脚本.指定单个回归测试( python -m test.regrtest test_spam **)将最小化输出,并且仅打印测试pass还是失败,从而将输出最小化。

直接运行test.regrtest可以设置可用于测试的资源。您可以使用-u命令行选项来执行此操作。将all指定为-u选项的值将启用所有可能的资源: python -m test.regrtest -uall 。如果需要除一种资源以外的所有资源(更常见的情况),则可以在all之后列出用逗号分隔的不需要的资源列表。命令 python -m test.regrtest -uall,-audio,-largefile 将使用test.regrtestlargefile资源以外的所有资源运行test.regrtest。有关所有资源和更多命令行选项的列表,请运行 python -m test.regrtest -h

执行回归测试的其他一些方式取决于在哪个平台上执行测试。在 Unix 上,您可以在构建 Python 的顶级目录中运行 make test 。在 Windows 上,从您的PCBuild目录执行 rt.bat 将运行所有回归测试。

在版本 2.7.14 中更改:test软件包可以作为脚本运行: python -m test 。这与运行test.regrtest模块相同。

25.6. test.support —用于测试的 Util Function

Note

test.test_support模块已在 Python 3.x 和 2.7.14 中重命名为test.support。名称test.test_support在 2.7 中已保留为别名。

test.support模块提供对 Python 回归测试的支持。

该模块定义以下异常:

test.support模块定义以下常量:

test.support模块定义以下Function:

传递字符串作为参数也是合法的;这些应该是sys.modules中的键。每个关联的模块将被unittest.TestLoader.loadTestsFromModule()扫描。通常在下面的test_main()函数中可以看到:

def test_main():
    support.run_unittest(__name__)

这将运行命名模块中定义的所有测试。

check_warnings接受格式为("message regexp", WarningCategory)的 2Tuples 作为位置参数。如果提供了一个或多个* filters ,或者可选关键字参数 quiet False,它将检查以确保警告符合预期:每个指定的过滤器必须至少与随附代码或测试失败,并且如果引发任何与任何指定过滤器都不匹配的警告,则测试失败。要禁用这些检查中的第一个,请将 quiet *设置为True

如果未指定任何参数,则默认为:

check_warnings(("", Warning), quiet=True)

在这种情况下,将捕获所有警告,并且不会引发任何错误。

进入上下文 Management 器后,将返回一个WarningRecorder实例。 catch_warnings()的基础警告列表可pass Logger 对象的warnings属性获得。为方便起见,代表最新警告的对象的属性也可以直接pass Logger 对象访问(请参见下面的示例)。如果未提出警告,则表示警告的对象上原应具有的任何属性都将返回None

Logger 对象还具有reset()方法,该方法清除警告列表。

上下文 Management 器的设计用途如下:

with check_warnings(("assertion is always true", SyntaxWarning),
                    ("", UserWarning)):
    exec('assert(False, "Hey!")')
    warnings.warn(UserWarning("Hide me!"))

在这种情况下,如果未发出警告或发出了其他警告,则check_warnings()将引发错误。

当测试需要更深入地研究警告,而不仅仅是检查警告是否发生时,可以使用如下代码:

with check_warnings(quiet=True) as w:
    warnings.warn("foo")
    assert str(w.args[0]) == "foo"
    warnings.warn("bar")
    assert str(w.args[0]) == "bar"
    assert str(w.warnings[0].args[0]) == "foo"
    assert str(w.warnings[1].args[0]) == "bar"
    w.reset()
    assert len(w.warnings) == 0

这里将捕获所有警告,并且测试代码直接测试捕获的警告。

2.6 版的新Function。

在 2.7 版中进行了更改:新的可选参数* filters quiet *。

check_py3k_warnings(("", DeprecationWarning), quiet=False)

2.7 版的新Function。

Example use:

with captured_stdout() as s:
    print "hello"
assert s.getvalue() == "hello\n"

2.6 版的新Function。

如果* deprecated *为True,则会在导入过程中禁止使用模块和程序包弃用消息。

2.7 版的新Function。

在开始导入之前,已保存命名模块以及在* fresh blocked *参数中命名的任何模块,然后在完成新导入后重新插入sys.modules

如果* deprecated *为True,则会在导入过程中禁止使用模块和程序包弃用消息。

如果无法导入命名模块,则此函数将引发unittest.SkipTest

Example use:

# Get copies of the warnings module for testing without
# affecting the version being used by the rest of the test suite
# One copy uses the C implementation, the other is forced to use
# the pure Python fallback implementation
py_warnings = import_fresh_module('warnings', blocked=['_warnings'])
c_warnings = import_fresh_module('warnings', fresh=['_warnings'])

2.7 版的新Function。

test.support模块定义以下类别:

2.6 版的新Function。

2.6 版的新Function。

在 2.7 版中进行了更改:添加了词典界面。

2.6 版的新Function。

首页