跳转到主要内容

ZC Buildout recipe for creating test runners

项目描述

https://github.com/zopefoundation/zc.recipe.testrunner/actions/workflows/tests.yml/badge.svg https://coveralls.io/repos/github/zopefoundation/zc.recipe.testrunner/badge.svg?branch=master Current version on PyPI Supported Python versions

此配方生成用于测试一组egg的zope.testing测试运行脚本。

buildout.cfg 中的示例用法

[buildout]
parts = test

[test]
recipe = zc.recipe.testrunner
eggs = <eggs to test>

变更历史

3.1 (2024-09-27)

  • 添加对Python 3.12的支持。

  • 放弃对Python 3.7的支持。

  • 修复测试,使其能够成功运行在较新的 setuptools 版本上。

3.0 (2023-02-08)

  • 添加对Python 3.10、3.11的支持。

  • 放弃对Python 2.7、3.5、3.6的支持。

2.2 (2020-11-30)

  • 添加对Python 3.9、PyPy2和PyPy3的支持。

2.1 (2019-05-14)

  • 添加对Python 3.5至3.8a3的支持。

2.0.0 (2013-02-10)

与buildout 2兼容。

这是从1.3.0开始的,然后

  • 合并来自1.2.1(svn://svn.zope.org/repos/main/zc.recipe.testrunner/tags/1.2.1)的修复,不包括nailing zope.testing版本。这修复了一些Windows问题

1.4.0 (2010-08-27)

  • 更新为使用zc.buildout 1.5.0脚本生成。这增加了以下选项:include-site-packages、allowed-eggs-from-site-packages、extends和exec-sitecustomize。

  • 合并来自1.2.1(svn://svn.zope.org/repos/main/zc.recipe.testrunner/tags/1.2.1)的修复,不包括nailing zope.testing版本。这修复了一些Windows问题

1.3.0 (2010-06-09)

  • 更新测试,以便与所有模块的最新版本一起运行。

  • 移除了对已弃用的zope.testing.doctest的使用,因此也放弃了Python 2.3的支持。

  • 开始使用zope.testrunner而不是zope.testing.testrunner。

1.2.1 (2010-08-24)

  • 修复了大量Windows问题

  • 将版本固定为ZTK 1.0a2(唉,至少我们要有一些稳定性)

  • 修复了一些其他测试失败,这些失败似乎来自其他包

1.2.0 (2009-03-23)

  • 添加了一个相对路径选项,用于使用egg、测试和工作目录路径相对于测试脚本。

1.1.0 (2008-08-25)

  • 要求至少使用zope.testing 3.6.0。

  • 修复了一个错误:当使用工作目录参数时,层并行运行失败。

1.0.0 (2007-11-04)

  • 准备稳定发布。

1.0.0b8 (2007-07-17)

  • 添加了使用初始化选项的能力,该选项将在设置环境后插入到bin/test中。

1.0.0b7 (2007-04-26)

特性变更

  • 添加了可选的环境选项,允许在buildout.cfg中定义一个部分,用于指定在运行测试之前应设置的变量。

1.0.0b6 (2007-02-25)

特性变更

  • 如果没有指定工作目录,或指定为空字符串,将为测试创建一个空的部分目录。

1.0.0b5 (2007-01-24)

修复的漏洞

    • 使用工作目录选项时,

    • 并且测试运行器需要重启自己

    • 并且测试运行器以相对路径(例如bin/test)运行

    那么测试运行器无法成功重启,因为sys.argv[0]中的相对路径已不再有效。

    现在我们将sys.argv[0]转换为绝对路径。

1.0.0b4 (2006-10-24)

特性变更

  • 添加了一个工作目录选项,用于指定生成的脚本的运行目录。

1.0.0b3 (2006-10-16)

更新到可以与(zc.buildout 1.0.0b10)一起工作(不会收到警告)。

1.0.0b2

添加了默认选项,用于指定测试运行器默认选项。

1.0.0b1

更新到可以与zc.buildout 1.0.0b5一起工作。

1.0.0a3

添加了默认选项,允许指定测试运行器的默认选项。

1.0.0a2

现在提供了额外的路径选项,用于在测试脚本中包含额外的路径。这对于依赖未打包为egg的Python包的egg很有用。

1.0.0a1

初始公开版本

详细文档

测试运行器配方

测试运行器配方,zc.recipe.testrunner,为项目创建测试运行器。

测试运行器配方有几个选项

eggs

eggs选项指定了要测试的egg列表,作为一个或多个setuptools要求字符串。每个字符串必须在单独的一行上给出。

script

script选项给出了要生成的脚本的名称,在buildout的bin目录中。如果不使用此选项,则将使用部分名称。

extra-paths

要包含在生成的测试脚本中的一或多个额外路径。

defaults

defaults选项允许指定测试运行器的默认选项。这些作为Python源代码指定,通常是一个列表字面量。

working-directory

working-directory选项允许指定测试将运行的目录。当运行时,测试运行器将切换到该目录。如果工作目录为空字符串或未指定,则配方将在部分中创建一个工作目录。

environment

在开始测试之前应导出的环境变量集。

initialization

提供在运行测试之前要运行的初始化代码。

relative-paths

使用相对于测试脚本的egg、测试和工作目录路径。

(注意,由于Zope测试运行器的限制,目前分布不能是zip文件。待办事项:修复测试运行器!)

为了说明这一点,我们将在我们的示例buildout中创建一对项目

>>> mkdir(sample_buildout, 'demo')
>>> mkdir(sample_buildout, 'demo', 'demo')
>>> write(sample_buildout, 'demo', 'demo', '__init__.py', '')
>>> write(sample_buildout, 'demo', 'demo', 'tests.py',
... '''
... import unittest
...
... class TestDemo(unittest.TestCase):
...    def test(self):
...        pass
...
... def test_suite():
...     loader = unittest.TestLoader()
...     return loader.loadTestsFromTestCase(TestDemo)
... ''')
>>> write(sample_buildout, 'demo', 'setup.py',
... """
... from setuptools import setup
...
... setup(name = "demo")
... """)
>>> write(sample_buildout, 'demo', 'README.txt', '')
>>> mkdir(sample_buildout, 'demo2')
>>> mkdir(sample_buildout, 'demo2', 'demo2')
>>> write(sample_buildout, 'demo2', 'demo2', '__init__.py', '')
>>> write(sample_buildout, 'demo2', 'demo2', 'tests.py',
... '''
... import unittest
...
... class Demo2Tests(unittest.TestCase):
...    def test2(self):
...        pass
...
... def test_suite():
...     loader = unittest.TestLoader()
...     return loader.loadTestsFromTestCase(Demo2Tests)
... ''')
>>> write(sample_buildout, 'demo2', 'setup.py',
... """
... from setuptools import setup
...
... setup(name = "demo2", install_requires= ['demoneeded'])
... """)
>>> write(sample_buildout, 'demo2', 'README.txt', '')

Demo 2依赖于demoneeded

>>> mkdir(sample_buildout, 'demoneeded')
>>> mkdir(sample_buildout, 'demoneeded', 'demoneeded')
>>> write(sample_buildout, 'demoneeded', 'demoneeded', '__init__.py', '')
>>> write(sample_buildout, 'demoneeded', 'demoneeded', 'tests.py',
... '''
... import unittest
...
... class TestNeeded(unittest.TestCase):
...    def test_needed(self):
...        pass
...
... def test_suite():
...     loader = unittest.TestLoader()
...     return loader.loadTestsFromTestCase(TestNeeded)
... ''')
>>> write(sample_buildout, 'demoneeded', 'setup.py',
... """
... from setuptools import setup
...
... setup(name = "demoneeded")
... """)
>>> write(sample_buildout, 'demoneeded', 'README.txt', '')

我们将更新我们的buildout,以将demo项目作为开发egg安装,并创建测试脚本

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo demoneeded demo2
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs =
...    demo
...    demo2
... script = test
... """)

请注意,我们在eggs选项中指定了demo和demo2,并且我们将它们放在不同的行上。

我们还指定了离线选项,以在离线模式下运行buildout。

现在,当我们运行buildout时

>>> import os
>>> os.chdir(sample_buildout)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')

我们在bin目录中安装了一个测试脚本

>>> ls(sample_buildout, 'bin')
-  buildout
-  test

我们还获得了一个用于运行测试的部分目录

>>> ls(sample_buildout, 'parts')
d  testdemo

更新时保持其内容完整

>>> _ = system(os.path.join(sample_buildout, 'bin', 'test') +
...            ' -q --coverage=coverage')
>>> ls(sample_buildout, 'parts', 'testdemo')
d  coverage
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> ls(sample_buildout, 'parts', 'testdemo')
d  coverage

我们可以运行测试脚本来运行我们的演示测试

>>> print_(system(os.path.join(sample_buildout, 'bin', 'test') + ' -vv'),
...        end='')
Running tests at level 1
Running zope.testrunner.layer.UnitTests tests:
  Set up zope.testrunner.layer.UnitTests in 0.001 seconds.
  Running:
 test (demo.tests.TestDemo...)
 test2 (demo2.tests.Demo2Tests...)
  Ran 2 tests with 0 failures, 0 errors and 0 skipped in 0.001 seconds.
Tearing down left over layers:
  Tear down zope.testrunner.layer.UnitTests in 0.001 seconds.

请注意,我们没有运行所需的演示测试。测试仅针对列出的蛋(egg)运行,而不是它们的依赖项。

如果我们从配置中省略脚本选项,那么测试脚本将从中获得它的名称

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> ls(sample_buildout, 'bin')
-  buildout
-  testdemo

我们可以运行测试脚本来运行我们的演示测试

>>> print_(system(os.path.join(sample_buildout, 'bin', 'testdemo') + ' -q'),
...        end='')
Running zope.testrunner.layer.UnitTests tests:
  Set up zope.testrunner.layer.UnitTests in 0.001 seconds.
  Ran 1 tests with 0 failures, 0 errors and 0 skipped in 0.001 seconds.
Tearing down left over layers:
  Tear down zope.testrunner.layer.UnitTests in 0.001 seconds.

如果我们需要在测试脚本中包含其他路径,我们可以使用extra-paths选项来指定它们

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/sample-buildout/parts/testdemo')
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run([
        '--test-path', '/sample-buildout/demo',
        ]))

我们可以使用working-directory选项来指定工作目录

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
... working-directory = /foo/bar
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/foo/bar')
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run([
        '--test-path', '/sample-buildout/demo',
        ]))

现在,我们的测试使用指定的工作目录,其指定的部分目录已消失

>>> ls(sample_buildout, 'parts')

如果我们需要指定默认选项,我们可以使用defaults选项。例如,Zope 3应用程序通常在名为ftests或tests的模块中定义测试套件。默认测试运行器的行为是查找名为tests的模块。要指定我们希望在tests和ftests模块中查找,我们需要为–tests-pattern选项提供一个默认值。如果我们喜欢点(dots),我们也可以使用-v选项请求更详细的输出

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
... defaults = ['--tests-pattern', '^f?tests$',
...             '-v'
...            ]
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/sample-buildout/parts/testdemo')
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run((['--tests-pattern', '^f?tests$',
'-v'
]) + [
        '--test-path', '/sample-buildout/demo',
        ]))

从这个示例中需要注意的一些事项

  • 给定表达式的两侧放置了括号。

  • 去除了前导空白。

为了演示环境(environment)选项,我们首先更新测试以包含对环境变量的检查

>>> write(sample_buildout, 'demo', 'demo', 'tests.py',
... '''
... import unittest
... import os
...
... class DemoTests(unittest.TestCase):
...    def test(self):
...        self.assertEqual('42', os.environ.get('zc.recipe.testrunner', '23'))
...
... def test_suite():
...     loader = unittest.TestLoader()
...     return loader.loadTestsFromTestCase(DemoTests)
... ''')

使用当前构建输出(buildout)运行它们会产生失败

>>> print_(system(os.path.join(sample_buildout, 'bin', 'testdemo')
...               + ' -vv'),
...        end='') # doctest: +ELLIPSIS
Running tests at level 1
Running zope.testrunner.layer.UnitTests tests:
  Set up zope.testrunner.layer.UnitTests in 0.001 seconds.
  Running:
 test (demo.tests.DemoTests...) (... s)
<BLANKLINE>
<BLANKLINE>
Failure in test test (demo.tests.DemoTests...)
Traceback (most recent call last):
  ...
AssertionError: '42' != '23'
...
  Ran 1 tests with 1 failures, 0 errors and 0 skipped in 0.001 seconds.
Tearing down left over layers:
  Tear down zope.testrunner.layer.UnitTests in 0.001 seconds.
<BLANKLINE>
Tests with failures:
   test (demo.tests.DemoTests...)

让我们更新构建输出以指定测试运行器所需的环境变量

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... environment = testenv
...
... [testenv]
... zc.recipe.testrunner = 42
... """)

运行构建输出(buildout)并看到测试运行器脚本现在包括设置环境变量的步骤。此外,测试再次通过

>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/sample-buildout/parts/testdemo')
os.environ['zc.recipe.testrunner'] = '42'
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run([
        '--test-path', '/sample-buildout/demo',
        ]))
