正确的单元测试方式Django模型没有交易错误

时间:2013-01-08 21:23:38

标签: django nose django-testing

我正在编写一些带有unique=Trueblank=False以及null=False等约束的模型。我正试图用鼻子为模型编写测试。但是,如果我写这样的测试:

from job_sites.models import Site, SiteType

@raises(IntegrityError)
def test_empty_site():
   s = Site()
   s.save()

@raises(IntegrityError)
def test_empty_site_type():
   st = SiteType()
   st.save()

我得到像这样的DatabaseError: DatabaseError: current transaction is aborted, commands ignored until end of transaction block运行第一次测试后。{/ p>

当我预料到错误时,运行DJango模型测试的正确方法是什么?

作为参考,模型如下所示:

class SiteType(models.Model):
    site_type_id = models.AutoField(primary_key=True)
    site_type = models.CharField(max_length=32, unique=True, blank=False, null=False, default=None)
    site_type_abbrev = models.CharField(max_length=32, blank=True)

    class Meta:
        db_table = u'site_types'

class Site(models.Model):
    site_id = models.AutoField(primary_key=True, blank=False, null=False, db_index=True)
    site_name = models.CharField(max_length=128, blank=False, null=False, db_index=True)
    site_type = models.ForeignKey(SiteType, blank=True, null=True)
    date_entered = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = u'sites'

我的约束和默认值如下所示:

ALTER TABLE site_types ADD CONSTRAINT site_types_site_type_name_minlen CHECK (char_length(site_type) > 0);
ALTER TABLE sites ALTER COLUMN date_entered SET DEFAULT now();
ALTER TABLE sites ADD CONSTRAINT sites_site_name_minlen CHECK (char_length(site_name) > 0);

1 个答案:

答案 0 :(得分:1)

您应该将测试创建为Django TestCase的子类,而不是使用nose的简洁测试定义。这样,您的数据库等将在运行时为您设置和配置,所有交易内容将被神奇地处理。

概述了如何为Django项目编写测试:https://docs.djangoproject.com/en/dev/topics/testing/overview/

相当于你想要做的事情看起来像:

from django.db import IntegrityError
from django.utils import unittest
from job_sites.models import Site, SiteType

class TestMyStuff(unittest.TestCase):

    def test_empty_site(self):
        s = Site()
        assertRaises(IntegrityError, s.save())

    def test_empty_site_type(self):
        st = SiteType()
        assertRaises(IntegrityError, st.save())

(免责声明:我实际上并未运行此代码,因此可能无效。)

但是,测试这种东西可能是浪费时间。这里测试的唯一逻辑是Django的内部逻辑,因此您不会通过测试来学习有关应用程序的任何内容。