返回: Pytest权威教程

优质集成实践

使用pip安装包

对于开发,我们建议你将[venv来安装应用程序和任何依赖项,以及pytest包本身。这可确保你的代码和依赖项与系统Python安装隔离。

接下来,setup.py使用以下最低内容将文件放在包的根目录中:

from setuptools import setup,find_packages

setup(name="PACKAGENAME",packages=find_packages())

PACKAGENAME包裹的名称在哪里。然后,你可以通过从同一目录运行,以“可编辑”模式安装程序包:

pip install -e .

它允许你更改源代码(测试和应用程序)并随意重新运行测试。这与运行类似,或者使用符号链接将你的包安装到开发代码中。pythonsetup.pydevelop``condadevelop

Python测试发现的约定

Pytest实现以下标准测试发现:

  • 如果未指定参数,则从`testpaths(如果已配置)或当前目录开始收集。或者,命令行参数可以用于目录,文件名或节点ID的任意组合。
  • 递归到目录,除非它们匹配norecursedirs
  • 在这些目录,搜索test_*.py*_test.py文件,由他们进口[的测试包名。
  • 从这些文件中收集测试项目:
    • test在类之外的前缀测试函数或方法
    • test前缀测试Test类中的前缀测试函数或方法(没有__init__方法)

有关如何自定义测试发现的示例[更改标准(Python)测试发现。

在Python模块中,pytest还使用标准的[unittest.TestCase子类化技术发现测试。

选择测试布局结构/导入规则

pytest支持两种常见的测试布局:

在应用程序代码外测试

如果你有许多函数测试,或者出于其他原因希望将测试与实际应用程序代码分开(通常是个好主意),那么将测试放入实际应用程序代码之外的额外目录可能会很有用:

setup.py
mypkg/
__init__.py
app.py
view.py
tests/
test_app.py
test_view.py
...

这有以下好处:

  • 执行后,你的测试可以针对已安装的版本运行。pipinstall.
  • 执行后,你可以使用可编辑安装对本地副本运行测试。pipinstall--editable.
  • 如果你没有setup.py文件并且依赖于默认情况下Python将当前目录放入sys.path以导入你的包,则可以执行直接对本地副本执行测试,而不使用。python-mpytest``pip

注意:

有关调用和调用之间差异的更多信息,请参阅[pytest导入机制和sys.path / PYTHONPATH。pytest``python-mpytest

请注意,使用此方案时,你的测试文件必须具有唯一的名称,因为pytest将它们作为顶级模块导入,因为没有包来从中获取完整的包名称。换句话说,在上面的示例中的试验文件将被导入为test_apptest_view通过加入顶层模块tests/sys.path

如果需要具有相同名称的测试模块,可以将__init__.py文件添加到tests文件夹和子文件夹,并将其更改为包:

setup.py
mypkg/
...
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py

现在Pytest将加载模块,tests.foo.test_viewtests.bar.test_view允许你使用相同名称的模块。但是现在这引入了一个微妙的问题:为了从tests目录中加载测试模块,pytest将存储库的根目录sys.path添加到,这增加了现在mypkg也可导入的副作用。如果你使用像tox这样的工具在虚拟环境中测试程序包,则会出现问题,因为你要测试程序包的已安装版本,而不是存储库中的本地代码。

在这种情况下,强烈建议使用src应用程序根包位于根目录的子目录中的布局:

setup.py
src/
mypkg/
__init__.py
app.py
view.py
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py

这种布局可以防止许多常见的陷阱,并且有很多好处,这在[IonelCristianMărieş的有更好的解释。

测试作为应用程序代码的一部分

如果测试和应用程序模块之间存在直接关系并希望将它们与应用程序一起分发,则将测试目录内联到应用程序包中非常有用:

setup.py
mypkg/
__init__.py
app.py
view.py
test/
__init__.py
test_app.py
test_view.py
...

在此方案中,使用以下--pyargs选项可以轻松运行测试:

pytest --pyargs mypkg

pytest将发现mypkg安装位置并从那里收集测试。

请注意,此布局也与src上一节中提到的布局一起使用。

注意:

你可以为你的应用程序使用Python3命名空间包(PEP420),但pytest仍将根据文件的存在执行[测试包名称发现__init__.py。如果你使用上面两个推荐的文件系统布局中的一个,但是__init__.py从你的目录中删除它们,那么它应该适用于Python3.3及更高版本。但是,从“内联测试”开始,你将需要使用绝对导入来获取应用程序代码。

注意:

如果pytest在递归到文件系统时找到“a / b / test_module.py”测试文件,它将确定导入名称,如下所示:

  • 确定basedir:这是第一个“向上”(朝向根)目录,不包含__init__.py。如果如两者ab包含一个__init__.py文件,然后父目录a将成为basedir
  • 执行以使测试模块可以在完全限定的导入名称下导入。sys.path.insert(0,basedir)
  • importa.b.test_module其中路径是通过将路径分隔符/转换为“。”字符来确定的。这意味着你必须遵循将目录和文件名直接映射到导入名称的约定。

这种有点进化的导入技术的原因在于,在较大的项目中,多个测试模块可能相互导入,因此导出规范的导入名称有助于避免出现意外情况,例如测试模块导入两次。

tox

一旦完成了你的工作并希望确保你的实际软件包通过所有测试,你可能需要查看tox,virtualenv测试自动化工具及其[pytest支持。tox帮助你使用预定义的依赖项设置virtualenv环境,然后使用选项执行预配置的测试命令。它将针对已安装的软件包运行测试,而不是针对源代码检查,从而有助于检测包装故障。

与setuptools集成

你可以使用[pytest-runner插件将测试运行集成到基于setuptools的项目中。

将此添加到setup.py文件:

from setuptools import setup

setup(
# ...,
setup_requires=["pytest-runner",...],
tests_require=["pytest",...],
# ...,
)

并在setup.cfg文件中创建一个别名:

[aliases]
test=pytest

如果你现在输入:

python setup.py test

这将使用执行你的测试pytest-runner。因为这是一个独立版本,pytest无需事先安装,无论如何都需要调用test命令。你还可以使用其他参数传递给pytest,例如测试目录或其他选项--addopts

你还可以setup.cfg通过将文件放入以下[tool:pytest]部分来指定文件中的其他pytest-ini选项:

[tool:pytest]
addopts = --verbose
python_files = testing/*/*.py

手动整合

如果由于某种原因你不想/不能使用pytest-runner,你可以编写自己的setuptools测试命令来调用pytest。

import sys

from setuptools.command.test import test as TestCommand

class PyTest(TestCommand):
user_options = [("pytest-args=","a","Arguments to pass to pytest")] def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = "" def run_tests(self):
import shlex # import here,cause outside the eggs aren't loaded
import pytest errno = pytest.main(shlex.split(self.pytest_args))
sys.exit(errno) setup(
# ...,
tests_require=["pytest"],
cmdclass={"pytest": PyTest},
)

现在,如果你运行:

python setup.py test

这将pytest在需要时下载,然后按照你的预期运行测试。你可以使用--pytest-args-a命令行选项传递单个参数字符串。例如:

python setup.py test -a "--durations=5"

相当于运行 pytest--durations=5

片状”测试是表现出间歇性或偶发性失败的测试,似乎具有非确定性行为。有时它会通过,有时会失败,而且不清楚为什么。本页讨论了可以提供帮助的pytest函数以及识别,修复或减轻它们的其他一般策略。

Pytest权威教程22-优质集成实践的更多相关文章

  1. Pytest权威教程(官方教程翻译)

    Pytest权威教程01-安装及入门 Pytest权威教程02-Pytest 使用及调用方法 Pytest权威教程03-原有TestSuite的执行方法 Pytest权威教程04-断言的编写和报告 P ...

  2. Pytest权威教程11-模块及测试文件中集成doctest测试

    目录 模块及测试文件中集成doctest测试 编码 使用doctest选项 输出格式 pytest-specific 特性 返回: Pytest权威教程 模块及测试文件中集成doctest测试 编码 ...

  3. Pytest权威教程01-安装及入门

    目录 安装及入门 安装 Pytest 创建你的第一个测试用例 执行多条测试用例 断言抛出了指定异常 使用类组织多条测试用例 函数测试中请求使用独立的临时目录 进一步阅读 返回: Pytest权威教程 ...

  4. Pytest权威教程21-API参考-03-夹具(Fixtures)

    目录 夹具(Fixtures) @ pytest.fixture config.cache的 capsys capsysbinary capfd capfdbinary doctest_namespa ...

  5. Pytest权威教程02-Pytest 使用及调用方法

    目录 Pytest 使用及调用方法 使用python -m pytest调用pytest 可能出现的执行退出code 获取版本路径.命令行选项及环境变量相关帮助 第1(N)次失败后停止测试 指定及选择 ...

  6. Pytest权威教程06-使用Marks标记测试用例

    目录 使用Marks标记测试用例 在未知标记上引发异常: -strict 标记改造和迭代 返回: Pytest权威教程 使用Marks标记测试用例 通过使用pytest.mark你可以轻松地在测试用例 ...

  7. Pytest权威教程14-缓存:使用跨执行状态

    目录 缓存:使用跨执行状态 使用方法 首先只重新运行故障或故障 上次运行中没有测试失败时的行为 新的config.cache对象 检查缓存内容 清除缓存内容 逐步修复失败用例 unittest.Tes ...

  8. Pytest权威教程16-经典xUnit风格的setup/teardown

    目录 经典xUnit风格的setup/teardown 模块级别setup/teardown 类级别setup/teardown 方法和函数级别setup/teardown 返回: Pytest权威教 ...

  9. Pytest权威教程17-安装和使用插件

    目录 安装和使用插件 在测试模块或conftest文件中要求/加载插件 找出哪些插件是可用的 按名称取消/取消注册插件 返回: Pytest权威教程 安装和使用插件 本节讨论如何安装和使用第三方插件. ...

随机推荐

  1. C# winform导出数据弹出可修改目录及文件名的窗口

    string localFilePath = "", fileNameExt = "", newFileName = "", FilePat ...

  2. Hadoop之HDFS读写流程

    hadoophdfs 1. HDFS写流程 2. HDFS写流程 1. HDFS写流程 HDFS写流程 副本存放策略: 上传的数据块后,触发一个新的线程,进行存放. 第一个副本:与client最近的机 ...

  3. Markdown 初学总结

    Markdown Tutorial(Typora-Specific) 1. Headers 最多可有六级标题,在标题前加 # 作为标记.注意标记与标题内容之间有空格: # 这是一级标题 ## 这是二级 ...

  4. BUAAOO-Third-Summary

    目录 从DBC到JML SMT solver 使用 JML toolchain的可视化输出 和我的测试结果 规格的完善策略 架构设计 debug情况 心得体会 一.从DBC到JML 契约式设计(Des ...

  5. 论PM与团队与敏捷开发

    敏捷开发是每个有追求的PM都会去读的书 敏捷开发是很少程序会去读的书 敏捷开发是团体其他人很少会读的书 然而, 据我的 所见, 所闻, 所论 敏捷开发在大家的脑袋里分为很多种版本 既有可以一辩的新鲜思 ...

  6. Java 之 函数式接口

    函数式接口 一.概念 函数式接口在 java 中是指:有且仅有一个抽象方法的接口. 函数式接口,即适用于函数式编程场景的接口. 而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用 ...

  7. Oracle 操作数据库(增删改语句)

    对数据库的操作除了查询,还包括插入.更新和删除等数据操作.后3种数据操作使用的 SQL 语言也称为数据操纵语言(DML). 一.插入数据(insert 语句) 插入数据就是将数据记录添加到已经存在的数 ...

  8. OC与swift混编 #import "项目名-Swift.h"失效问题

    由于项目多个环境部署,每次改配置比较麻烦,所以线上环境一个TARGETS,内部环境一个TARGETS, 都知道oc和swift混编的时候,会生成一个'项目名-Swift.h'文件,这个文件是隐式的,需 ...

  9. 修改CentOS的YUM源

    CentOS配置本地yum源/阿里云yum源/163yuan源并配置yum源的优先级 1.查看本地yum源 2.把默认yum源备份 mkdir /opt/centos-yum.bak mv /etc/ ...

  10. Andrew Ng机器学习 四:Neural Networks Learning

    背景:跟上一讲一样,识别手写数字,给一组数据集ex4data1.mat,,每个样例都为灰度化为20*20像素,也就是每个样例的维度为400,加载这组数据后,我们会有5000*400的矩阵X(5000个 ...