Testing Pyramid Web Apps with pytest
I recently took another look at pytest and liked what I saw. Previously, I had used it to try it out and couldn't see much advantage over nose or the Python standard library unittest module (the Python 2.7+ version, that is). Several features of recent versions of pytest changed my mind, but chief among them is fixtures as function arguments. In fact, I think that and other features make pytest the most Pythonic of current crop of testing frameworks. But that's a subject for another post...
In this post I'm going to focus on how to use pytest to test a Pyramid web app. Let's start with a trival Pyramid view function that simply returns a dict that will be used to render a template:
@view_config(route='hello', renderer='hello.mako') def my_view(request): return {'greeting': 'Hello world!'}
and an equally trivial unit test for that view function:
def test_my_view(): from views import my_view response = my_view(request) assert response['greeting'] == 'Hello world!'
As written, that test will error out with a syntax error because 'request' is undefined. We'll deal with that by setting up a pytest fixture to provide us with pyramid.testing.DummyRequest instance:
from pyramid import testing import pytest @pytest.fixture def pyramid_req(): return testing.DummyRequest() def test_my_view(pyramid_req): from views import my_view response = my_view(pyramid_req) assert response['greeting'] == 'Hello world!'
Easy! Each test function that uses pyramid_req as an argument gets a fresh pyramid.testing.DummyRequest instance to work with. Note that pytest has its own concept of a "request" to allow test fixtures to interact with the requesting text context and that effectively makes request a reserved argument name, so we distinguish the Pyramid request by calling our test fixture function pyramid_req.
Also note the things that we didn't have to do:
- Our test function is just that - a plain function, not a method of a class that subclasses unittest.TestCase.
- There are no setUp or tearDown functions for methods.
- The test assertion is a simple Python assert statement, not a special method or function call like assertEqual.
If we change our test assertion so that the test will fail:
... assert response['greeting'] == 'Hello Jupiter!'
and run the test suite, we get