pytest: prevent imported auto-used session fixture from executing multiple times












1















My pytest test files are spread across multiple packages, and they share some common fixtures. However, I found that my auto-used session-scoped fixture is ran multiple times.



Here is a basic structure of my project:



.
├── Pipfile
├── Pipfile.lock
├── __init__.py
├── common
│   ├── __init__.py
│   └── conftest.py
├── pkg_a
│   ├── __init__.py
│   ├── conftest.py
│   └── test_a.py
└── pkg_b
├── __init__.py
├── conftest.py
└── test_b.py


And here are the content of each .py file:



==> ./__init__.py <==

==> ./common/__init__.py <==

==> ./common/conftest.py <==
import pytest


@pytest.fixture(scope='session', autouse=True)
def setup():
print 'setting up'
yield
print 'tearing down'


==> ./pkg_a/__init__.py <==

==> ./pkg_a/conftest.py <==
from common.conftest import *

==> ./pkg_a/test_a.py <==
def test():
assert True

==> ./pkg_b/__init__.py <==

==> ./pkg_b/conftest.py <==
from common.conftest import *

==> ./pkg_b/test_b.py <==
def test_b():
assert True


Here is the output of pytest:



➜ pytest -s pkg_a pkg_b
========================== test session starts ==========================
platform darwin -- Python 2.7.15, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: /path/to/the/project, inifile:
collected 2 items

pkg_a/test_a.py setting up
.
pkg_b/test_b.py setting up
.tearing down
tearing down


======================= 2 passed in 0.02 seconds ========================


My understanding to the session fixtures is that they will only be ran once for the lifetime of pytest command. But here the setting up and tearing down are printed twice, and they are interleaved.



Is there any way to only execute the fixture only once? I want the setting up to be printed only once at the beginning and tearing down at the very end for the whole test session.



P.S. I know the parameterized session fixture will be execute multiple times. But I don't think my fixture is parameterized.










share|improve this question

























  • the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

    – hoefling
    Nov 22 '18 at 2:04











  • @hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

    – Liyang Chen
    Nov 22 '18 at 14:13











  • @hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

    – Liyang Chen
    Nov 22 '18 at 14:22






  • 1





    Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

    – hoefling
    Nov 22 '18 at 14:50






  • 1





    You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

    – hoefling
    Nov 22 '18 at 14:54


















1















My pytest test files are spread across multiple packages, and they share some common fixtures. However, I found that my auto-used session-scoped fixture is ran multiple times.



Here is a basic structure of my project:



.
├── Pipfile
├── Pipfile.lock
├── __init__.py
├── common
│   ├── __init__.py
│   └── conftest.py
├── pkg_a
│   ├── __init__.py
│   ├── conftest.py
│   └── test_a.py
└── pkg_b
├── __init__.py
├── conftest.py
└── test_b.py


And here are the content of each .py file:



==> ./__init__.py <==

==> ./common/__init__.py <==

==> ./common/conftest.py <==
import pytest


@pytest.fixture(scope='session', autouse=True)
def setup():
print 'setting up'
yield
print 'tearing down'


==> ./pkg_a/__init__.py <==

==> ./pkg_a/conftest.py <==
from common.conftest import *

==> ./pkg_a/test_a.py <==
def test():
assert True

==> ./pkg_b/__init__.py <==

==> ./pkg_b/conftest.py <==
from common.conftest import *

==> ./pkg_b/test_b.py <==
def test_b():
assert True


Here is the output of pytest:



➜ pytest -s pkg_a pkg_b
========================== test session starts ==========================
platform darwin -- Python 2.7.15, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: /path/to/the/project, inifile:
collected 2 items

pkg_a/test_a.py setting up
.
pkg_b/test_b.py setting up
.tearing down
tearing down


======================= 2 passed in 0.02 seconds ========================


My understanding to the session fixtures is that they will only be ran once for the lifetime of pytest command. But here the setting up and tearing down are printed twice, and they are interleaved.



Is there any way to only execute the fixture only once? I want the setting up to be printed only once at the beginning and tearing down at the very end for the whole test session.



P.S. I know the parameterized session fixture will be execute multiple times. But I don't think my fixture is parameterized.










share|improve this question

























  • the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

    – hoefling
    Nov 22 '18 at 2:04











  • @hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

    – Liyang Chen
    Nov 22 '18 at 14:13











  • @hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

    – Liyang Chen
    Nov 22 '18 at 14:22






  • 1





    Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

    – hoefling
    Nov 22 '18 at 14:50






  • 1





    You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

    – hoefling
    Nov 22 '18 at 14:54
















1












1








1








My pytest test files are spread across multiple packages, and they share some common fixtures. However, I found that my auto-used session-scoped fixture is ran multiple times.



Here is a basic structure of my project:



.
├── Pipfile
├── Pipfile.lock
├── __init__.py
├── common
│   ├── __init__.py
│   └── conftest.py
├── pkg_a
│   ├── __init__.py
│   ├── conftest.py
│   └── test_a.py
└── pkg_b
├── __init__.py
├── conftest.py
└── test_b.py


