关于python:在子文件夹中使用pytest where test

Using pytest where test in subfolder

我正在使用python pytest来运行我的单元测试。我的项目文件夹是:

Main—包含数据文件:a.txt

Main\Tests—运行pytest的文件夹

Main\Tests\A_test文件夹,包含测试文件

_test文件夹中的测试使用文件A.txt(位于主文件夹中)。

我的问题是,当我运行py.test时,测试失败,因为它找不到A.txt

我发现这是因为pytest在运行测试时使用Main\Test路径,而不是将路径更改为Main\Tests\A_test(在测试文件中打开A.txt时使用相对路径)

我的问题:有没有一种方法可以将pytest change目录设置到它为每个测试执行的测试的文件夹中?所以测试中的相对路径仍然有效?

有没有其他通用的解决方法?(我不想把所有东西都改成绝对路径或者类似的东西,这也是一个例子,在现实生活中我有几百个测试)。

谢谢您,

诺姆


方案A

在项目的根目录下,创建一个名为tests.py的文件,其中包含以下内容

1
2
3
4
5
6
import os, pathlib
import pytest

os.chdir( pathlib.Path.cwd() / 'Tests' )

pytest.main()

然后可以使用命令python tests.py运行测试。

选项B

对于那些喜欢使用batch/bash运行脚本的人,我们可以更改batch/bash中的目录,然后调用运行pytest框架的python脚本。为此,请在项目文件夹中创建以下脚本。

test.bat(用于Windows)

1
2
3
4
5
@echo off

cd /d %~dp0Tests
python %~dp0Tests/runner.py %*
cd /d %~dp0

test.sh(用于Linux)

1
2
3
cd $PWD/Tests
python runner.py $@
cd $PWD

然后在"测试"文件夹中,创建名为runner.py的文件,其中包含以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
import pathlib, sys
import pytest

cwd = pathlib.Path.cwd()

# Add the project's root directory to the system path
sys.path.append(str( cwd.parent ))

# This is optional, but you can add a lib directory
# To the system path for tests to be able to use
sys.path.append(str( cwd / 'lib' ))

pytest.main()

如果目录结构在tests文件夹中包含某种类型的lib文件夹,我们可以通过创建一个pytest.ini配置文件来指示pytest忽略它,方法如下。

1
2
[pytest]
norecursedirs = lib

在这种情况下,您的目录/文件结构最终将是:

1
2
3
4
5
6
7
8
9
10
root
├── test.bat
├── test.sh
├── Main
└── Tests
    ├── runner.py
    ├── pytest.ini # Optional pytest config file
    ├── lib # Optional, contains helper modules for the tests
    ├── tests # Tests go here
    └── # Or, in the OPs case, you could also place all of your tests here

。附加信息

这不是运行pytest的典型方法,但我更喜欢使用pytest.main(),因为这个小技巧允许我们:

  • 有任何目录结构。
  • 在测试运行程序启动之前执行代码。
  • 您仍然可以传入命令行选项,它的行为将与直接运行pytest命令的行为完全相同。

嗯,我有点解决了它,不确定这是最好的方法,但它是有效的:

在每个测试中:

  • 我检查测试是从IT目录还是从\Main\Tests执行。
  • 如果是从\Main\Tests执行,那么我就从chdir执行到\Main\Tests\A_test
  • 我用def setUpClass方法来做这个。

    例如:

    1
    2
    3
    4
    @classmethod
    def setUpClass(cls):
        if (os.path.exists(os.path.join(os.curdir,"A_test"))):
            os.chdir("A_test")

    无论是从Tests文件夹(带pytest)还是从A_test文件夹(通过pycharm)执行,这都会使测试通过。