Using pytest fixtures from upper-level conftest.py in subdirectories - python

I'm trying to use a fixture from a subdirectory that is defined in the parent directory's conftest.py however, I'm just constantly getting a "fixture [name] not found" error when doing so. Example of the directory structure:
Tests/
conftest.py
test_1.py
test_subdirectory_1/
test_subdirectory_2/
conftest.py
test_2.py
I'd like to use a fixture that has a session scope in the original conftest.py (in the Tests/ directory) in the test_2.py file. However whenever I run test_2.py from the test_subdirectory_2 folder, it gives me a fixture not found error.
I'm doing this from the command line:
root#[ip]:/Test/test_subdirectory_1/test_subdirectory/2# pytest test_2.py
and it spits out:
E Fixture not found.
however, if I move over to the root directory and I do:
root#[ip]:/Test# pytest -k "test_name_from_test_2"
it works perfectly fine. I need to be able to run it from its own directory by just specifying the file name.
Pytest documentation says this type of file structure should be acceptable as tests are supposed to be able to look upward in parent directories for additional fixtures. Can anyone tell me why this is happening?
Here's the platform/version im using: platform linux -- Python 3.8.5, pytest-6.1.0, py-1.9.0, pluggy-0.13.1

Related

pytest config within pytest.ini not being registered when pytest.ini is in tests subdirectory rather than project root directory

