Opened 16 years ago
Closed 16 years ago
#7694 closed (invalid)
Models that are imported into tests.py (and utilize signals) result in parallel tests that break test cases
Reported by: | Dave Naffziger | Owned by: | nobody |
---|---|---|---|
Component: | Testing framework | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In a sample models.py file:
def MyModel(models.Model): """ >>> u=User.objects.create_user('test2','te...@test.com') >>> u.email='new' >>> u.save() """ anyfield = models.BooleanField() COUNT = 0 def user_pre_save(sender, instance, signal, *args, **kwargs): global COUNT r = random.randint(1,50) print 'pre_save: count: %s random: %s' %(COUNT, r) COUNT +=1 dispatcher.connect(user_pre_save, signal=signals.pre_save, sender=User)
Then create a tests.py and add this import (that's all you need):
from myproject.models import MyModel
Here is what the test output looks like. Note that it looks like we're creating two duplicate threads each with their own state (COUNT doesn't increment between the runs of user_pre_save, but random is different.
pre_save: count: 0 random: 49 pre_save: count: 0 random: 23 ... Failed example: u=User.objects.create_user('test2','te...@test.com') Expected nothing Got: pre_save: count: 1 random: 13 pre_save: count: 1 random: 2 ... Failed example: u.save() Expected nothing Got: pre_save: count: 2 random: 18 pre_save: count: 2 random: 49
I've not been able to figure out what is causing this.
Note:
See TracTickets
for help on using tickets.
What you're seeing is the result of the signal handler getting installed twice. This is due to a quirk of Python's model importer; if one file has "from foo.bar import whiz", and a second file has "from bar import whiz", the whiz module will be imported and processed twice, as long as the PYTHONPATH supports finding both locations.
In this case, I'm guessing that two locations are settings.INSTALLED_APPS and tests.py differ - one has the full project path, but the other only has the application name in the import. As a result, the module is getting imported twice, and the signal is getting installed twice. If you modify the import paths to be consistent, the problem will go away.