I am trying to run my tests in parallel using manage.py test --parallel. By default this will use a different DB for each thread.
Each process gets its own database
Is it possible to only use one? Also is it a bad practice and why?
Don't think it's possible to do this without overwritting of Django TestRunner.
Separate database increase isolation of your tests. This help to prevent appearence of flucky tests.
Related
I am making some integration tests for an app, testing routes that modify the database. So far, I have added some code to my tests to delete all the changes I have made to the DB because I don't want to change it, but it adds a lot of work and doesn't sounds right. I then thought about copying the database, testing, deleting the database in my testing script. The problem with that is that it is too long to do. Is there a method for doing that ?
I see two possible ways to solve your problem:
In-memory database e.g. (h2)
Database in docker container.
Both approaches solve your problem, you can just shutdown db/container and run it again, db will be clean in that case and you don't have to care about it. Just run new one. However there are some peculiarities:
In-memory is easier to implement and use, but it may have problems with dialects, e.g. some oracle sql commands are not available for H2. And eventually you are running your tests on different DB
Docker container with db is harder to plugin into your build and tests, but it doesn't have embeded DB problems with dialects and DB in docker is the same as your real one.
You can start a database transaction at the beginning of a test and then roll it back. See the following post for details:
https://lostechies.com/jimmybogard/2012/10/18/isolating-database-data-in-integration-tests/
I have a Django (v1.4, using Postgresql) project which I've written a bunch of working unittests for. These use FactoryBoy to generate most of their data.
I'm now starting to write some integration tests using LiveServerTestCase with Selenium. I've just realised that my tests and the live test server use different databases. Which means that data created by factories in my tests aren't available to Selenium.
I'm not sure of the best way to progress. I think I could use fixtures to supply data that would work, although this is a pain having got this far using factories instead.
Is there a way I can continue to use factories to generate data that will work for my Selenium tests? Really I'd like my tests and LiveServerTestCase to use the same database.
I found out why this happened to me, and some possible workarounds, including Ilya Baryshev's answer above.
If your test descends from Django's TestCase, and if your database supports transactions, then each test runs in its own transaction, and nobody outside (no other thread, external process, or other test) can see the objects created in the database by your test.
LiveServerTestCase uses threads, so it would suffer from this problem. So the designers made it inherit from TransactionTestCase instead of TestCase, which disables these transactions, so that changes are globally visible.
What happened to me was that I added some mixins to my test class, and one of them pulled in TestCase. This doesn't cause an error, but it silently replaces the base class of LiveServerTestCase with TestCase, which enables transactions again, causing the problem that you describe.
Ilya's SQLite memory database workaround works because Django contains code that detects when using a SQLite :memory: database that actually shares the same connection between threads, so you see your test's objects in the LiveServerThread because they're inside the same transaction. However this comes with some caveats:
It’s important to prevent simultaneous database queries via this shared connection by the two threads, as that may sometimes randomly cause the tests to fail. So you need to ensure that the two threads don’t access the database at the same time. In particular, this means that in some cases (for example, just after clicking a link or submitting a form), you might need to check that a response is received by Selenium and that the next page is loaded before proceeding with further test execution. Do this, for example, by making Selenium wait until the HTML tag is found in the response (requires Selenium > 2.13)...
https://docs.djangoproject.com/en/1.4/topics/testing/#live-test-server
In my case, once we identifier that autocommit was being turned off when the test started, and tracked down why (because we had entered TestCase code that we shouldn't have done), we were able to fix the inheritance hierarchy to avoid pulling in TestCase, and then the same database was visible from both the live server thread and the test.
This also works with Postgres databases, so it would provide a solution for velotron.
Have you tried using sqlite as your database backend for tests?
When using an in-memory SQLite database to run the tests, the same
database connection will be shared by two threads in parallel: the
thread in which the live server is run and the thread in which the
test case is run.
from Django docs
If you're not using anything beyond regular ORM, you might benefit from test speedups as well.
We are using Redisco for our models, and I am writing some tests for our models, however redis keeps filling up, so for each test, more data is added to reddis.
Is there a way to clear Redis for each test, and what are the best practices when testing (using redis and redisco)
- EDIT -
This is the solution I went with in the end, and I want to share this with others who might have the same question
To make sure each test case is running on a clean Redis instance, start each test case by running
redis = Redis()
redis.flushall()
As people have commented below, make sure you don't run the tests against a production instance of Redis
I would recommend running a second redis instance for testing (eg. on a different port...) so you are also not able to accidentally drop any production data from your redis when running tests.
You could then use custom BaseTestClass which overrides your project's settings (in the setUp method - you can also emtpy your redis' dbs there) so that they point to another redis instance (hopefully you've defined your redis connections in your project's settings) and have all your test classes inherit from this base class.
The standard way of dealing with side-effects such as connecting to a database in unit tests is to provide a mock implementation of the data layer during the test. This can be done in many ways, you could use a different redis instance, or dynamically override methods to report to your test rather than actually manipulating the database etc.
Dependancy Injection is a pattern used for this kind of problem, more often in static languages like Java, but there are tools for Python, see http://code.google.com/p/snake-guice/
Some of my requirements are these:
Create a in-memory sqlite3 database.
Read a list, and pull those data from
production database.
Perform unit tests
Remain the test database.
Perform some intelligent UI tests using the same test database.
I am not a pro in test, but these have to achieved, anyone professional who can suggest a best practice in this area?
Thanks very much for your help!
New in Django 1.8
The --keepdb option can be used to preserve the test database between test runs
https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-option---keepdb
You can run:
./manage.py testserver
Your test database will be created, all your tests are run and afterwards the server keeps running, so you can do your ui testing.
hope this helps,
Anton
Persistent Database Test Runner adds a new command called quicktest that will retain the database after the test is run, and use the same when run again.
Running Django unit tests is far too slow. Especially when I just want to run one test but the test runner wants to create the entire database and destroy the whole thing just for that one test.
In the case where I have not changed any of my models, I could save oodles of time if Django would not bother trying to create and destroy the entire database, and instead saved it for next time. Better yet, it would be great if the test runner was capable of being able to see which models have changed and only replacing those prior to running tests.
I'd prefer to not have to subclass the test runner myself, but that's what I'm going to have to do if I don't find a solution soon. is there anything like this already in existence?
In django1.8 added new parameter for manage.py test command --keepdb
./manage.py test --keepdb
Have you tried using an in-memory SQLite database for tests? It's much faster than using a disk-based database.
I'm using Djang-nose. If you set a env var REUSE_DB=1 it will not destroy the DB after running tests and re-use that same DB for the next run. Whenever your schema changes, just set REUSE_DB=0 and do one 'full' run. After that reset it to 1 and you're good to go.
https://github.com/django-nose/django-nose