>>> print_(system(os.path.join(sample_buildout, 'bin', 'testdemo')+' -vv'),
...        end='')
Running tests at level 1
Running zope.testrunner.layer.UnitTests tests:
  Set up zope.testrunner.layer.UnitTests in 0.001 seconds.
  Running:
 test (demo.tests.DemoTests...)
  Ran 1 tests with 0 failures, 0 errors and 0 skipped in 0.001 seconds.
Tearing down left over layers:
  Tear down zope.testrunner.layer.UnitTests in 0.001 seconds.

我们可以在构建输出(buildout)中添加初始化步骤。这些步骤将被添加到脚本末尾

>>> write(sample_buildout, 'buildout.cfg',
... r"""
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
... defaults = ['--tests-pattern', '^f?tests$',
...             '-v'
...            ]
... initialization = sys.stdout.write('Hello all you egg-laying pythons!\n')
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/sample-buildout/parts/testdemo')
sys.stdout.write('Hello all you egg-laying pythons!\n')
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run((['--tests-pattern', '^f?tests$',
'-v'
]) + [
        '--test-path', '/sample-buildout/demo',
        ]))

这也可以与多行初始化部分一起工作

>>> write(sample_buildout, 'buildout.cfg',
... r"""
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
... defaults = ['--tests-pattern', '^f?tests$',
...             '-v'
...            ]
... initialization = sys.stdout.write('Hello all you egg-laying pythons!\n')
...               sys.stdout.write('I thought pythons were live bearers?\n')
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir('/sample-buildout/parts/testdemo')
sys.stdout.write('Hello all you egg-laying pythons!\n')
sys.stdout.write('I thought pythons were live bearers?\n')
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run((['--tests-pattern', '^f?tests$',
'-v'
]) + [
        '--test-path', '/sample-buildout/demo',
        ]))

