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.

Change History (1)

comment:1 by Russell Keith-Magee, 16 years ago

Resolution: invalid
Status: newclosed

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.

Note: See TracTickets for help on using tickets.
Back to Top