Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use a pytest fixture in the condition of my skipif logic?

Tags:

pytest

fixture

I am trying to use a pytest fixture (scope=module) in a class skipif decorator, but I am getting an error saying the fixture is not defined. Is this possible?

conftest.py has a fixture with module scope called 'target' that returns a CurrentTarget object. The CurrentTarget object has a function isCommandSupported. test_mytest.py has a class Test_MyTestClass that contains a dozen test functions. I want to skip all the tests in Test_MyTestClass based on if the fixture target.isCommandSupported so I decorate Test_MyTestClass with skipif like:

@pytest.mark.skipif(not target.isCommandSupprted('commandA), reason=command not supported')
class Test_MyTestClass:
...

I get this error: NameError: name 'target' is not defined

If I try:

@pytest.mark.skipif(not pytest.config.getvalue('tgt').isCommandSupprted('commandA), reason=command not supported')
class Test_MyTestClass:
...

I get this error: AttributeError: 'function' object has no attribute 'isCommandSupprted'

like image 734
Chis Williamson Avatar asked Oct 03 '13 20:10

Chis Williamson


2 Answers

The reason you get an error in the first case is that pytest injects fixtures, so they become available in your test functions via function parameters. They are never imported into higher scope.

The reason you get the AttributeError is that fixtures are functions and are evaluated at first (or each) use. So, when you get it through pytest.config it's still a function. This is the same reason the other answer will fail - if you import it, you're importing the fixture function, not it's result.

There is no direct way of doing what you want, but you can work around it with an extra fixture:

@pytest.fixture(scope='module')
def check_unsupported(target):
  if not target.isCommandSupported('commandA'):
    pytest.skip('command not supported')

@pytest.mark.usefixtures('check_unsupported')
def test_one():
  pass

def test_two(check_unsupported):
  pass
like image 75
Mayo Avatar answered Sep 30 '22 16:09

Mayo


You can import target from conftest like so:

from conftest import target

Then, you can use it in pytest.mark.skipif as you were intending in your example.

@pytest.mark.skipif(not target.isCommandSupported('commandA'), reason='command not supported')
def Test_MyTestClass:

If you needed to repeat the same pytest.mark.skipif logic across several tests and wanted to avoid copy-pasting, a simple decorator will help:

check_unsupported = pytest.mark.skipif(not target.isCommandSupported('commandA'),
                                       reason='command not supported')

@check_unsupported
def test_one():
    pass

@check_unsupported
def test_two():
    pass
like image 31
alkalinity Avatar answered Sep 30 '22 15:09

alkalinity