Testing

We all know that all software should be extensively tested, but who has time for it? ;)

Testing views (pytest only)

Ideally your views should be minimalistic and require very little testing. Boogie automates simple tests that simply request a view without any complex validation of the response.

Depending on the complexity of your frontend and/or how the view functions are organized, those automated tests barely scratch the surface. Either way, the test classes in this module are a good starting point for more comprehensive tests for the views of your application.

Web Crawler

Perhaps the most convenient test class in this module is the CrawlerTester. You just override a few parameters in the sub-class and it will start crawling pages in your web site looking for broken links and invalid responses.

# test_urls.py
import pytest
from boogie.testing.pytest import CrawlerTester


class TestPublicUrls(CrawlerTester):
    ... # TODO


# Now we repeat the same tests, but with a different user fixture.
class TestUserUrls(TestPublicUrls):
    must_visit = ('/profile/', '/account/logout/')

    @pytest.fixture
    def user(self, db):
        return factories.make_user()

Explicit

Sometimes it is necessary to offer a more fine-grained control of the URLs that should be visited. Web crawling based tests can be very slow and are hard to isolate. They are a nice when doing “integration tests”, but are really poor to cover specific apps or functions.

UrlTester provides a more fine grained option for testing the URLs of an specific app.

# test_urls.py
from boogie.testing.pytest import UrlTester


class TestUrls(UrlTester):
    ... # TODO

API Reference

Testing models

# TODO

Fixtures

Boogie integrates both Factory Boy and Model Mommy projects. While there is a lot of overlap between both projects, there are some unique features of each project that complement the other.

Currently, the only public API is the factory() function:

# on factories.py
# Notice we do not have to specify default values even for required fields.
# ModelMommy fills those entries with random data.
user = factory(User)
admin = factory(User, is_superuser=True, is_staff=True)

# on tests.py
from .factories import *

# We use factory.create(**optional_kwargs) to create new instances.
# Use .build() instead of .create() to preventing saving on the db.
def test_user_can_edit_blog(user, admin, db):
    assert not user.create().can_edit_blog()
    assert not admin.create().can_edit_blog()

API Reference

boogie.testing.factories.factory(model, **kwargs)[source]

Creates a factory boy factory class

Mocks

Mocks are very useful in tests. A prevalent use of mocks can greatly reduce unnecessary trips to the database which can be very costly and usually is the major factor in making test suites of web-based apps slow.

You may want to optimize even further by recognizing that unittest.mock Mocks are really slow compared to more lightweight Python objects. Boogie provides very lightweight Mock classes and context managers that helps saving a few CPU cycles.

API Reference

class boogie.testing.mock.LightMock(*args, **kwargs)[source]

A lightweight Mock class.

It creates attributes and methods on-demand.

>>> x = LightMock()
>>> x.foo.bar(42)                                      # doctests: +ELLIPSIS
<LightMock ...>
boogie.testing.mock.mock_save(model, method=<class 'boogie.testing.mock.LightMock'>)[source]

Context manager that mocks the .save() method of a model to prevent it from hitting the database.

Usage:
with mock_save(model):
    model.name = "Hello"
    model.save()  # it does not actually touch the db
boogie.testing.mock.assume_unique(form=None)[source]

Context manager that suppress checks of uniqueness during model validation.

Usage:
with assume_unique(model):
    model.slug = "repeated-slug"
    model.full_clean()  # prevents touching the db on uniqueness checks
boogie.testing.mock.raise_exception(exception)[source]

Return a function that raises the given exception when called.

Boogie Client

Boogie implements a Django Client subclass that adds a few extra methods that can be useful in testing and on interactive environments such as Jupyter notebooks.

The boogie client can be accessed as a fixture from the boogie.testing.pytest module. There are a few different flavors:

client:
Standard client for a anonymous user.
user_client:
Client logged in as “user”.
admin_client:
Client logged in as “admin/superuser”.
author_client:
Client logged in as “author”. Author is the owner of some resource.

API Reference

boogie.testing.client.Client

alias of boogie.testing.mock.

Debug

Boogie special module boogie.debug implements a few functions that helps with debugging code. This module uses lots of dirty hacks and non-standard practices and should never be enabled in a production environments. It is, however, very convenient to track bugs and other forms of exploration.

API Reference

boogie.debug.info()[source]

Display detailed information about object.

boogie.debug.embed()[source]
boogie.debug.set_trace()[source]
boogie.debug.enable_debugging(auto=False)[source]

Register debugging function to builtins.