Python 将pytest工作目录更改为测试用例目录

Python 将pytest工作目录更改为测试用例目录,python,pytest,working-directory,Python,Pytest,Working Directory,我有以下pytest目录结构: system_tests/ ├── conftest ├── pytest.ini │ ├── suite_1/ │ └── test_A.py │ └── suite_2/ ├── sub_suite_2a/ │ └── test_B.py └── sub_suite_2b/ └── test_C.py 当每个测试方法运行时,许多第三方库/进程在当前工作目录中生成

我有以下pytest目录结构:

system_tests/
  ├── conftest
  ├── pytest.ini
  │
  ├── suite_1/
  │   └── test_A.py
  │   
  └── suite_2/
      ├── sub_suite_2a/
      │   └── test_B.py
      └── sub_suite_2b/
          └── test_C.py
当每个测试方法运行时,许多第三方库/进程在当前工作目录中生成工件。当我从
sub_suite
文件夹(使用CLI或IDE“play”按钮)运行pytest时,文件将在
sub_suite
文件夹中生成,我希望它们位于该文件夹中。但是,当我从
system\u tests
文件夹运行pytest以运行所有测试时,所有工件都在
system\u tests
文件夹中创建,这不是我想要的


有没有一种简单的方法可以强制pytest始终使用test class文件夹作为工作目录,这样无论从何处运行测试,我都可以得到相同的结果?

为此,您可以选择许多选项。这里有一些

一,。 编写pytest fixture以检查当前工作目录是否等于所需的工作目录,如果不等于,则将所有工件文件移动到所需的目录如果您生成的工件都是相同类型的文件(例如.*.jpg、*.png、*.gif),并且您只希望它们位于不同的目录中,那么这就足够了。类似的方法可以工作

from pathlib import Path
import shutil

@pytest.fixture
def cleanup_artifacts():
    yield None
    cwd = Path.cwd()
    desired_dir = Path.home() / 'system-tests' / 'suite-2' / 'sub_suite_2a'
    if cwd != desired_dir:
        for f in cwd.glob('*.jpg'):
            shutil.move(f, desired_dir)
然后,您可以根据需要将该装置添加到测试中

二,。 您可以将pytest
rootdir
配置为所需的目录,因为pytest使用
rootdir
存储项目/testrun特定的信息

当您运行pytest时,将其作为

pytest --rootdir=desired_path
有关更多信息,请参见此处:


如果两者都不适用于您,请详细说明您的需求。当然,这可以通过pytest实现。

以下功能级别的fixture将更改为测试用例目录,运行测试(yield),然后更改回调用目录以避免副作用:

@pytest.fixture(scope=“function”)
def更改测试目录(请求):
chdir(request.fspath.dirname)
产量
chdir(request.config.invocation\u dir)
  • request
    是一个内置的pytest夹具
  • fspath
    是正在执行的测试模块的
    LocalPath
  • dirname
    是测试模块的目录
  • request.config.invocationdir
    -执行pytest的文件夹
  • request.config.rootdir
    -pytest root不会根据运行pytest的位置而改变。此处未使用,但可能有用

任何由测试启动的进程都将使用测试用例文件夹作为其工作目录,并将其日志、输出等复制到那里,而不管测试套件是在哪里执行的。

另一种更可靠的方法:始终按完整路径引用文件

\uuuu file\uuuu
是一个自动声明的Python变量,它是当前模块的名称。因此,在您的
test\u B.py
文件中,它的值为:
system\u tests/suite\u 2/sub\u suite\u 2a/test\u B.py
。只需找到父对象并选择文件的写入位置

from pathlib import Path
test_data_dir = Path(__file__).parent / "test_data"
现在,您将它们都放在同一个位置,并且可以告诉您的版本控制系统忽略它们

如果代码在库中,请确保可以使用此选项更改当前目录:

import os
from pathlib import Path
test_data_dir = Path(__file__).parent / "test_data"
os.chdir(test_data_dir)

对我来说,这看起来像是XY问题——为什么不告诉测试方法在相对于测试脚本文件的目录中生成工件呢?很好。问题是这些工件不是由测试方法直接生成的。它们由测试框架库、其他运行应用程序的日志文件等生成。现在,它们将这些文件写入工作目录。我想我需要重写一些代码,使所有路径都成为绝对路径,但我希望有一个更快的修复。我喜欢使用
cleanup\u artifacts()
fixture的想法。我肯定会在运行结束时使用它来整合和打包输出文件。然而,我尝试更改
rootdir
,但没有任何明显的效果。pytest更改了相对于新rootdir的所有路径,但最终结果是相同的。很高兴看到您找到了答案。是的,将您的工作目录更改为测试所在的目录最有意义!建议的夹具引入了会干扰其他测试的副作用,可能在将来会把你搞糊涂。根据@Farhan Kathawala的答案返回之前,使用yield然后cwd返回到
request.config.invocation\u dir