0

I'm trying to run tests with fixture data, and getting the infamous IntegrityError: column user_id is not unique error.

Now, looking at my fixtures, I can see that the ids of my User models in my fixture are unique between each other. I infer that the clash is with existing data in (non-test) database. Is this correct? (Edit: This appears to be incorrect - see below)

I want to be able to control exactly what data are available to my tests. Is there a way to prevent the django testrunner from loading data from my live database, as well as my fixture data? (Edit: Yes - see Thibaut's answer).

Edit: Switching to using a clean, in memory database, as per Thibaut's answer does not fix the problem. Accordingly, I infer that my existing dev database is not the problem.

So, I have a third question: How do I diagnose the cause of an IntegrityError when loading fixtures during testing? (And, how do I fix it?)

Edit 2: The solution for my problem, in addition to starting with a clean database (per Thibault J) was also to eliminate models from installed apps referring to User, until the error no longer occurs.

DrTyrsa's other suggestion (than looking at the data), was to use natural keys, which for User would no doubt have required a certain amount of monkey-patching or other hackery (edit the code for User?).

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • 1
    It's not the problem of your `User` model, it's a problem of some other model that uses `ForeignKey` to `User`. – DrTyrsa Dec 07 '11 at 10:17
  • @DrTyrsa: I suspect that you're right (see my update in a moment). Would you care to expand on how to diagnose/fix this? – Marcin Dec 07 '11 at 10:36
  • 1
    It's difficult to answer without seeing your fixtures and models. The thing that definetely will solve the problem is [natural keys](https://docs.djangoproject.com/en/dev/topics/serialization/#natural-keys). But it will take some time to implement that. Another option is to create objects with a lot of relations in `setUp` method, but it won't be very helpful if you a have a lot of them. Or you can just examine your fixtures carefully and find what causes the error. – DrTyrsa Dec 07 '11 at 10:56
  • @DrTyrsa: I would be grateful for any hints towards a structured or intelligent approach to examining my fixtures carefully. – Marcin Dec 07 '11 at 11:04
  • What about posting them here? And models.py. – DrTyrsa Dec 07 '11 at 11:05
  • @DrTyrsa: They're pretty big. I'm updating my question to reflect your suggestions, though. – Marcin Dec 07 '11 at 11:12
  • 1
    You can always delete some parts of them from the end of file. When there is no exception you've just deleted code that causes the problem, Ctrl-Z and examine it. – DrTyrsa Dec 07 '11 at 11:16

1 Answers1

0

Use a different database for prod and tests (good practice). In settings.py :

if 'test' in sys.argv:                                                          
    try:                                                                        
        from test_settings import *                                             
    except ImportError:                                                         
        pass

In test_settings.py:

DATABASES = {                                                                   
    'default': {                                                                
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'memory://testdb',
    }                                                                           
}
Thibault J
  • 4,336
  • 33
  • 44
  • Thanks - this works (`Creating test database for alias 'default' (':memory:')...`), although it isn't resolving my problem. (For pedantry's sake, I should add that your first snippet should probably be placed at the end of settings.py). – Marcin Dec 07 '11 at 10:35