在子文件夹中使用pytest where test

Noa*_*oam 9 python unit-testing pytest

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

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

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

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

A_test文件夹中的测试使用该文件A.txt(位于Main文件夹中).

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

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

我的问题:有没有办法让pytest更改目录到它为每个测试执行的测试文件夹?那么测试中的相对路径仍然可以工作?

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

谢谢,

诺姆

wp-*_*com 6

选项A

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

import os, pathlib
import pytest

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

pytest.main()
Run Code Online (Sandbox Code Playgroud)

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


选项B

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

test.bat(对于Windows)

@echo off

cd /d %~dp0Tests
python %~dp0Tests/runner.py %*
cd /d %~dp0
Run Code Online (Sandbox Code Playgroud)

test.sh(对于Linux)

cd $PWD/Tests
python runner.py $@
cd $PWD
Run Code Online (Sandbox Code Playgroud)

然后在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()
Run Code Online (Sandbox Code Playgroud)

如果您的目录结构在Tests文件夹中包含某种类型的lib文件夹,我们可以通过创建带有以下内容的pytest.ini配置文件来指示pytest忽略它。

[pytest]
norecursedirs = lib
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

附加信息

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

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


Noa*_*oam 5

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

在每个测试中:

  1. 我检查测试是从它的目录还是从\Main\Tests
  2. 如果从那时起执行它\Main\Testschdir\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")
Run Code Online (Sandbox Code Playgroud)

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

  • 既然你提出了解决方案,我不想做出新的答案。但您也可以将“setUpClass”方法中的代码添加到“A_test/__init__.py”文件中。这样,如果您的目录中有多个测试,则无需将代码添加到每个文件中。这是 PyCharm 友好的 (3认同)

Mr.*_*tef 5

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

  • 在测试目录中添加 `__init__.py` 会使 pytest 将它们添加到 pythonpath 中,但这意味着如果您有一个名为“os”的目录,它将与 python 包 os 发生冲突,并造成严重破坏。这种情况经常发生,我不推荐。 (2认同)