使用 pytest 在子文件夹中进行测试

问题描述 投票:0回答:6

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

Main
- 包含数据文件:
A.txt

Main\Tests
- 我运行 pytest 的文件夹

Main\Tests\A_test
- 包含测试文件的文件夹

A_test 文件夹中的测试使用文件

A.txt
(位于主文件夹中)。

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

A.txt

我发现这是因为pytest在运行测试时使用了路径

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

我的问题:有没有办法让 pytest 将目录更改为它为每个测试执行的测试的文件夹?这样测试中的相对路径仍然有效?

还有其他通用方法来解决这个问题吗? (我不想将所有内容更改为绝对路径或类似的东西,这也是一个例子,在现实生活中我有数百个测试)。

谢谢你,

诺姆

python unit-testing testing pytest subdirectory
6个回答
14
投票

选项 A — 最小解决方案

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

import os, pathlib
import pytest

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

pytest.main()

然后您可以使用命令

python tests.py
来运行测试。




选项 B — 使用批处理/bash 测试运行程序

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

test.bat(适用于 Windows)

@echo off

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

test.sh(适用于 Linux)

cd $PWD/Tests
python runner.py $@
cd $PWD

然后在 Tests 文件夹中,创建一个名为 runner.py 的文件,其中包含以下内容

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 忽略它。

[pytest]
norecursedirs = lib

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

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
    命令完全相同。

5
投票

好吧,我解决了这个问题,不确定这是最好的方法,但它有效:

在每项测试中:

  1. 我检查测试是从它的目录还是从
    \Main\Tests
  2. 执行
  3. 如果是从
    \Main\Tests
    执行,那么我
    chdir
    \Main\Tests\A_test

我是在

def setUpClass
方法下完成此操作的。

例如:

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

这使得无论是从

Tests
文件夹(使用 pytest)还是从
A_test
文件夹(通过 pycharm)执行,测试都会通过


5
投票

__init__.py
添加到测试包中对我有用。所有测试均在之后执行。


4
投票

假设您需要根

Main
sys.path
中。

提供您当前的目录是

Main/
:

$python -m pytest Tests/A_test

这会将

Main
附加到
sys.path
并在
A_test
子目录中运行测试。 有关 pythonpath 和 pytest 关系的更多信息,请参见: http://doc.pytest.org/en/latest/pythonpath.html#pythonpath


1
投票

解决此问题的“通用”(即常用)方法是将软件包安装为可编辑安装

> py -m pip -e .

这需要在运行上述命令之前首先在文件夹中添加

__init__.py
(将其变成包)。

除此之外,我认为“最真实”的答案(可能取决于意见)来自 pytest docs 本身:

testpaths
配置选项可以在
setup.cfg
pytest.ini
tox.ini
中设置,或
pyroject.toml
文件。


0
投票

我通过在

testpaths
中使用
pytest.ini
来实现此功能:

# pytest.ini or .pytest.ini
[pytest]
minversion = 6.0
addopts = -ra -q
; addopts = -s -vv
testpaths =
    tests
env = 
    VAULT_TOKEN=asdfasdf
    TEST_FLAG=true

参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.