[pytest-dev] pytest_runtest_call hook skipped in strange manner

holger krekel holger at merlinux.eu
Wed Feb 6 14:00:49 CET 2013


Hi Anton,

pytest_runtest_call is responsible for executing the test.  An exception
will escalate, so not all plugin hook impls might execute in the case of
a failing test.

If you use @pytest.mark.tryfirst before the pytest_runtest_call you should
be able to avoid the problem - your hook will run.

HTH,
holger



On Wed, Feb 06, 2013 at 13:56 +0200, Anton P wrote:
> Sorry for confusing, but it looks like runtest_call hook defined in plugin
> is always skiped in case test is failed.
> I've tried to add there some output to file to be sure that there is no
> issue with pytest stdout capturing.
> This issue creates a problem for me. Because plugin does some stuff before
> test and try to verify that stuff is good after test finished. But if tc
> could be failed (does py.test can predict the result?!) runtest_call hook
> is skipped but runtest_teardown hook is run as usual. Therefore I get
> double error: tc failed, teardown failed.
> 
> If nobody has time to check this, than please point me where I can check
> the issue by myself. Why the hook could be skipped?
> 
> Ubuntu Linux 12.04 -- Python 2.7.3 -- pytest-2.3.4
> 
> Thank you in advance!
> -Anton
> 
> 
> On Tue, Feb 5, 2013 at 4:51 PM, Anton P <anton7811 at gmail.com> wrote:
> 
> > Hi All,
> >
> > I'm faced with very strange issue with runtest_call hook.
> > I've create plugin with such hook and it's working good unless you have
> > the following code in the test case:
> > assert env.switch[1].type == "real"
> > If you change at least on sign in this assertion (e.g. != "real" or ==
> > "unreal") the issue cannot be reproduced and hook is performed correctly.
> >
> > Could anybody explain me what is going with this test case?
> >
> > Thank you in advance!
> > -Anton
> >
> >
> > Here the code:
> >
> >
> > $ tree
> > .
> > ├── conftest.py
> > ├── pytest_fake.py
> > └── test_temp.py
> >
> > *1. conftest.py*
> > #! /usr/bin/env python
> >
> > pytest_plugins = ["pytest_fake", ]
> >
> > def pytest_runtest_call(item):
> >     print "\nconftest runtest call"
> >
> > def pytest_runtest_teardown(item, nextitem):
> >     print "\nconftest runtest teardown"
> >
> > *2. pytest_fake.py*
> > #!/usr/bin/env python
> >
> > import pytest
> >
> >
> > def pytest_addoption(parser):
> >     group = parser.getgroup("fake", "plugin fake")
> >     group.addoption("--fake", action="store_true", dest="fake",
> >                     default=False,
> >                     help="Enable fake plugin. %default by default.")
> >
> >
> > def pytest_configure(config):
> >     if config.option.fake:
> >         config.pluginmanager.register(Fake(config.option), "_fake")
> >
> >
> > def pytest_unconfigure(config):
> >     fake = getattr(config, "_fake", None)
> >     if fake:
> >         del config._fake
> >         config.pluginmanager.unregister(fake)
> >
> >
> > class Fake(object):
> >
> >     def __init__(self, opts):
> >         pass
> >
> >     @pytest.mark.trylast
> >     def pytest_runtest_call(self, item):
> >         print "runtest_call - OK"
> >
> >     @pytest.mark.tryfirst
> >     def pytest_runtest_teardown(self, item, nextitem):
> >         print "runtest_teardown"
> >
> > *3. test_temp.py*
> > #! /usr/bin/env python
> >
> > class A:
> >     pass
> >
> > class B:
> >     def __init__(self):
> >         self.switch = {}
> >         self.switch[1] = A()
> >         self.switch[1].type = "unreal"
> >
> > class TestTemp(object):
> >     def test_tmp_01(self):
> >         var = B()
> >         assert var.switch[1].type == "real"
> >
> >     def test_tmp_02(self):
> >         env1 = B()
> >         assert env1.switch[1].type != "real"
> >
> >
> >
> > *Execution log:*
> >
> > I'm expecting that message "runtest_call - OK" will appear before the
> > first case.
> >
> > $ py.test -s -v --fake test_temp.py
> > ================================================= test session starts
> > =================================================
> > platform linux2 -- Python 2.7.3 -- pytest-2.3.4 -- /usr/bin/python
> > collected 2 items
> >
> > test_temp.py:13: TestTemp.test_tmp_01
> > conftest runtest call
> > FAILEDruntest_teardown
> >
> > conftest runtest teardown
> >
> > test_temp.py:17: TestTemp.test_tmp_02
> > conftest runtest call
> > runtest_call - OK
> > PASSEDruntest_teardown
> >
> > conftest runtest teardown
> >
> >
> > ====================================================== FAILURES
> > =======================================================
> > ________________________________________________ TestTemp.test_tmp_01
> > _________________________________________________
> >
> > self = <test_temp.TestTemp object at 0x15e6f90>
> >
> >     def test_tmp_01(self):
> >         var = B()
> > >       assert var.switch[1].type == "real"
> > E       assert 'unreal' == 'real'
> > E         - unreal
> > E         ? --
> > E         + real
> >
> > self       = <test_temp.TestTemp object at 0x15e6f90>
> > var        = <test_temp.B instance at 0x16293f8>
> >
> > test_temp.py:15: AssertionError
> > =============================================== slowest test durations
> > ================================================
> > 0.00s call     test_temp.py::TestTemp::test_tmp_01
> > 0.00s setup    test_temp.py::TestTemp::test_tmp_01
> > 0.00s teardown test_temp.py::TestTemp::test_tmp_01
> > 0.00s call     test_temp.py::TestTemp::test_tmp_02
> > 0.00s setup    test_temp.py::TestTemp::test_tmp_02
> > 0.00s teardown test_temp.py::TestTemp::test_tmp_02
> > ========================================= 1 failed, 1 passed in 0.02
> > seconds ==========================================
> >
> >

> _______________________________________________
> Pytest-dev mailing list
> Pytest-dev at python.org
> http://mail.python.org/mailman/listinfo/pytest-dev



More information about the Pytest-dev mailing list