During the development of Tandem Exchange, I wanted to write some test routines to check the validity of the core search functions that figure out which of the users would be good matches for one another as language tandem partners.
There are a number of ways to do this, Django’s built-in unit test infrastructure is a bit limited in that it attempts to create and drop a new database each time, to let the test have an independent and clean database in which to work. But this isn’t something that’s possible with most shared webhosters, for obvious reasons, so the Django unit test infrastructure is less than useful in these cases.
But you don’t really need to create/drop databases all the time. In my case, the schema stays the same throughout, all I want to do is add and remove users on the non-production database and check that the search functions work.
Here’s how I am planning to do it, via the unittest.TestCase setUp() and tearDown() methods:
users_before = User.objects.values_list('id', flat=True).order_by('id')
[2, 8221, 8222, 8732, 8734, 8735, 8750, 8758, 8760, 8777, 8780, 8791]
users_after = User.objects.values_list('id', flat=True).order_by('id')
[2, 8221, 8222, 8732, 8734, 8735, 8750, 8758, 8760, 8777, 8780, 8791, 8805]
users_to_remove = list(set(users_before) - set(users_after))
Then all you need to do for any particular unit test is to remove those users created in the duration. This isn’t something you can use in a production database, since there will be a natural race condition between the setUp() and tearDown() calls. But this should work just fine in a non-production environment, where no one’s signing up while you’re running tests.
Update: Here’s what the unittest.TestCase code looked like, in the end. Note that you must evaluate the QuerySet expression immediately in setUp() and tearDown() as failure to do so causes them to both be lazily-evaluated at the users_to_remove assignment, which gives you an empty set.
# Before performing any tests, record the existing
# user IDs:
# 1. So we know which users we created during the test
# 2. So we can remove just those fake users.
# Get the list of all users before the tests.
# Must evaluate the QuerySet or it will be lazily-evaluated later, which is wrong.
self.users_before = list(User.objects.values_list('id', flat=True).order_by('id'))
# Get the list of all users after the tests.
users_after = list(User.objects.values_list('id', flat=True).order_by('id'))
# Calculate the set difference.
users_to_remove = sorted(list(set(users_after) - set(self.users_before)))
# Delete that difference from the database.