Skip to content

py.test doesn't reimport changed modules #762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pytestbot opened this issue Jun 2, 2015 · 7 comments
Closed

py.test doesn't reimport changed modules #762

pytestbot opened this issue Jun 2, 2015 · 7 comments
Labels
type: bug problem that needs to be addressed

Comments

@pytestbot
Copy link
Contributor

Originally reported by: BitBucket: caryoscelus, GitHub: caryoscelus


Test case:

#!python

#module.py
def fail():
    raise Exception('fail')
#!python

#test_a.py
import module

def do_nothing():
    pass

module.fail = do_nothing

def test_nofail():
    module.fail()
#!python

#test_b.py
import module
import pytest

def test_fail():
    with pytest.raises(Exception):
        module.fail()

pytest test_b.py runs fine, but just pytest fails


@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


I'm just guessing that module.fail raises an error.

Pytest doesn't try to reimport modules before executing test cases; all modules are collected during startup before the first test is even executed, so this is certainly not a bug and is working as intended.

If you post more details of what you are trying to accomplish (instead of how) we might be able to help you better.

@pytestbot
Copy link
Contributor Author

Original comment by BitBucket: caryoscelus, GitHub: caryoscelus:


I'm just guessing that module.fail raises an error.

#!

test_a.py .
test_b.py F

===================================================================== FAILURES ======================================================================
_____________________________________________________________________ test_fail _____________________________________________________________________

    def test_fail():
        with pytest.raises(Exception):
>           module.fail()
E           Failed: DID NOT RAISE

test_b.py:6: Failed

this is certainly not a bug and is working as intended

Passing tests when there should be fail (reverting example above gives exactly this) is working as intended? Well, that's kinda surprising.

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


Global changes will carry over from one module to the next; pytest (and any other testing framework AFAIK) does not attempt to restore global state between each test.

You should take care to restore any global state changed during each test run, and pytest's fixtures are a great way to accomplish that. For your example specifically, you could use monkeypatch to change module.fail just for that one test:

#test_a.py
import module

def do_nothing():
    pass

def test_nofail(monkeypatch):
    monkeypatch.setattr(module, 'fail', do_nothing)
    module.fail()

monkeypatch will ensure to restore module.fail to its previous state after the test ends.

@pytestbot
Copy link
Contributor Author

Original comment by BitBucket: caryoscelus, GitHub: caryoscelus:


With more real-world examples (e.g. test_a.py doesn't change module directly, but through other module import) using monkeypatch (or other explicit methods) won't help simply because the fail would not be recognized in the first place.

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


It doesn't matter if the global state is changed by test_a itself or by some other function which is called by test_nofail, monkeypatch would still work fine. There's a section about this in the mock's documentation which applies for monkeypatch as well.

Please keep in mind that changing global state during import is usually a bad idea, and as I mentioned before you will encounter this problem with any other testing framework, not just pytest.

@pytestbot
Copy link
Contributor Author

Original comment by BitBucket: caryoscelus, GitHub: caryoscelus:


It does matter if the module changing global state is third-party. You can propose whatever good solution there is, but as long as it requires something to do locally, it won't help. Let me illustrate this with example, if that's not clear enough for you:

#!python

# test_a.py
import module
import third_party_global_state_changing_module
#!python

#test_b.py
import module
def test_module():
    # should fail, but doesn't
    module.do_something_unsupported_implemented_in_third_party_module()

End-user won't be able to find the fail without running pytest test_b.py manually.

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


You are correct, that will be a problem, but that's why it is not a good idea to change global state during import. :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

1 participant