Access fixtures from unittest.TestCase
Hello, is there a way to access a fixture object from inside a unitest.TestCase test function? As far as I understand, the way to combine fixtures and TestCase is like this: import pytest, unittest @pytest.mark.usefixtures('tmpdir') class MyTest(unittest.TestCase): def test_something(self): # XXX how can I get to ``tmpdir`` here? But there seems to be no way to get to the fixture object, which is rather constraining. Or am I missing something? Thanks for your help, Wolfgang
Hi Wolfgang, On Fri, Apr 04, 2014 at 11:21 +0200, Wolfgang Schnerring wrote:
Hello,
is there a way to access a fixture object from inside a unitest.TestCase test function? As far as I understand, the way to combine fixtures and TestCase is like this:
import pytest, unittest
@pytest.mark.usefixtures('tmpdir') class MyTest(unittest.TestCase):
def test_something(self): # XXX how can I get to ``tmpdir`` here?
But there seems to be no way to get to the fixture object, which is rather constraining. Or am I missing something?
Right, any "usefixture" needs to either have a global side effect or stick some object to "self". One easier way to get a tempdir is this: class MyTest(unittest.TestCase): @pytest.fixture(autouse=True) def set_tmpdir(self, tmpdir): self.tmpdir = tmpdir def test_something(self): # access self.tmpdir HTH, holger
Thanks for your help, Wolfgang
_______________________________________________ Pytest-dev mailing list Pytest-dev@python.org https://mail.python.org/mailman/listinfo/pytest-dev
Hello Holger, * holger krekel <holger@merlinux.eu> [2014-04-07 10:24]:
On Fri, Apr 04, 2014 at 11:21 +0200, Wolfgang Schnerring wrote:
is there a way to access a fixture object from inside a unitest.TestCase test function? Right, any "usefixture" needs to either have a global side effect or stick some object to "self". @pytest.fixture(autouse=True) def set_tmpdir(self, tmpdir): self.tmpdir = tmpdir
Thanks for the hint! Using a method of the TestCase as a wrapper fixture around the actual fixture is clever, but also a little unwieldy... would there be an easy way to introduce an API to make that easier? Wolfgang
Hi Wolfgang, On Mon, Apr 07, 2014 at 13:18 +0200, Wolfgang Schnerring wrote:
Hello Holger,
* holger krekel <holger@merlinux.eu> [2014-04-07 10:24]:
On Fri, Apr 04, 2014 at 11:21 +0200, Wolfgang Schnerring wrote:
is there a way to access a fixture object from inside a unitest.TestCase test function? Right, any "usefixture" needs to either have a global side effect or stick some object to "self". @pytest.fixture(autouse=True) def set_tmpdir(self, tmpdir): self.tmpdir = tmpdir
Thanks for the hint! Using a method of the TestCase as a wrapper fixture around the actual fixture is clever, but also a little unwieldy... would there be an easy way to introduce an API to make that easier?
Thing is that trying to bring pytest fixtures to unittest.TestCase's methods directly is very hard, especially given the many extensions/subclasses that people use. If unittest had a plugin system that would help. do you have to inherit unittest.TestCase, btw? If you don't, all problems go away :) best, holger
Wolfgang
_______________________________________________ Pytest-dev mailing list Pytest-dev@python.org https://mail.python.org/mailman/listinfo/pytest-dev
Hello,
Thanks for the hint! Using a method of the TestCase as a wrapper fixture around the actual fixture is clever, but also a little unwieldy... would there be an easy way to introduce an API to make that easier?
Thing is that trying to bring pytest fixtures to unittest.TestCase's methods directly is very hard, especially given the many extensions/subclasses that people use.
Yeah, I can see how that might be a rather annoying proposition. On the other hand... I'm not too familiar with the pytest internals (yet? ;), so this might be totally crazy, but would it be feasible to have an API like pytest.get_fixture('myfixturename') to retrieve the fixture object? Or is there no such kind of registry and they are all handled local to the test function?
do you have to inherit unittest.TestCase, btw? If you don't, all problems go away :)
Yes I do; my use case is migrating projects with large test suites (several thousand test functions across dozens of packages) from unittest/zope.testrunner to pytest. Thus, we need mechanisms that work gradually, since anything that requires us to change something /everywhere/ is a non-starter. We've already got fancy tooling[1] that converts zope.testrunner-style "layers"[2] to pytest fixtures, but as you noted above, some test infrastructure is hidden away in TestCase base classes. So, even if I start a new package that uses pytest/fixtures from the ground up (as I did last week ;), I still need to integrate with some older packages, and their TestCases. But I guess I can work with the workaround you gave (using a TestCase method as a fixture to wrap the actual fixture), while refactoring stuff piecemeal to provide test infrastructure in a testframework-independent way (you know, being testframework-indepent really isn't a use-case usually...) Thanks again, Wolfgang [1] https://pypi.python.org/pypi/gocept.pytestlayer [2] https://pypi.python.org/pypi/plone.testing#layers
Hi Wolfgang, On Tue, Apr 08, 2014 at 08:20 +0200, Wolfgang Schnerring wrote:
Hello,
Thanks for the hint! Using a method of the TestCase as a wrapper fixture around the actual fixture is clever, but also a little unwieldy... would there be an easy way to introduce an API to make that easier?
Thing is that trying to bring pytest fixtures to unittest.TestCase's methods directly is very hard, especially given the many extensions/subclasses that people use.
Yeah, I can see how that might be a rather annoying proposition.
On the other hand... I'm not too familiar with the pytest internals (yet? ;), so this might be totally crazy, but would it be feasible to have an API like pytest.get_fixture('myfixturename') to retrieve the fixture object? Or is there no such kind of registry and they are all handled local to the test function?
A global "pytest.get_fixture()" would be hard to get right, i am afraid. Indeed, all fixtures are local to test functions. pytest.get_fixture would need to be a function that works on a per-test basis, i.e. get changed (or it's context changed) for each test. You could probably write a local plugin that provides it. Basically setting item.getfuncargvalue as pytest.get_fixture in a pytest_runtest_setup hook. Parametrization wouldn't work with it for sure.
do you have to inherit unittest.TestCase, btw? If you don't, all problems go away :)
Yes I do; my use case is migrating projects with large test suites (several thousand test functions across dozens of packages) from unittest/zope.testrunner to pytest. Thus, we need mechanisms that work gradually, since anything that requires us to change something /everywhere/ is a non-starter.
We've already got fancy tooling[1] that converts zope.testrunner-style "layers"[2] to pytest fixtures, but as you noted above, some test infrastructure is hidden away in TestCase base classes. So, even if I start a new package that uses pytest/fixtures from the ground up (as I did last week ;), I still need to integrate with some older packages, and their TestCases.
Thanks for explaining, makes sense.
But I guess I can work with the workaround you gave (using a TestCase method as a fixture to wrap the actual fixture), while refactoring stuff piecemeal to provide test infrastructure in a testframework-independent way (you know, being testframework-indepent really isn't a use-case usually...)
Yes, incremental refactoring like this is a good strategy. cheers and good luck, holger
Thanks again, Wolfgang
[1] https://pypi.python.org/pypi/gocept.pytestlayer [2] https://pypi.python.org/pypi/plone.testing#layers
_______________________________________________ Pytest-dev mailing list Pytest-dev@python.org https://mail.python.org/mailman/listinfo/pytest-dev
participants (2)
-
holger krekel -
Wolfgang Schnerring