question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Test fixtures with scope set to session

See original GitHub issue

I am using pytest-sanic to test my sanic application, which communicates with a database layer running in a docker container and I am having difficulty achieving the following test setup:

Expected Setup

  1. Spawn one database container for the entire test suite
  2. Setup the database and tables inside the container required by the app
  3. yield a session scoped fixture to the app
  4. Run tests
  5. Perform teardown.

Sample Code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Configuration for testing fixtures
"""
try:
    import pytest
    import docker
    from app import app as test_app
    from utilities.database_setup import create_databases, create_tables
except Exception as e:
    raise e

@pytest.yield_fixture
def app():
    yield test_app

@pytest.fixture
def test_cli(loop, app, test_client):
    return loop.run_until_complete(test_client(app))

@pytest.fixture(scope="session", autouse=True)
async def database_setup():
    """ Setup DB Layer for the App """
    print('Setting up pytest session!')
    client = docker.from_env()
    assert client.ping() is True, "Unable to connect to docker."
    print('spawning db container...')
    container = client.containers.run(
        image='redis:latest',
        ports={6380:  6380},
        detach=True
    )
    print('db container running...')
    print('Container ID: {}'.format(container.id))
    db_host = "localhost"
    db_port =  6380
    print('setting up databases...')
    await create_databases(db_host, db_port)
    print('setting up tables...')
    await create_tables(db_host, db_port)
    yield
    print("stopping db container")
    container.kill()

Error

ScopeMismatch: 
You tried to access the 'function' scoped fixture 'loop' with a 'session' scoped request object, involved factories

Alternatives

I am also open to using other alternatives to achieve this test setup since I am not tied to this approach.

Any help or suggestions will be greatly appreciated.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
shinybrarcommented, May 2, 2019

I fixed the issue, by starting the database + app configurations through docker-compose.

0reactions
jackey8616commented, Mar 10, 2019

I’m not sure this would help you or not. Long days ago I faced same issue as you. I want to make the test running under just one instance, so I use module scope. And the solution I found is to make everything be module scope.

Here is my conftest.py check it out.

import pytest
import asyncio
from pytest_sanic.utils import TestClient

from sanic import Sanic
from app import index
from stage import add_route as stage_add_route


@pytest.yield_fixture(scope='module')
def app():
    app = Sanic()
    app.add_route(index, '/', methods=['GET'])
    stage_add_route(app)
    yield app


@pytest.fixture(scope='module')
def loop():
    # Reference from pytest_sanic.plugin#loop to give a new scope.
    loop = asyncio.get_event_loop()
    yield loop


@pytest.fixture(scope='module')
def test_client(loop):
    # Reference from pytest_sanic.plugin#test_client to give a new scope.
    clients = []

    async def create_client(app, **kwargs):
        client = TestClient(app, loop=loop, **kwargs)
        await client.start_server()
        clients.append(client)
        return client

    yield create_client

    if clients:
        for client in clients:
            loop.run_until_complete(client.close())


@pytest.fixture(scope='module')
def test_cli(loop, app, test_client):
yield loop.run_until_complete(test_client(app))

Also, since test_client is deprecated, so just change to sanic_client and do the same thing.

Regards.

Read more comments on GitHub >

github_iconTop Results From Across the Web

pytest fixtures: explicit, modular, scalable
Fixtures are created when first requested by a test, and are destroyed based on their scope : function : the default scope, the...
Read more >
Understand 5 Scopes of Pytest Fixtures | by Xiaoxu Gao
Pytest fixtures have five different scopes: function, class, module, package, and session. The scope basically controls how often each fixture will be executed....
Read more >
pytest -- how do I use global / session-wide fixtures?
1 Answer 1 ; import · @pytest.fixture(scope="session") def some_resource( ; def test_1 · print · '\n Test 1') ; import · @pytest.fixture(scope="session ......
Read more >
Specifying Fixture Scope - Python Testing with pytest [Book]
Fixtures include an optional parameter called scope, which controls how often a fixture gets set up and torn down. The scope parameter to...
Read more >
pytest session scoped fixtures | pythontest - Brian Okken
In pytest fixtures nuts and bolts, I noted that you can specify session scope so that a fixture will only run once per...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found