Writing tests

Functional tests

tddspry provides NoseTestCase class to base functional testing.

class tddspry.NoseTestCase

For convenience this class consist of all functions exists in nose.tools module.

So, if you have functions, like this:

def addititon(first, second):
    return first + second

def division(first, second):
    if not second:
        raise ValueError
    return first / second

def multiplication(first, second):
    return first * second

def subtraction(first, second):
    return first - second

You can write simple TestFunctions class to test its:

from tddspry import NoseTestCase


class TestFunctions(NoseTestCase):

    def test_addition(self):
        self.assert_equal(addititon(1, 2), 3)
        self.assert_not_equal(addititon(1, 2), 2)

    def test_division(self):
        self.assert_equal(division(4, 2), 2)
        self.assert_not_equal(division(5.0, 2), 2)
        self.assert_raises(ValueError, division, 2, 0)

    def test_multiplication(self):
        self.assert_equal(multiplication(1, 2), 2)
        self.assert_not_equal(multiplication(1, 2), 3)

    def test_subtraction(self):
        self.assert_equal(subtraction(2, 1), 1)
        self.assert_equal(subtraction(2, 1), 2)
classmethod assert_almost_equal(first, second, places=7, msg=None)

Fail if the two objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit).

classmethod assert_almost_equals(first, second, places=7, msg=None)

Fail if the two objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit).

classmethod assert_equal(first, second, msg=None)
Fail if the two objects are unequal as determined by the ‘==’ operator.
classmethod assert_equals(first, second, msg=None)
Fail if the two objects are unequal as determined by the ‘==’ operator.
classmethod assert_false(expr, msg=None)
Fail the test if the expression is true.
classmethod assert_not_almost_equal(first, second, places=7, msg=None)

Fail if the two objects are equal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit).

classmethod assert_not_almost_equals(first, second, places=7, msg=None)

Fail if the two objects are equal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero.

Note that decimal places (from zero) are usually not the same as significant digits (measured from the most signficant digit).

classmethod assert_not_equal(first, second, msg=None)
Fail if the two objects are equal as determined by the ‘==’ operator.
classmethod assert_not_equals(first, second, msg=None)
Fail if the two objects are equal as determined by the ‘==’ operator.
classmethod assert_raises(excClass, callableObj, *args, **kwargs)
Fail unless an exception of class excClass is thrown by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is thrown, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception.
classmethod assert_true(expr, msg=None)
Fail the test unless the expression is true.
static eq_(a, b, msg=None)
Shorthand for ‘assert a == b, “%r != %r” % (a, b)
static make_decorator(func)
Wraps a test decorator so as to properly replicate metadata of the decorated function, including nose’s additional stuff (namely, setup and teardown).
static ok_(expr, msg=None)
Shorthand for assert. Saves 3 whole characters!
static raises(*exceptions)

Test must raise one of expected exceptions to pass.

Example use:

@raises(TypeError, ValueError)
def test_raises_type_error():
    raise TypeError("This test passes")

@raises(Exception):
def test_that_fails_by_passing():
    pass

If you want to test many assertions about exceptions in a single test, you may want to use assert_raises instead.

static set_trace()
Call pdb.set_trace in the calling frame, first restoring sys.stdout to the real output stream. Note that sys.stdout is NOT reset to whatever it was before the call once pdb is done!
static timed(limit)

Test must finish within specified time limit to pass.

Example use:

@timed(.1)
def test_that_fails():
    time.sleep(.2)
static with_setup(setup=None, teardown=None)

Decorator to add setup and/or teardown methods to a test function:

@with_setup(setup, teardown)
def test_something():
    # ...

Note that with_setup is useful only for test functions, not for test methods or inside of TestCase subclasses.

Django related tests

tddspry.django provides DatabaseTestCase and HttpTestCase classes to testing Django applications.

Database tests with DatabaseTestCase

For testing Django model classes and anything objects that needed database connection you should be used tddspry.django.DatabaseTestCase. This test-case inherits tddspry.TestCase, so consists of all nose tools functions and decorators.

At setup DatabaseTestCase creates test database or flushes it if needed and loading fixtures if possible (database_name, database_flush and fixtures attributes).

Also for convenience DatabaseTestCase has additional helpers:

class tddspry.django.DatabaseTestCase
assert_count(model, number)

Helper counts all model objects and assert_equals it with given number.

Also you can to put number argument as tuple and list and assert_count checks all of its values.

assert_create(model, **kwargs)

Helper tries to create new instance of model class with given **kwargs and checks that instance really created.

assert_create returns created instance.

assert_delete(instance)
Helper tries to delete instance and checks that it correctly deleted.
assert_read(model, **kwargs)

Helper tries to filter model instances by **kwargs lookup.

assert_read returns QuerySet with filtered instances or simple instance if resulted QuerySet count is 1.

assert_update(instance, **kwargs)

Helper tries to update given instance with **kwargs and checks that all of **kwargs values was correctly saved to instance.

assert_update returns updated instance.

Note: Also DatabaseTestCase can call additional helper by helper method. See below how use it.

Usage

So, for testing CRUD of django.contrib.auth.models.Group model you can write next test case:

from tddspry.django import DatabaseTestCase

from django.contrib.auth.models import Group


NEW_NAME = 'Super-Test Group'
TEST_NAME = 'Test Group'


