django-nose
django-jasmine
class MyTestCase(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Tests that work for only a certain version of the library.
pass
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_windows_support(self):
# windows specific testing code
pass
expectedFailure decoratorclass ExpectedFailureTestCase(unittest.TestCase):
@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
@override_settings(ALLOW_COMMENTS=True)
def test_comments_allowed(self):
# ...
https://github.com/carljm/django-testing-slides/blob/master/settings/30_good.md
from django.utils.unittest import TestCase
import mock
cursor_wrapper = mock.Mock()
cursor_wrapper.side_effect = RuntimeError("No touching the database!")
@mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper)
class NoDBTestCase(TestCase):
"""Will blow up if you database."""
https://github.com/carljm/django-testing-slides/blob/master/models/30_no_database.md
import unittest
class FormTests(unittest.TestCase):
def test_validation(self):
form_data = {
'name': 'X' * 300,
}
form = ContactForm(data=form_data)
self.assertFalse(form.is_valid())
Eventbrite just released a library on GitHub called rebar – https://github.com/eventbrite/rebarfrom rebar.testing import flatten_to_dict
form_data = flatten_to_dict(ContactForm())
form_data.update({
'name': 'X' * 300,
})
form = ContactForm(data=form_data)
assert(not form.is_valid())
ModelFormclass ModelFormTests(unittest.TestCase):
def test_validation(self):
form_data = {
'name': 'Test Name',
}
form = ContactForm(data=form_data)
self.assert_(form.is_valid())
self.assertEqual(form.instance.name, 'Test Name')
form.save()
self.assertEqual(
Contact.objects.get(id=form.instance.id).name,
'Test Name'
)
FormSetfrom rebar.testing import flatten_to_dict, empty_form_data
formset = ContactFormSet()
form_data = flatten_to_dict(formset)
form_data.update(
empty_form_data(formset, len(formset))
)
Modeldef test_that_spam_posts_are_hidden(self):
post = Post(mark_post_as_spam=True)
discussion = Discussion(posts=[post])
assert discussion.visible_posts == []
class MyTransactionTestCase(TransactionTestCase):
fixtures = ['some_fixture.json',]
@patch.object(SomeObjectInsideTransaction, 'some_method')
def test_disable_transaction(self, some_method):
some_method.side_effect = IOError("Unexpected exception")
try:
self.client.get('/your/view/url/')
except IOError:
pass
# assertions here
You have to use TransactionTestCase:
Django TestCase classes make use of database transaction facilities, if available, to speed up the process of resetting the database to a known state at the beginning of each test. A consequence of this, however, is that the effects of transaction commit and rollback cannot be tested by a Django TestCase class. If your test requires testing of such transactional behavior, you should use a Django TransactionTestCase.
import sys, random
def chaos_trace(frame, event, arg):
if event == 'line' and random.random() < 0.000001:
raise MemoryError()
return chaos_trace
sys.settrace(chaos_trace)
You will get some lovely random failures injected into your code. A great way to find bugs, and make sure your reasoning is sound in the face of CHAOS!
mock = Mock(name='bar', return_value='fish')
mock(1, 2, spam = 99)
# 'fish'
mock.assert_called_once_with(1, 2, spam = 99)
mock.called
# True
mock.call_count
# 1
mock.call_args
# ((1, 2), {'spam': 99})
From: http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-testing-with-mock-4899484mock = MagicMock()
mock[5]
# <mock.Mock object at 0x2f90690>
mock.__str__.return_value = 'bzzzz'
str(mock)
# 'bzzzz'
mock = Mock(side_effect=KeyError('boom'))
mock()
# Traceback (most recent call last)
# ....
# KeyError: 'boom'
>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
... mock_open.return_value = MagicMock(spec=file)
...
... with open('/some/path', 'w') as f:
... f.write('something')
...
>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')
http://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth
from mock import Mock, MagicMock
class SomeTestCase(TestCase):
def testRawPostData(self):
...
request = Mock(spec=request)
request.raw_post_data = 'myrawdata'
print request.raw_post_data # prints 'myrawdata'
file_mock = MagicMock(spec=file)
file_mock.read.return_value = 'myfiledata'
request.FILES = {'myfile': file_mock}
print request.FILES['myfile'].read() # prints 'myfiledata'
outstream = StringIO()
with patch('sys.stdout', new=outstream) as out:
...
actual_out = out.getvalue()
import unittest
def setUpModule():
print 'Module setup...'
def tearDownModule():
print 'Module teardown...'
class Test(unittest.TestCase):
def setUp(self):
print 'Class setup...'
def tearDown(self):
print 'Class teardown...'
def test_one(self):
print 'One'
def test_two(self):
print 'Two'
from autofixture import AutoFixture
fixture = AutoFixture(Entry)
entries = fixture.create(10)
django-test-utils
./manage.py makefixture proposals.Proposal[:10] --indent=4 > proposal_with_related_items.json
factory_boy - A test fixtures replacement for Python based on thoughtbot's factory_girl for Ruby
import factory
from models import User
class UserFactory(factory.Factory):
FACTORY_FOR = User
first_name = 'John'
last_name = 'Doe'
admin = False
# Returns a User instance that's not saved
user = UserFactory.build()
# Returns a saved User instance
user = UserFactory.create()
# Returns a dict of attributes that can be used to build a User instance
attributes = UserFactory.attributes()
# Returns an object with all defined attributes stubbed out:
stub = UserFactory.stub()
rebar - Rebar makes your Forms stronger
from rebar.testing import flatten_to_dict
form_data = flatten_to_dict(ContactForm())
form_data.update({
'name': 'X' * 300,
})
form = ContactForm(data=form_data)
assert(not form.is_valid())
The same for formsets
from rebar.testing import flatten_to_dict, empty_form_data
formset = ContactFormSet()
form_data = flatten_to_dict(formset)
form_data.update(
empty_form_data(formset, len(formset))
)