Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reset a Django test database id's after each test?

I have a django app and I am running some unit tests on it. So the problem I am having is not when one test inserts into the test db. It is the tests that come after. Since each test is not saving the transaction, the entry from a previous test is not there which is fine, although the auto increment id's are increasing as if there are still entries into the database. Which I need to fix because I am inserting more data where I cannot control the id's given to it and need to be able to grab this specific data for the test. If I hard code the code to grab the objects I will have to change the code for every time I add a new test, which is not ideal.

I have multiple tests running, but for simplicity sake, I will show two.

from django.test import TestCase
from app.models import Model

class VersionMerge(TestCase):
   fixtures = ['initial_test_data.json']

   def test_model_test1(self):
       *Insert new data*
       *grab new data in*
       *Check data*

   def test_model_test2(self):
       *Insert new data*
       *grab new data*
       *Check data*

The problem arises in test_model_test2 where when I try to grab the new data, I have to print the object out to see the id's to be able to grab it.

I have a solution on how I can fix this on the actual database but not the test one. For mine I need to be able to connect to a docker container and run a psql command to reset the table_id_seq.

docker exec -t  $CONTAINER_ID psql --dbname=test_database_name -username=user -c "SELECT setval('modelName_appName_id_seq', 2, true)"

This will go to the table and set the last id value used to be 2 to make the next id 3. However whenever I try to run the command from inside python using

cmd = "command above"
os.system(cmd)

and when I run this I get the following error.

sh: 1: docker: not found
sh: 1: docker: not found

Looking for any help on this, either a new solution to the problem or improvements on mine.

TLDR; I need to be able to modify data in the database that the django unit tests create.

like image 381
Ryan w Avatar asked Jul 24 '18 17:07

Ryan w


2 Answers

If you need a test to reset the primary key sequence, you can issue a RawSQL query doing that. How to do that exactly is answered in this StackOverflow question.

An easier option is available if you're using pytest. We're using pytest and pytest-django in all our Django projects and it makes testing a breeze. pytest-django provdes a database fixture that can take a boolean parameter to reset the sequences. Use it like so:

@pytest.mark.django_db(transaction=True, reset_sequences=True)
def mytest():
    [...]
like image 185
jnns Avatar answered Nov 03 '22 22:11

jnns


I got this to work by replacing TestCase with TransactionTestCase and set reset_sequences=True. However the tests are running slower.

from django.test import TransactionTestCase

class ViewTest(TransactionTestCase):
    reset_sequences = True

    def test_view_redirects(self):
       ...

Here's the doc

like image 30
Pooya Kamranjam Avatar answered Nov 03 '22 21:11

Pooya Kamranjam