You've written some unit tests for your Python app. Good for you! There are dozens of us, dozens!You don't always remember to run your tests, or worse, your colleagues don't always remember to run them.
Run tests in a module. Pytest testmod.py. Run tests in a directory. Pytest testing/ Run tests by keyword expressions. Pytest -k 'MyClass and not method' This will run tests which contain names that match the given string expression, which can include Python operators that use filenames, class names and function names as variables. I had to delete existing Python unittest run configurations for the tests I was trying to run before I could run them as Django tests. I did not need to set any environment variables.
Wouldn't it be nice to automatically run unit tests on every commit to GitHub? What about on every pull request?You can do this with GitHub Actions.You'd be able to hunt down commits that broke the build, and if you're feeling blamey, who broke the build.Sounds complicated, but it's not.Sounds like it might cost money, but the free version has ~30 hours of execution per month.Let me show you how to set this up.
There is example code for this blog post here.
Setting up your project
I'm going to assume that:
- You have some Python code
- You use Git, and your code is already in a GitHub repository
If you're already running unit tests locally you can skip this section.Otherwise, your Python project's folder looks something like this:
If you don't have tests already, I recommend trying pytest (and adding it to your requirements.txt).
You'll need at least one test
You'll want to make sure your tests run and pass locally
Set up your Action
You'll need to create new a file in a new folder: .github/workflows/ci.yml
.You can learn more about these config files here.Here's an example file:
Now your project looks like this:
Commit your changes, push it up to GitHub and watch your tests run!
Sometimes they fail:
Sometimes they pass:
Add a badge to your README
You can add a 'badge' to your project's README.md.Assuming your project was hosted at https://github.com/MyName/my-project/, you can add thisto your README.md file:
Next steps
Write some tests, run them locally, and then let GitHub run them for you on every commit from now on.If you get stuck, check out this minimal reference or the Actions docs.
Latest versionReleased:
Test django schema and data migrations, including ordering
Project description
Features
- Allows to test
django
schema and data migrations - Allows to test both forward and rollback migrations
- Allows to test the migrations order
- Allows to test migration names
- Fully typed with annotations and checked with
mypy
, PEP561 compatible - Easy to start: has lots of docs, tests, and tutorials
Read the announcing post.See real-world usage example.
Installation
We support several django
versions:
1.11
2.2
3.0
3.1
Other versions might work too, but they are not officially supported.
Testing django migrations
Testing migrations is not a frequent thing in django
land.But, sometimes it is totally required. When?
When we do complex schema or data changesand what to be sure that existing data won't be corrupted.We might also want to be sure that all migrations can be safely rolled back.And as a final touch we want to be sure that migrationsare in the correct order and have correct dependencies.
Testing forward migrations
To test all migrations we have a Migrator
class.
It has three methods to work with:
.apply_initial_migration()
which takes app and migration names to generatea state before the actual migration happens. It creates thebefore state
by applying all migrations up to and including the ones passed as an argument..apply_tested_migration()
which takes app and migration names to perform theactual migration.reset()
to clean everything up after we are done with testing
So, here's an example:
That was an example of a forward migration.
Backward migration
The thing is that you can also test backward migrations.Nothing really changes except migration names that you pass and your logic:
Testing migrations ordering
Sometimes we also want to be sure that our migrations are in the correct order.And all our dependecies = [...]
are correct.
To achieve that we have plan.py
module.
That's how it can be used:
Django Test Client
This way you can be sure that migrationsand apps that depend on each other will be executed in the correct order.
Test framework integrations 🐍
We support several test frameworks as first-class citizens.That's a testing tool after all!
Run Django Tests For Learning
Note that the Django post_migrate
signal's receiver list is cleared atthe start of tests and restored afterwards. If you need to test yourown post_migrate
signals then attach/remove them during a test.
pytest
We ship django-test-migrations
with a pytest
pluginthat provides two convinient fixtures:
migrator_factory
that gives you an opportunityto createMigrator
classes for any databasemigrator
instance for the'default'
database
That's how it can be used:
unittest
We also ship an integration with the built-in unittest
framework.
Here's how it can be used:
Choosing only migrations tests
In CI systems it is important to get instant feedback. Running tests thatapply database migration can slow down tests execution, so it is often a goodidea to run standard, fast, regular unit tests without migrations in parallelwith slower migrations tests.
pytest
django_test_migrations
adds migration_test
marker to each test usingmigrator_factory
or migrator
fixture.To run only migrations test, use -m
option:
unittest

django_test_migrations
adds migration_test
tagto every MigratorTestCase
subclass.To run only migrations tests, use --tag
option:
Django Checks
django_test_migrations
comes with 2 groups of Django's checks for:

- detecting migrations scripts automatically generated names
- validating some subset of database settings
Testing migration names
django
generates migration names for you when you run makemigrations
.And these names are bad (read more about why it is bad)!Just look at this: 0004_auto_20191119_2125.py
What does this migration do? What changes does it have?
One can also pass --name
attribute when creating migrations, but it is easy to forget.
We offer an automated solution: django
checkthat produces an error for each badly named migration.
Add our check into your INSTALLED_APPS
:
And then in your CI run:
This way you will be safe from wrong names in your migrations.
Do you have a migrations that cannot be renamed? Add them to the ignore list:
And we won't complain about them.
Or you can completely ignore entire app:
Database configuration
Add our check to INSTALLED_APPS
:
Then just run check
management command in your CI like listed in sectionabove.
Credits
This project is based on work of other awesome people:
License
MIT.
Release historyRelease notifications | RSS feed
1.1.0
1.0.0
0.3.0
0.2.0
0.1.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size django_test_migrations-1.1.0-py3-none-any.whl (25.2 kB) | File type Wheel | Python version py3 | Upload date | Hashes |
Filename, size django-test-migrations-1.1.0.tar.gz (21.5 kB) | File type Source | Python version None | Upload date | Hashes |
Hashes for django_test_migrations-1.1.0-py3-none-any.whl
Algorithm | Hash digest |
---|---|
SHA256 | 7ea17dac1a0b0c8084681899c6563d85f4262832f2fbb0c6240b12e554333934 |
MD5 | 52e8d6d65a119e313a3f5489f5699b16 |
BLAKE2-256 | ee87170f1a51f6829cba1f5b5e864371d6ab5544b3bbff36203583ce7566ec33 |
Hashes for django-test-migrations-1.1.0.tar.gz
Algorithm | Hash digest |
---|---|
SHA256 | 27c0127552920bbdc339a84de360f1792abc8c353e2c8d2b86af92dc1ade6703 |
MD5 | 77b7acfbdceb59b9ac7090afcc71fc98 |
BLAKE2-256 | ca3e11942a8769c47035dd55e26c8404d212015dc0503057263059b1ae8ecc33 |