And here are the content of each .py file:



==> ./__init__.py <==

==> ./common/__init__.py <==

==> ./common/conftest.py <==
import pytest


@pytest.fixture(scope='session', autouse=True)
def setup():
print 'setting up'
yield
print 'tearing down'


==> ./pkg_a/__init__.py <==

==> ./pkg_a/conftest.py <==
from common.conftest import *

==> ./pkg_a/test_a.py <==
def test():
assert True

==> ./pkg_b/__init__.py <==

==> ./pkg_b/conftest.py <==
from common.conftest import *

==> ./pkg_b/test_b.py <==
def test_b():
assert True


Here is the output of pytest:



➜ pytest -s pkg_a pkg_b
========================== test session starts ==========================
platform darwin -- Python 2.7.15, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: /path/to/the/project, inifile:
collected 2 items

pkg_a/test_a.py setting up
.
pkg_b/test_b.py setting up
.tearing down
tearing down


======================= 2 passed in 0.02 seconds ========================


My understanding to the session fixtures is that they will only be ran once for the lifetime of pytest command. But here the setting up and tearing down are printed twice, and they are interleaved.



Is there any way to only execute the fixture only once? I want the setting up to be printed only once at the beginning and tearing down at the very end for the whole test session.



P.S. I know the parameterized session fixture will be execute multiple times. But I don't think my fixture is parameterized.










share|improve this question
















My pytest test files are spread across multiple packages, and they share some common fixtures. However, I found that my auto-used session-scoped fixture is ran multiple times.



Here is a basic structure of my project:



.
├── Pipfile
├── Pipfile.lock
├── __init__.py
├── common
│   ├── __init__.py
│   └── conftest.py
├── pkg_a
│   ├── __init__.py
│   ├── conftest.py
│   └── test_a.py
└── pkg_b
├── __init__.py
├── conftest.py
└── test_b.py


And here are the content of each .py file:



==> ./__init__.py <==

==> ./common/__init__.py <==

==> ./common/conftest.py <==
import pytest


@pytest.fixture(scope='session', autouse=True)
def setup():
print 'setting up'
yield
print 'tearing down'


==> ./pkg_a/__init__.py <==

==> ./pkg_a/conftest.py <==
from common.conftest import *

==> ./pkg_a/test_a.py <==
def test():
assert True

==> ./pkg_b/__init__.py <==

==> ./pkg_b/conftest.py <==
from common.conftest import *

==> ./pkg_b/test_b.py <==
def test_b():
assert True


Here is the output of pytest:



➜ pytest -s pkg_a pkg_b
========================== test session starts ==========================
platform darwin -- Python 2.7.15, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: /path/to/the/project, inifile:
collected 2 items

pkg_a/test_a.py setting up
.
pkg_b/test_b.py setting up
.tearing down
tearing down


======================= 2 passed in 0.02 seconds ========================


My understanding to the session fixtures is that they will only be ran once for the lifetime of pytest command. But here the setting up and tearing down are printed twice, and they are interleaved.



Is there any way to only execute the fixture only once? I want the setting up to be printed only once at the beginning and tearing down at the very end for the whole test session.



P.S. I know the parameterized session fixture will be execute multiple times. But I don't think my fixture is parameterized.







python testing pytest fixtures






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 1:05







Liyang Chen

















asked Nov 21 '18 at 15:45









Liyang ChenLiyang Chen

806




806













  • the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

    – hoefling
    Nov 22 '18 at 2:04











  • @hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

    – Liyang Chen
    Nov 22 '18 at 14:13











  • @hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

    – Liyang Chen
    Nov 22 '18 at 14:22






  • 1





    Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

    – hoefling
    Nov 22 '18 at 14:50






  • 1





    You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

    – hoefling
    Nov 22 '18 at 14:54





















  • the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

    – hoefling
    Nov 22 '18 at 2:04











  • @hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

    – Liyang Chen
    Nov 22 '18 at 14:13











  • @hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

    – Liyang Chen
    Nov 22 '18 at 14:22






  • 1





    Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

    – hoefling
    Nov 22 '18 at 14:50






  • 1





    You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

    – hoefling
    Nov 22 '18 at 14:54



















the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

– hoefling
Nov 22 '18 at 2:04





the project structure looks a bit misconfigured (why do you have an __init__.py in the project root dir? is it a package? why are test directories made to packages?). Also, importing from conftests is a bad practice as it can easily break things; conftests are not meant to be regular python modules, they will be automatically executed by pytest when found. Suggestion: remove unnecessary __init__.pys, remove conftest imports, move common/conftest.py to the project root dir.

– hoefling
Nov 22 '18 at 2:04













@hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

– Liyang Chen
Nov 22 '18 at 14:13





@hoefling understood. thanks for your suggestion! Yes, the current structure of my project is a bit messy. I'm still wondering... is it possible to archive the fixture under current structure?

– Liyang Chen
Nov 22 '18 at 14:13













@hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

– Liyang Chen
Nov 22 '18 at 14:22





@hoefling I think it makes sense to have the test file siting side by side with the logic code. I removed the __init__.py in the root folder, but the result is the same.

– Liyang Chen
Nov 22 '18 at 14:22




1




1





Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

– hoefling
Nov 22 '18 at 14:50





Again: you have to introduce a conftest.py in the project root dir where the tests are executed and remove the conftest imports.

– hoefling
Nov 22 '18 at 14:50




1




1





You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

– hoefling
Nov 22 '18 at 14:54







You can keep the tests along with the production code, but you have to be far more careful about organizing the code. pytest will append parent dirs of conftest files to sys.path, which can easily introduce import issues - especially when you're keeping tests in python packages. It makes sense to take a look at Good Integration Practices, however from my experience keeping tests in source dir only makes sense when you are going to release tests with the source code, like numpy or pandas do.

– hoefling
Nov 22 '18 at 14:54














1 Answer
1






active

oldest

votes


















0














You are right. Session scoped fixture is supposed to run only once. But if you look closely, there are two setup fixtures for test_a. One from common/conftest.py and other from pkg_a/conftest.py. You don't need to import common.conftest.py in pkg_a/conftest.py. pytest starts collecting conftest files starting from project root.
You can see the fixture setup process with --setup-show switch: pytest test_a.py --setup-show.



To solve your problem, you can remove from common.conftest import * from your test_a(b)/conftest.py files .



More about conftest collection of pytest here: https://docs.pytest.org/en/2.7.3/plugins.html






share|improve this answer


























  • If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

    – Liyang Chen
    Nov 22 '18 at 1:09













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415697%2fpytest-prevent-imported-auto-used-session-fixture-from-executing-multiple-times%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You are right. Session scoped fixture is supposed to run only once. But if you look closely, there are two setup fixtures for test_a. One from common/conftest.py and other from pkg_a/conftest.py. You don't need to import common.conftest.py in pkg_a/conftest.py. pytest starts collecting conftest files starting from project root.
You can see the fixture setup process with --setup-show switch: pytest test_a.py --setup-show.



To solve your problem, you can remove from common.conftest import * from your test_a(b)/conftest.py files .



More about conftest collection of pytest here: https://docs.pytest.org/en/2.7.3/plugins.html






share|improve this answer


























  • If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

    – Liyang Chen
    Nov 22 '18 at 1:09


















0














You are right. Session scoped fixture is supposed to run only once. But if you look closely, there are two setup fixtures for test_a. One from common/conftest.py and other from pkg_a/conftest.py. You don't need to import common.conftest.py in pkg_a/conftest.py. pytest starts collecting conftest files starting from project root.
You can see the fixture setup process with --setup-show switch: pytest test_a.py --setup-show.



To solve your problem, you can remove from common.conftest import * from your test_a(b)/conftest.py files .



More about conftest collection of pytest here: https://docs.pytest.org/en/2.7.3/plugins.html






share|improve this answer


























  • If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

    – Liyang Chen
    Nov 22 '18 at 1:09
















0












0








0







You are right. Session scoped fixture is supposed to run only once. But if you look closely, there are two setup fixtures for test_a. One from common/conftest.py and other from pkg_a/conftest.py. You don't need to import common.conftest.py in pkg_a/conftest.py. pytest starts collecting conftest files starting from project root.
You can see the fixture setup process with --setup-show switch: pytest test_a.py --setup-show.



To solve your problem, you can remove from common.conftest import * from your test_a(b)/conftest.py files .



More about conftest collection of pytest here: https://docs.pytest.org/en/2.7.3/plugins.html






share|improve this answer















You are right. Session scoped fixture is supposed to run only once. But if you look closely, there are two setup fixtures for test_a. One from common/conftest.py and other from pkg_a/conftest.py. You don't need to import common.conftest.py in pkg_a/conftest.py. pytest starts collecting conftest files starting from project root.
You can see the fixture setup process with --setup-show switch: pytest test_a.py --setup-show.



To solve your problem, you can remove from common.conftest import * from your test_a(b)/conftest.py files .



More about conftest collection of pytest here: https://docs.pytest.org/en/2.7.3/plugins.html







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 18:22

























answered Nov 21 '18 at 18:00









SilentGuySilentGuy

1004




1004













  • If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

    – Liyang Chen
    Nov 22 '18 at 1:09





















  • If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

    – Liyang Chen
    Nov 22 '18 at 1:09



















If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

– Liyang Chen
Nov 22 '18 at 1:09







If I remove the import from pkg_a/conftest.py, the fixture is not executed for the pkg_a. If I remove the import from both package, the fixture is not executed at all. No setting up and tearing down is printed. What I want is the setting up appears at the very beginning and tearing down at the very end only once.

– Liyang Chen
Nov 22 '18 at 1:09




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415697%2fpytest-prevent-imported-auto-used-session-fixture-from-executing-multiple-times%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

RAC Tourist Trophy