如果使用relative-paths选项,egg(和额外)路径将以测试脚本为基准生成

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
...               ${buildout:directory}/sources
... relative-paths = true
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import os
<BLANKLINE>
join = os.path.join
base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
base = os.path.dirname(base)
<BLANKLINE>
import sys
sys.path[0:0] = [
  join(base, 'demo'),
  ...
  '/usr/local/zope/lib/python',
  join(base, 'sources'),
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir(join(base, 'parts/testdemo'))
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run([
        '--test-path', join(base, 'demo'),
        ]))

relative-paths选项可以在构建输出(buildout)级别指定

>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
... develop = demo
... parts = testdemo
... offline = true
... relative-paths = true
...
... [testdemo]
... recipe = zc.recipe.testrunner
... eggs = demo
... extra-paths = /usr/local/zope/lib/python
...               ${buildout:directory}/sources
... """)
>>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout') + ' -q'),
...        end='')
>>> cat(sample_buildout, 'bin', 'testdemo')  # doctest: +ELLIPSIS
#!/usr/local/bin/python2.4
<BLANKLINE>
import os
<BLANKLINE>
join = os.path.join
base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
base = os.path.dirname(base)
<BLANKLINE>
import sys
sys.path[0:0] = [
  join(base, 'demo'),
  ...
  '/usr/local/zope/lib/python',
  join(base, 'sources'),
  ]
<BLANKLINE>
import os
sys.argv[0] = os.path.abspath(sys.argv[0])
os.chdir(join(base, 'parts/testdemo'))
<BLANKLINE>
<BLANKLINE>
import zope.testrunner
<BLANKLINE>
if __name__ == '__main__':
    sys.exit(zope.testrunner.run([
        '--test-path', join(base, 'demo'),
        ]))

下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

zc.recipe.testrunner-3.1.tar.gz (20.4 kB 查看哈希值)

上传于 来源

构建版本

zc.recipe.testrunner-3.1-py3-none-any.whl (15.8 kB 查看哈希值)

上传于 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误日志 StatusPage StatusPage 状态页面