@@ -12,81 +12,83 @@ I'm pretty lazy when it comes to writing tests for existing code, however, I'm
12
12
even lazier when it comes to repetitive manual testing action.
13
13
14
14
This package aims at de-duplicating the data import tests from
15
- django-representatives and django-representatives-votes which is to be re-used
16
- in django-cities-light.
15
+ django-representatives and django-representatives-votes which is re-used in
16
+ django-cities-light.
17
17
18
18
Database state assertion
19
19
========================
20
20
21
21
A nice way to test a data import script is to create a source data fixture with
22
22
a subset of data, ie. with only 10 cities instead of 28K or only 3 european
23
23
parliament representatives instead of 3600, feed the import function with that
24
- and then compare the database state with a django fixture. For example:
24
+ and then compare the database state with a django fixture. This looks like what
25
+ I was used to do:
25
26
26
27
- use such a command to create a small data extract
27
28
`shuf -n3 cities15000.txt > cities_light/tests/cities_test_fixture.txt `,
28
29
- use it against the import script on a clean database,
29
30
- verify the database manually, and run
30
31
`django-admin dumpdata --indent=4 cities_light > cities_light/tests/cities_test_expected.txt `
31
- - then, make a test case that calls the import script against the fixture and
32
- call test_light's function to assert that the database contains only the
33
- expected data .
32
+ - then, make a test case that calls the import script against the fixture,
33
+ - write and maintain some funny (fuzzy ?) repetitive test code to ensure that
34
+ the database is in the expected state .
34
35
35
36
When a bug is fixed, just add the case to the fixture and repeat the process to
36
37
create new expected data dumps, use coverage to ensure no case is missed.
37
38
38
- Predictible serialization
39
- =========================
39
+ With django-dbdiff, I just need to maintain to initial data extract, and test
40
+ it with ``Fixture.assertNoDiff('appname/path/to/fixture',
41
+ models=[YourModelToTest]) `` in a ``django.test.TransactionTestCase `` which has
42
+ ``reset_sequences=True ``:
40
43
41
- It is important to use serializers which dump data in a predictible way because
42
- this app relies on diff between an expected - user-generated and versioned -
43
- fixture and dumped database data.
44
-
45
- Django's default model-to-dict logic - implemented in
46
- django.core.serializers.python.Serializer.get_dump_object() - returns a dict,
47
- this app registers a slightly modified version of the default json serializer
48
- which returns OrderedDicts instead.
49
-
50
- In addition, dbdiff serialization forces Decimal normalization, because
51
- trailing zeros could happen in inconsistent ways.
52
-
53
- Cross-database fixture compatibility
54
- ====================================
55
-
56
- MySQL doesn't have microseconds in datetimes, so dbdiff's serializer removes
57
- microseconds from datetimes so that fixtures are cross-database compatible
58
- which make them usable for cross-database testing.
44
+ - if the fixture in question doesn't exist, it'll be automatically created on
45
+ with dumpdata for the concerned models on the first run, raising
46
+ "FixtureCreated" exception to fail the test and inform of the path of the
47
+ created fixture, so that it doesn't mislead the user in thinking the test
48
+ passed with an existing fixture,
49
+ - if the fixture exists, it'll run dumpdata on the models concerned and GNU
50
+ diff it against the fixture, if there's any output it'll be raised in the
51
+ "DiffFound" exception, failing the test and printing the diff.
59
52
60
53
Usage
61
54
=====
62
55
63
- MySQL, SQLite and PostgreSQL, Python 2.7 and 3.4 are supported along with
64
- Django 1.7 to 1.10 - it's always better to support django's master so that we
65
- can upgrade easily when it is released.
56
+ Example::
66
57
67
- Install ``django-dbdiff `` with pip and add ``dbdiff `` to ``INSTALLED_APPS ``.
58
+ from django import TransactionTestCase
59
+ from dbdiff.fixture import Fixture
68
60
69
- When ``dbdiff `` is installed, ``dumpdata `` will use its serializers which have
70
- predictible output and cross-database support, so fixtures dumped without
71
- ``dbdiff `` installed will have to be regenerated after ``dbdiff `` is installed.
72
61
73
- Example::
62
+ class YourImportTest(test.TransactionTestCase):
63
+ reset_sequences = True
64
+
65
+ def test_your_import(self):
66
+ your_import()
74
67
75
- from dbdiff import dbdiff
68
+ Fixture('yourapp/tests/yourtest.json',
69
+ models=[YourModel]).assertNoDiff()
76
70
77
- your_import_function()
78
- assert not dbdiff.diff('your_app/tests/some_fixture.json')
71
+ The first time, it will raise a ``FixtureCreated `` exception, and the test will
72
+ fail. This is to inform the user that the test didn't really run. On the next
73
+ run though, it will pass.
79
74
80
75
If any difference is found between the database and the test fixture, then
81
76
``diff() `` will return the diff as outputed by GNU diff.
82
77
83
- A context manager that will raise an exception if a diff is found is also
84
- provided, it's able to delete models and reset the PK sequences for them::
78
+ See tests and docstrings for crunchy details.
85
79
86
- with dbdiff.exact('your_app/fixture.json'):
87
- # do stuff
80
+ Requirements
81
+ ============
88
82
89
- More public API tests can be found in dbidff/tests/test_dbdiff.py.
83
+ MySQL, SQLite and PostgreSQL, Python 2.7 and 3.4 are supported along with
84
+ Django 1.7 to 1.10 - it's always better to support django's master so that we
85
+ can **upgrade easily when it is released **, which is one of the selling points
86
+ for having 100% coverage.
87
+
88
+ Install
89
+ =======
90
+
91
+ Install ``django-dbdiff `` with pip and add ``dbdiff `` to ``INSTALLED_APPS ``.
90
92
91
93
Django model observer
92
94
=====================
0 commit comments