Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pytest -- how do I use global / session-wide fixtures?

I want to have a "global fixture" (in pytest they could also be called "session scoped fixtures") which does some expensive environment setup, like typically preparing a resource, which is then reused across test modules. The setup is something like this,

shared_env.py

would have a fixture doing something expensive, like starting up a Docker container, MySQL server, etc.

@pytest.yield_fixture(scope="session")
def test_server():
    start_docker_container(port=TEST_PORT)
    yield TEST_PORT
    stop_docker_container()

test_a.py

would use the server,

def test_foo(test_server): ...

test_b.py

would use the same server

def test_foo(test_server): ...

It seems that pytest has support for this via scope="session", but I can't figure out how to make the actual imports work. The current setup will given an error message like,

fixture 'test_server' not found
available fixtures: pytestconfig, ...
use 'py.test --fixtures [testpath] ' for help on them
like image 989
gatoatigrado Avatar asked Nov 13 '14 00:11

gatoatigrado


People also ask

Can a pytest fixture use another fixture?

fixtures have explicit names and are activated by declaring their use from test functions, modules, classes or whole projects. fixtures are implemented in a modular manner, as each fixture name triggers a fixture function which can itself use other fixtures.

Which command can be used to show all available fixtures?

Additionally, if you wish to display a list of fixtures for each test, try the --fixtures-per-test flag.

How do I use pytest fixtures?

To access the fixture function, the tests have to mention the fixture name as input parameter. Pytest while the test is getting executed, will see the fixture name as input parameter. It then executes the fixture function and the returned value is stored to the input parameter, which can be used by the test.

What is pytest fixture scope session?

A session-scoped fixture effectively has access to all collected test items. Here is an example of a fixture function which walks all collected tests and looks if their test class defines a callme method and calls it: # content of conftest.py import pytest @pytest.


2 Answers

There is a convention in pytest which uses the special file named conftest.py and contains session fixtures.

I have extracted two very simple examples to give a quick start. They do not use classes.

Everything taken from http://pythontesting.net/framework/pytest/pytest-session-scoped-fixtures/

Example 1:

The fixture is not executed unless supplied as an argument to a test_* function. The fixture some_resource is executed prior to calling the referencing function, in this case test_2. The finalizer on the other hand is executed at the end.

conftest.py:

import pytest
@pytest.fixture(scope="session")

def some_resource(request):
  print('\nSome resource')
 
  def some_resource_fin():
    print('\nSome resource fin')

  request.addfinalizer(some_resource_fin)

test_a.py:

def test_1():
  print('\n Test 1')
 
def test_2(some_resource):
  print('\n Test 2')

def test_3():
  print('\n Test 3')

Result:

$ pytest -s
======================================================= test session starts ========================================================
platform linux -- Python 3.4.3 -- py-1.4.26 -- pytest-2.7.0
rootdir: /tmp/d2, inifile: 
collected 3 items 

test_a.py 
 Test 1
.
Some recource

 Test 2
.
 Test 3
.
Some resource fin

Example 2:

Here the fixture is configured with autouse=True, so it is executed once at the beginning of the session, and it does not have to be referenced. Its finalizer is executed at the end of the session.

conftest.py:

import pytest
@pytest.fixture(scope="session", autouse=True)

def auto_resource(request):
  print('\nSome resource')
 
  def auto_resource_fin():
    print('\nSome resource fin')

  request.addfinalizer(auto_resource_fin)

test_a.py:

def test_1():
  print('\n Test 1')
 
def test_2():
  print('\n Test 2')

def test_3():
  print('\n Test 3')

Result:

$ pytest -s
======================================================= test session starts ========================================================
platform linux -- Python 3.4.3 -- py-1.4.26 -- pytest-2.7.0
rootdir: /tmp/d2, inifile: 
collected 3 items 

test_a.py 
Some recource

 Test 1
.
 Test 2
.
 Test 3
.
Some resource fin
like image 198
4 revs, 2 users 95% Avatar answered Sep 22 '22 13:09

4 revs, 2 users 95%


Okay, I think I got it ... the solution is to name shared_env.py conftest.py

See this good blog post for details [ http://pythontesting.net/framework/pytest/pytest-session-scoped-fixtures/ ]. It has a working example, so hopefully not too hard to work backwards from there if necessary.

like image 28
gatoatigrado Avatar answered Sep 21 '22 13:09

gatoatigrado