Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to elegantly specify fixture usage at the test module level in pytest? #4

Open
justdoit0823 opened this issue Jul 26, 2017 · 0 comments

Comments

@justdoit0823
Copy link
Contributor

justdoit0823 commented Jul 26, 2017

With pytest test framework, we may define a module scope server fixture in conftest.py as the following:

import pytest
from pytest_localserver.http import WSGIServer


def app(environ, start_response):
    """A simple WSGI application"""
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return [environ['PATH_INFO'].encode()]


@pytest.fixture(scope='module')
def testserver():
    """Define the test WSGI server."""
    server = WSGIServer(host='127.0.0.1', port=8031, application=app)
    server.start()
    yield server
    server.stop()

and writing cases to test the server behaviour in another Python module.

Here are some different ways to write such test cases.

  • The simplest version (test_request_a.py)
import requests

url = 'http://127.0.0.1:8031'


class TestFooGroup:

    def test_foo_a(self, testserver):
        res = requests.get(url + '/foo/a')
        assert res.content.decode() == '/foo/a'

    def test_foo_b(self, testserver):
        res = requests.get(url + '/foo/b')
        assert res.content.decode() == '/foo/b'


class TestBarGroup:

    def test_bar_a(self, testserver):
        res = requests.get(url + '/bar/a')
        assert res.content.decode() == '/bar/a'

    def test_bar_b(self, testserver):
        res = requests.get(url + '/bar/b')
        assert res.content.decode() == '/bar/b'

Run command pytest test_request_a.py to start test.

  • pytest.ini version (test_request_b.py)
import requests

url = 'http://127.0.0.1:8031'


class TestFooGroup:

    def test_foo_a(self):
        res = requests.get(url + '/foo/a')
        assert res.content.decode() == '/foo/a'

    def test_foo_b(self):
        res = requests.get(url + '/foo/b')
        assert res.content.decode() == '/foo/b'


class TestBarGroup:

    def test_bar_a(self):
        res = requests.get(url + '/bar/a')
        assert res.content.decode() == '/bar/a'

    def test_bar_b(self):
        res = requests.get(url + '/bar/b')
        assert res.content.decode() == '/bar/b'

Except the above code, we nedd a pytest configuration file pytest.ini to run the test.

[pytest]

usefixtures = testserver

We can include all fixtures require by project here.

  • module level test function (test_request_c.py)
import requests

url = 'http://127.0.0.1:8031'


def test_server(testserver):
    pass


class TestFooGroup:

    def test_foo_a(self):
        res = requests.get(url + '/foo/a')
        assert res.content.decode() == '/foo/a'

    def test_foo_b(self):
        res = requests.get(url + '/foo/b')
        assert res.content.decode() == '/foo/b'


class TestBarGroup:

    def test_bar_a(self):
        res = requests.get(url + '/bar/a')
        assert res.content.decode() == '/bar/a'

    def test_bar_b(self):
        res = requests.get(url + '/bar/b')
        assert res.content.decode() == '/bar/b'

In this way, we can write a module level test function to touch the testserver fixture.

  • pytestmark variable return from pytest.mark.usefixtures (test_request_d.py)
import pytest
import requests

url = 'http://127.0.0.1:8031'
pytestmark = pytest.mark.usefixtures('testserver')


class TestFooGroup:

    def test_foo_a(self):
        res = requests.get(url + '/foo/a')
        assert res.content.decode() == '/foo/a'

    def test_foo_b(self):
        res = requests.get(url + '/foo/b')
        assert res.content.decode() == '/foo/b'


class TestBarGroup:

    def test_bar_a(self):
        res = requests.get(url + '/bar/a')
        assert res.content.decode() == '/bar/a'

    def test_bar_b(self):
        res = requests.get(url + '/bar/b')
        assert res.content.decode() == '/bar/b'

With usefixtures function, we can specify a module level fixture.

You can get the detail at pytest document using-fixtures-from-classes-modules-or-projects

In my opinion, when we don't refer fixture variable in test method, version d is the most elegant, version c is next.

What's your opinion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant