问题
I'm using Django 1.2.3-3+squeeze1 on Debian squeeze with PostgreSQL 8.4.7-0squeeze2 (though I don't think PostgreSQL is relevant here), and running Django unit tests based on unittest with the following setUp and tearDown
def setUp(self):
print "running setup"
self.c = Client()
self.user = User.objects.create_user('faheem', 'faheem@email.unc.edu', 'foo')
self.logged_in = self.c.login(username='faheem', password='foo')
settings.MEDIA_ROOT='/tmp/'
#settings.ZIP_UPLOAD='/var/tmp/zip/'
def tearDown(self):
print "running teardown"
FolderUpload.objects.all().delete()
FileUpload.objects.all().delete()
ZipFileUpload.objects.all().delete()
OldFileUpload.objects.all().delete()
# FIXME: Quick & dirty fix for the time being. Should make this a delete method.
os.system("rm -rf "+ settings.ZIP_UPLOAD + "/*")
The idea is for everything to be removed from the database between running unit tests. According to the unittest documentation,
that is what tearDown
is for. The problem I am having is that there still seems to be some state saved between the different unit tests.
Specifically, I'm seeing that the ids get incremented. So lets say if I create one ZipFileUpload
object in test1
, and then create one ZipFileUpload
object in test2
, then I would expect both ids to be 1
, but what I see is that is id 1
for test1
and id 2
fortest2
. This would make sense if the ids come from some index which lives outside these tables. I don't know enough about how Diango does this to know if that is in fact the case. If they are doing it this way, I have no idea why. Any clarification on this point would be appreciated.
Regardless, I would settle for a clean way to drop the database, if anyone can suggest one. This method should probably go into teadDown
. Testing Django applications mentions the following function, but I failed to import it from django.test.utils
. Confusingly, this function seems to be in django/db/backends/creation.py
.
destroy_test_db(old_database_name, verbosity=1)
Destroys the database whose name is in stored in NAME in the DATABASES, and sets NAME to use the provided name.
The first part of this sentence is Ok - "Destroy the database whose name is stored in NAME in the DATABASES",
but what is meant by "sets NAME to use the provided name" mean? I assume the provided name is old_database_name
,
It is not clear what NAME
is in the context. Is it the NAME
in DATABASES
, and if so,
why do I need to set something that is already set?
I assume the provided name is old_database_name
,
but if so, why would I want to set it to an argument called old_database_name
?
This sentence is unchanged in development docs.
EDIT:
After a reply from Steve Mayne (see below), I thought I would elaborate on the background of this a little bit.
This application was originally written over 2007/2008/2009, including the unit tests. During most of that time, I was using pre 1.0 releases of Django. According to Ken Cochran's Django Release History, 1.0 was released on September 3rd, 2008. The setup described worked fine during that time. I see that the tearDown function above was originally written in December 2007. So, perhaps Django's behavior changed?
In hindsight, I realise that emptying the tables, as tearDown
does above, does not guarantee that the id count will be reset to 1
, since the sequence can be a separate object from the table.
Thanks to Steve for his solution. If it exists, I'd like to hear about a portable solution to the sequence reset. I'd also be interested in an explanation of how to make the destroy_test_db
function above work.
回答1:
You can reset the ID sequence on each table using the following SQL:
SELECT pg_catalog.setval(pg_get_serial_sequence('table_name', 'id'), 1);
You should only do this if your table is empty.
来源:https://stackoverflow.com/questions/6249936/django-object-ids-increment-between-unit-tests