pytest is issuing a warning due to an unknown custom mark when running my test suite despite (hopefully) registering it correctly as per the pytest documentation (see https://docs.pytest.org/en/stable/mark.html#registering-marks).
My Python project's structure is (simplified for the sake of this query):
my_project/
src/
tests/
integration/
unit/
conftest.py
pytest.ini
My pytest.ini is (again, simplified):
# pytest.ini
[pytest]
markers =
incremental: marks related sequential tests to xfail after an earlier failure
because my conftest.py contains the #pytest.mark.incremental recipe outlined in the pytest documentation (see https://docs.pytest.org/en/latest/example/simple.html#incremental-testing-test-steps).
When I run pytest from the command line from within the root directory of my project (i.e. /my_project/ $ pytest), pytest issues the following warning:
PytestUnknownMarkWarning: Unknown pytest.mark.incremental - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
#pytest.mark.incremental
-- Docs: https://docs.pytest.org/en/stable/warnings.html
However, if I tell pytest to run the tests directory (i.e. /my_project/ $ pytest tests) I get no such warning. Similarly if I move my pytest.ini file from within the tests directory back to the project root directory then again I don't get the error.
Is there a way to configure pytest so that I can keep my structure as tests/pytest.ini to avoid over-cluttering the project root directory, while still ensuring that my pytest.ini is read correctly by pytest when I just run /my_project/ $ pytest from the command line?
Extra info incase useful:
(my-project-env) /Users/me/Documents/my_project/ $ pytest
============================================= test session starts =============================================
platform darwin -- Python 3.8.5, pytest-6.0.2, py-1.9.0, pluggy-0.13.1
rootdir: /Users/me/Documents/my_project
I know this is an old question, but may I suggest that you run pytest from inside the folder where you put your pytest.ini file?
cd tests
pytest
I think that may solve your problem.

ImportError - tests failing on CircleCI but pass locally

Exactly as title says - my folder structure is something like this:
venv/
__init__.py
.circleci/
config.yml
Dockerfile
docker-compose.yml
config.py
requirements.txt
src/
__init__.py
other_scripts.py
tests/
__init__.py
test_a.py
test_b.py
the test files have a from config import * line. Running $ pytest from the root directory locally or through a bash shell into the container (inside a virtualenv) works as expected, but on CircleCI the build fails with an ImportError: No module named 'config' for the above line of code. I'm using python3.5 and circleCI 2.0.
Thanks in advance!
As suggested in the comment: remove __init__.py from the root dir, add an empty file named conftest.py.
For the explanation of the conftest.py trick, take a look at my other answers to similar questions, for example pytest cannot find module or Using pytest with a src layer. In short, adding a conftest.py will add the project dir to sys.path, so the config module becomes importable.
As for removal of __init__.py file, it's not related to the error, it just doesn't belong there. Surely, you don't want to make the project dir to a package, so an early removal of unneeded init module will spare you some unexpected errors in the future.

How can I make the application package available to the tests, when using py.test?

Suppose I'm writing a test. Obviously it is testing my app, so I need to import the app package somehow into the test script. The directory structure is this:
root/
app/
__init__.py
somemodule.py
tests/
my_test.py
And I run the tests like so:
cd tests
py.test # runs all the tests in the current directory
The question is: How should I import the application modules in my test modules?
In my_test.py, I tried doing from .. import app. This gives me an error Parent module '' not loaded, cannot perform relative import.
What is the standard way to accomplish this?
EDIT: Please note I edited the question to refer specifically to the py.test tool.
You should be able to make it run by properly configuring your py.test.
Add your module to your app/__init__.py the following line
from .somemodule import MyClass # or whatever ur class is called
Create a file called conftest.py in your main folder. You can leave it empty but it is used by py.test to find out the project path. Inside you can run some py.test initialization like adding fixtures.
In your my_test.py you will be able now to call
from app import MyClass
Now from your main folder you can finally:
py.test tests/test.py
This has worked for me. I think py.test has a way to include modules since you are probably not able to achieve the same without it. At least if I did not use py.test I would stick to modifying my PYTHONPATH to point to my application path.
EDIT:
Just to clarify py.test manipylates the sys.path for the testing session to include the root directory. Py.test identify the root path by using the conftest.py file. The root path is then added to the system path and used for testing.
You are indeed able to run:
py.test tests/test.py
and this would also work:
cd..
py.test rootTest/tests/test.py

Pytest not recognizing added options

I have a project directory looks like following
Projects/
....this_project/
........this_project/
............__init__.py
............code.py
............tests/
................conftest.py
................test_1.py
................test_2.py
and I added a command line option (--PALLADIUM_CONFIG) by putting following code into conftest.py
def pytest_addoption(parser):
parser.addoption("--PALLADIUM_CONFIG", action="store")
#pytest.fixture
def PALLADIUM_CONFIG(request):
return request.config.getoption("--PALLADIUM_CONFIG")
And what strange is:
if I cd into
Projects/this_project/this_project
or
Projects/this_project/this_project/tests
and run
py.test --PALLADIUM_CONFIG=***
if runs well
but if I locate myself in for example
Projects/this_project
or
Projects
then pytest gives me error
py.test: error: unrecognized arguments: --PALLADIUM_CONFIG=***
That's a limitation of pytest itself. Take a look at the docs:
Note that pytest does not find conftest.py files in deeper nested sub directories at tool startup. It is usually a good idea to keep your conftest.py file in the top level test or project root directory.
One solution is to create an external plugin, or move the option to a conftest file nearer the root.

Py.test No module named *

I have a folder structure like this
App
--App
--app.py
--Docs
--Tests
--test_app.py
In my test_app.py file, I have a line to import my app module. When I run py.test on the root folder, I get this error about no module named app. How should I configure this?
Working with Python 3 and getting the same error on a similar project layout, I solved it by adding an __init__ file to my tests module.
$ touch tests/__init__.py
I'm not great at packaging and importing, but I think that this helps pytest work out where the target App module is located.
I already had an __init__.py file in the /App/App directory and wanted to run tests from the project root without any path-mangling magic:
python -m pytest tests
The output immediately looks like this:
➟ python -m pytest tests
====================================== test session starts ======================================
platform linux -- Python 3.5.1, pytest-2.9.0, py-1.4.31, pluggy-0.3.1
rootdir: /home/andrew/code/app, inifile:
plugins: teamcity-messages-1.17
collected 46 items
... lines omitted ...
============================= 44 passed, 2 skipped in 1.61 seconds ==============================
I had a similar problem and had to delete __init__.py from the root and add an __init__.py to the tests folder.
So you are running py.test from /App. Are you sure /App/App is in your $PYTHONPATH?
If it's not, code that tries to import app will fail with such a message.
EDIT0: including the info from my comment below, for completeness.
An attempt to import app will only succeed if it was executed inside /App/App, which is not the case here. You probably want to make /App/App a package by putting __init__.py inside it, and change your import to qualify app as from App import app.
EDIT1: by request, adding further explanation from my second comment below.
By putting __init__.py inside /App/App, that directory becomes a package. Which means you can import from it, as long as it - the directory - is visible in the $PYTHONPATH. I.e. you can do from App import app if /App is in the $PYTHONPATH. Your current working directory gets automatically added to $PYTHONPATH, so when you run a script from /App, the import will work.
Running pytest with the python -m pytest command helps with this exact thing.
Since your current package is not yet in your $PYTHONPATH or sys.path - pytest gets this error.
By using python -m pytest you automatically add the working directory into sys.path for running pytest. Their documentation also mentions:
This is almost equivalent to invoking the command line script pytest
I also got same error while running test cases for my app located as below
myproject
--app1
--__init.py__
--test.py
--app2
--__init.py__
--test.py
--__init.py__
I deleted my myproject's init.py file to run my test cases.
TL;DR
You might as well add an empty conftest.py file to your root app folder.
(if you take a look at the question folder structure, that would be the same level as the "Tests" folder, not inside of it).
More info:
Pytest looks for conftest.py files inside all your project folders.
conftest.py provides configuration for the file tree pytest finds it in. Because pytest somehow scans all subdirectories starting from conftest.py folder, it should find packages/modules outside the tests folder (as long as a conftest.py file is in your app root folder).
Eventually, you might want to write some code in your empty conftest.py, specially to share fixtures among different tests files, in order to avoid duplicate code. Afterall, the DRY principle (Don't Repeat Yourself) should also be follwed when writing tests.
Adding __init.py__ to the tests folder also should help pytest to find modules throughout your application. However, note that Python 3.3+ has implicit namespace packages that allow it to create a packages without an __init__.py file. That been said, creating __init__.py files for this specific purpose seems more like a a workaround for pytest than a python requirement. More about that in: Is __init__.py not required for packages in Python 3.3+
I got the similar issue. And after trying multiple things including installing pytest on virtual environment and adding/removing __init__.py file from the package, none worked for me.
Solution that worked for me is(windows solution):
Added Project folder(not package folder) to python path(set PYTHONPATH=%PYTHONPATH%;%CD%)
Ran my script from Project Folder and boom, it worked.
I hit the same issue.
my-app
--conf
--my-app
--tests
I set the __init__.py files. I added a conftest.py ( for sharing pytest.fixtures ). I added this to my Poetry file ( pyproject.toml:
[tool.pytest.ini_options]
pythonpath = [
"."
Turned out it was my use of hyphens and not underscores ! Noo...
# pytest can't find Module
--my-app
# works
--my_app
What worked for me: I had to make absolute imports in my test file and call python -m test in the root folder.
This worked for me:
Went to parent app, and pip install -e . (install a local and editable app).

Categories