class TestGroup(DatabaseTestCase):

    def test_create(self):
        self.assert_create(Group, name=TEST_NAME)

    def test_delete(self):
        group = self.assert_create(Group, name=TEST_NAME)
        self.assert_delete(group)

    def test_read(self):
        self.assert_create(Group, name=TEST_NAME)
        self.assert_read(Group, name=TEST_NAME)

    def test_update(self):
        group = self.assert_create(Group, name=TEST_NAME)
        self.assert_update(group, name=NEW_NAME)

Server-side tests with HttpTestCase

In addition to tddspry.django.DatabaseTestCase tddspry.django provides tddspry.django.HttpTestCase class to testing HTTP responses with Twill browser and django.test.Client.

At setup HttpTestCase run Django WSGI server and connects it with twill browser.

For historical reasons HttpTestCase was developed for testing Django applications with Twill browser, so its consists of all functions exists in twill.commands module as class methods.

And for convenience several twill methods was simplifying and rewriting, there are:

class tddspry.django.HttpTestCase
find(what, flags='', flat=False)

Twill used regexp for searching content on web-page. Use flat=True to search content on web-page by standart Python what in html expression.

If this expression was not True (was not found on page) it’s raises TwillAssertionError as in twill.commands.find method.

go(url, args=None, kwargs=None)

Twill needs to set full URL of web-page to loading. This helper auto-prepends SITE value if needed.

You can also give urlpattern name and function tries to reverse it to real URL.

notfind(what, flags='', flat=False)

Twill used regexp for searching content on web-page. Use flat=True to search content on web-page by standart Python not what in html expression.

If this expression was not True (was found on page) it’s raises TwillAssertionError as in twill.commands.notfind method.

url(url, args=None, kwargs=None)
Assert that current URL matches the given regexp.

And from Release 0.3 of tddspry HttpTestCase consist of client attribute that stores instance of django.test.Client class.

Also, HttpTestCase provides next methods:

class tddspry.django.HttpTestCase
build_url(url, args=None, kwargs=None, prepend=False)
Helper reverses url if possible and auto-prepends SITE to it if prepend=True.
disable_edit_hidden_fields()

Disable editing hidden fields (<input type="hidden" ... />) by Twill browser (as by default in twill).

To enable use HttpTestCase.enable_edit_hidden_fields method.

disable_redirect()

Disable auto-redirects in Twill tests.

To enable use HttpTestCase.enable_redirect method.

enable_edit_hidden_fields(flag=True)

Enable editing hidden fields (<input type="hidden" ... />) by Twill browser.

To disable use HttpTestCase.disable_edit_hidden_fields method.

enable_redirect(flag=True)

Enable auto-redirects in Twill tests (as by default in twill).

To disable use HttpTestCase.disable_redirect method.

go200(url, args=None, kwargs=None, check_links=False)
Go to url and check that response code is 200.
login(username, password, url=None, formid=None)
Login to Django using username and password.
login_to_admin(username, password)
Login to Django admin CRUD using username and password.
logout(url=None)
Logout from current Django session.
submit200(submit_button=None, url=None, check_links=False)
Submit form and checks that response code is 200.

Usage

So, for testing login/logout process in your project you can write next test-case:

from tddspry.django import HttpTestCase

from django.conf import settings


class TestLoginPage(HttpTestCase):

    def test_login(self):
        user = self.helper('create_user', 'username', 'password')
        self.login('username', 'password')
        self.url(settings.LOGIN_REDIRECT_URL)

    def test_logout(self):
        user = self.helper('create_user', 'username', 'password')
        self.login('username', 'password')
        self.logout()
        self.url('/')

Additional helpers

DatabaseTestCase and HttpTestCase can call additional helpers by helper(name, *args, **kwargs) method. Now tddspry.django.helpers provides:

tddspry.django.helpers.create_profile(obj, user, klass, **kwargs)
Create profile for given user.
tddspry.django.helpers.create_staff(obj, username=None, password=None, email=None, raw=False)
Create Django user with staff rights.
tddspry.django.helpers.create_superuser(obj, username=None, password=None, email=None, raw=False)
Create Django user with superuser and staff rights.
tddspry.django.helpers.create_user(obj, username=None, password=None, email=None, active=True, staff=False, superuser=False, raw=False)
Create Django user with given names or with default if absent.
tddspry.django.helpers.registration(obj, username=None, email=None, password=None, verbosity=False, registration_url='registration_register', registration_formid=1, registration_tos=False, activate_word='activate', activation_url='registration_activate', login_url='auth_login', login_formid=1)

Register new user, activate it and login. Registers new user, activates it and tries to log in. Helper covers all registration process provided by django-registration.

Usage

For create new non-active user in test case use next snippet:

from tddspry.django import DatabaseTestCase


class TestNonActiveUser(DatabaseTestCase):

    def test_active(self):
        user = self.helper('create_user', active=False)
        self.assert_false(user.is_active)

Also you can to access any additional helper function or var directly by helpers attribute. For example, to access default values for username, password and email user fields use next snippet:

from tddspry.django import DatabaseTestCase


class TestHelpersVars(DatabaseTestCase):

    def test_default_values(self):
        user = self.helper('create_user', raw=True)
        self.assert_equal(user.username, self.helpers.USERNAME)
        self.assert_equal(user.password, self.helpers.PASSWORD)
        self.assert_equal(user.email, self.helpers.EMAIL)

Note: You don’t need to send obj argument to additional helper via helper method. But if you want to call additional helper directly you must send DatabaseTestCase or HttpTestCase object as first argument.

Table Of Contents

Previous topic

Testing with tddspry

Next topic

Running tests

This Page