问题
I'm using python pytest to run my unit tests. My project folders are:
Main - contains data file: A.txt
Main\Tests - the folder from which I run pytest
Main\Tests\A_test - folder that contains a test file
The test in A_test folder uses the file A.txt (that is in Main folder).
My problem is that when I run py.test the test fails because it can't find A.txt.
I found out that it is because pytest uses the path Main\Test when running the test instead of changing the path to Main\Tests\A_test (I'm using relative path when opening A.txt inside the test file)
My question: is there a way to make pytest change directory to the folder of the test it executes for each test? so that relative paths inside the tests will still work?
Is there some other generic way to solve it? (I don't want to change everything to absolute paths or something like this, also this is an example, in real life I have several hundreds tests).
Thank you,
Noam
回答1:
Option A — Minimal solution
At the root of your project, create a file called tests.py with the following in it
import os, pathlib
import pytest
os.chdir( pathlib.Path.cwd() / 'Tests' )
pytest.main()
You can then use the command python tests.py to run the tests.
Option B — With batch/bash test runners
For those who prefer using batch/bash to run scripts, we can change directories within batch/bash, and then call a Python script that runs the pytest framework. To do this, create the following scripts in the project folder.
test.bat (for Windows)
@echo off
cd /d %~dp0Tests
python %~dp0Tests/runner.py %*
cd /d %~dp0
test.sh (for Linux)
cd $PWD/Tests
python runner.py $@
cd $PWD
And then in the Tests folder, create a file called runner.py with the following
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()
If your directory structure includes some type of lib folder within your Tests folder, we can instruct pytest to ignore it by creating a pytest.ini config file with the following.
[pytest]
norecursedirs = lib
Under this scenario, your directory/file structure would end up being:
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
Additional Comments
The methods above aren't the typical way of running pytest, but I prefer using pytest.main() because it allows us to:
- Have any directory structure.
- Execute code before the test runner starts.
- And you can still pass in command line options, and it will behave exactly the same as if you were running the
pytestcommand directly.
回答2:
Well I kind of solved it, not sure it is the best way but it is working:
In each of the tests:
- I check if the test is being executed from it directory or from
\Main\Tests - If it is being executed from
\Main\Teststhen Ichdirto\Main\Tests\A_test
I do this under the def setUpClass method.
For example:
@classmethod
def setUpClass(cls):
if (os.path.exists(os.path.join(os.curdir, "A_test"))):
os.chdir("A_test")
This makes the test pass no matter if it is executed from Tests folder (with pytest) or from A_test folder (through pycharm)
回答3:
Assuming you need your root Main in the sys.path.
Giving your current dir is Main/:
$python -m pytest Tests/A_test
This will append Main to the sys.path and run tests at the A_test subdirectory.
More about pythonpath and pytest relationship here: http://doc.pytest.org/en/latest/pythonpath.html#pythonpath
回答4:
Adding __init__.py to the package of the tests worked for me. All test are executed afterwards.
来源:https://stackoverflow.com/questions/47498390/using-pytest-where-test-in-subfolder