Scope controls how often a fixture gets called.
The default is “function”.
Here are the options for scope:
scope | When setup and teardown run |
---|---|
function | (default) Setup before each function, teardown after each function |
class | Setup before first test of class, teardown after last test of class |
module | Setup/Teardown bracketing tests of a module |
package | Setup/Teardown bracketing tests of a package/directory |
session | Setup/Teardown at the beginning and end of the entire test session / test run |
Since the default scope is “function”, the cheese db example will open and close the db for every test.
Here’s the fixture again:
@pytest.fixture()
def cheese_db(request):
# setup
print('\n[setup] cheese_db, connect to db')
# code to connect to your db
makeshift_cheese_db = {'Brie': 'No.', 'Camenbert': 'Ah! We have Camenbert, yessir.'}
# return db to test code
return makeshift_cheese_db
# return db to test code
yield makeshift_cheese_db
# teardown
print('\n[teardown] cheese_db, disconnect to db')
When run, we can see the setup/teardown once per function:
(cheese) $ pytest test_cheese.py -s
================== test session starts ==================
collected 3 items
test_cheese.py
[setup] cheese_db, connect to db
in test_brie()
.
[teardown] cheese_db, disconnect to db
[setup] cheese_db, connect to db
in test_camenbert()
.
[teardown] cheese_db, disconnect to db
=================== 3 passed in 0.04s ===================
This doesn’t really make sense. Especially if connecting is a time consuming operation.
Let’s change the scope to “module” so we only connect/disconnect from the db once per test file/module:
@pytest.fixture(scope="module")
def cheese_db(request):
...
And let’s re-run it:
$ pytest test_cheese.py -s
================== test session starts ==================
collected 3 items
test_cheese.py
[setup] cheese_db, connect to db
in test_brie()
.in test_camenbert()
.
[teardown] cheese_db, disconnect to db
=================== 3 passed in 0.04s ===================
There. Much better. The db is connected before it’s needed, and closed when we’re done with it.
This post is part of a series on pytest fixtures
- pytest fixtures nuts and bolts
- pytest xunit-style fixtures
- Basic pytest fixtures example
- Using pytest fixtures by naming them
- Using pytest autouse fixtures
- Using pytest fixtures with mark.usefixtures
- pytest fixture return value
- pytest fixture teardown
- pytest fixture scope - this post
- Parametrizing pytest fixtures with param
- Using multiple pytest fixtures
- Modularity: pytest fixtures using other fixtures
- pytest session scoped fixtures
- Mixing pytest fixture scope)