Saturday, September 28, 2013

Manual test succeeds but automated test fails - SQLite3 problem?

Hello all,

I'm developing my first standalone Django app and have run into a confounding scenario.  My app code executes without problem when tested manually but fails when tested automatedly using django.test.TestCase.

Both test setups are nearly identical.  Both are configured to use SQLite for the db.  Both use nearly identical test classes to instantiate the abstract class.  Both use identical settings specific to the app.

My app is structured as two model classes: One is an abstract class for uploaded images and the other optionally generates an object based on the image of the first class.  (See code below)

Both classes use overridden save functions.  The UploadedImage class must call save twice, first to save off the uploaded image path so it's available to the generated object and lastly to update attributes specific to the associated object when the associated object is created.  The second save is where the problem occurs in the automated tests.  (See traceback below)

The automated tests throw 'IntegrityError: PRIMARY KEY must be unique' when the associated object is created. The exception occurs when save is called on the UploadedIMage class a second time.

Reading the stack trace, it appears that SQLite insists on doing a db insert instead of an update(!) which creates a duplicate primary key and violates the uniqueness constraint.

Attempting to fix by calling 'force_update=True' or listing update fields for the second save call causes Django ORM to complain that 'update and insert cannot be called at the same time'.

Again, these exceptions only occur during automated testing.  All is peachy when the code is used manually, uploading images and creating objects using Django admin.

Anyone run into something similar.  I'm pretty burnt out on trying to debug it myself and could really use some suggestions.  Thanks.


MODEL CODE:

class MyObject(models.Model):

    class Meta:
        get_latest_by = "created"
    
    
    name = models.CharField(_("Name"), 
                            unique=True, 
                            max_length=64)
    
    slug = models.SlugField(max_length=64, 
                            unique=True, 
                            editable=False)
    
    associated_image = models.CharField(_("Associated Image Path"), 
                                        max_length=256, 
                                        editable=False)
    
    object_xml = models.CharField(_("Object XML"), 
                                    max_length=256, 
                                    editable=False)
    
    created = models.DateTimeField(_("Created"), 
                                   auto_now_add=True, 
                                   editable=False)
    
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        else:
            self.slug = self.slug
        
        if not (self.object_xml):
            #Processing code...
            ...
            <snipped>
            ...
        
        super(MyObject, self).save(*args, **kwargs)
    
    
    def __unicode__(self):
        return u'%s' % (self.name)

No comments:

Post a Comment