代码之家  ›  专栏  ›  技术社区  ›  Mad Physicist

在非根conftest.py中使用pytest\u addoptions

  •  3
  • Mad Physicist  · 技术社区  · 6 年前

    Project/
    |
    +-- src/
    |   |
    |   +-- proj/
    |       |
    |       +-- __init__.py
    |       +-- code.py
    |       +-- tests/
    |           |
    |           +-- __init__.py
    |           +-- conftest.py
    |           +-- test_code.py
    +-- doc/
    +-- pytest.ini
    +-- setup.py
    

    可导入的包 proj 生活在 src 目录。测试与它一起安装在 proj.tests 子包。代码、测试本身和安装都可以正常工作。但是,我很难将选项传递给测试。

    我有一个选择, --plots ,在中定义 conftest.py Project/src/proj/tests/ ),这将创建 .plots/ 在根文件夹中放置一些图形调试:

    # conftest.py
    def pytest_addoption(parser):
        parser.addoption("--plots", action="store_true", default=False)
    

    我希望有两种不同的方法来运行此测试:

    1. 第一个是从命令行,在 Project 目录:

       $ pytest --plots
      

      这会立即失败

       usage: pytest [options] [file_or_dir] [file_or_dir] [...]
       pytest: error: unrecognized arguments: --plots
         inifile: /.../Project/pytest.ini
         rootdir: /.../Project
      

      如果添加包目录,运行正常:

       $ pytest src/proj --plots
       ...
       rootdir: /.../Project, inifile: pytest.ini
       ...
      

      如果我指定tests子目录:

       $ pytest src/proj/tests --plots
       ...
       rootdir: /.../Project, inifile: pytest.ini
       ...
      
    2. 第二种方法是运行 test 包本身的功能。这个 测试 函数在中定义 Project/src/proj/__init__.py

       # __init__.py
      
       def test(*args, **kwargs):
           from pytest import main
           cmd = ['--pyargs', 'proj.tests']
           cmd.extend(args)
           return main(cmd, **kwargs)
      

      该函数将在 项目 安装方式如下:

       >>> import proj
       >>> proj.test()
      

      一般来说,这是可行的,但如果我这样做

       >>> proj.test('--plots')
      

       usage:  [options] [file_or_dir] [file_or_dir] [...]
       : error: unrecognized arguments: --plots
         inifile: None
         rootdir: /some/other/folder
      

      为了这次测试,我跑了 python setup.py develop 然后 cd “d” to /some/other/folder`以确保所有内容都正确安装。

    --情节 命令行选项。似乎我已经为选项1找到了一个解决方法,即手动将其中一个包传递给 pytest ,但我甚至不完全理解它是如何工作的(为什么我也可以通过 src/proj src/proj/tests ?).

    所以问题是,如何让pytest始终如一地运行我的测试包,以便 确认测试.py 被抓了?我愿意考虑任何合理的选择,让我得到 --情节 )版本和 proj.test() 版本。


    作为参考,这是我的 pytest.ini 文件:

    # pytest.ini
    
    [pytest]
    testpaths = src/proj/tests
    confcutdir = src/proj/tests
    

    我正在用pytest3.8.0运行Pythons 2.7、3.3、3.4、3.5、3.6和3.7(在anaconda中)。在所有版本中,结果都是可重复的。

    1 回复  |  直到 4 年前
        1
  •  4
  •   Community    4 年前

    引用自 the pytest_addoption docs :

    注意:此功能只能在插件或应用程序中实现 conftest.py 位于测试根目录的文件 pytest discovers plugins during startup

    请注意 皮特斯特 找不到 确认测试.py 在工具启动时,文件位于嵌套较深的子目录中。通常情况下,保持健康是个好主意 确认测试.py 顶级测试或项目根目录中的文件。

    当你打电话的时候 Project 迪尔, 皮特斯特 将其识别为根目录,因此 addoption 上钩 Project/src/proj/tests/conftest.py

    如果你描述的项目结构是一个要求,我会移动 pytest_addopts 将impl挂接到一个单独的插件模块上;例如,它可以驻留在projectdir中的任何位置 Project/src/proj/tests/plugin_plots.py

    $ pytest -p src.proj.tests.plugin_plots
    

    这个 将执行hook impl并正确添加参数。

    (您可能需要调整 sys.path 能够正确加载自定义插件模块,例如使用 PYTHONPATH=. pytest -p python -m pytest -p ,或以可编辑模式安装项目等)

    不进入 -p 每次都坚持 pytest.ini ,例如。

    # pytest.ini
    [pytest]
    addopts=-p src.proj.tests.plugin_plots
    

    以编程方式运行测试时,启用args列表:

    def test(*args, **kwargs):
        from pytest import main
        cmd = ['-p', 'proj.tests.plugin_plots', '--pyargs', 'proj.tests']
        cmd.extend(args)
        return main(cmd, **kwargs)