如何在生产数据库上运行Django单元测试?
我最近开始学习测试驱动开发(TDD),正在为我的Django应用写单元测试。我知道可以使用数据快照(fixtures),这是测试执行的标准方法,但有些测试需要在整个数据库上运行,而对于一个有超过1000万行数据的数据库,使用JSON格式的数据快照我实在不想去处理。而且,这个测试是“只读”的。
所以,我想问问大家,你们是怎么设置测试套件,让它们在生产数据库上运行的?我想这可能很简单,只要在某个测试的setUp方法中添加DATABASE_NAME的设置就行了。但是,当我把settings.DATABASE_NAME设置为"prod_db"时,运行测试时却出现了"NameError: global name 'settings' is not defined"的错误。而且,Django的一个问题描述中提到过,意外删除生产数据库的风险,链接在这里:http://code.djangoproject.com/ticket/11987。
那么,如何才能做到这一点?或者说,更好的是,最好的做法是什么,能让一个测试在生产数据库上运行,而不是在临时数据库上?
提前感谢大家的意见!
5 个回答
这个测试运行器适用于Django 1.3版本。
from django.test.simple import DjangoTestSuiteRunner as TestRunner
class DjangoTestSuiteRunner(TestRunner):
def setup_databases(self, **kwargs):
pass
def teardown_databases(self, old_config, **kwargs):
pass
如果有人在网上搜索解决某个问题,这里有一个关于如何在Django生产数据库上进行单元测试的基本框架。你可以查看Django文档中的相关部分,了解文件和目录的结构,以及代码应该放在哪里。代码应该放在 yourapp/management/commands/newcommandname.py
这个位置,同时,management和commands文件夹里也需要有空的 __init__.py
文件,这样Python才能把它们当作有效的模块。
你可以通过以下命令来运行测试套件:
$python manage.py newcommandname
接下来是你应该放在 yourapp/management/commands/newcommandname.py
中的代码:
from django.core.management.base import BaseCommand
import unittest
class Command(BaseCommand):
help = """
If you need Arguments, please check other modules in
django/core/management/commands.
"""
def handle(self, **options):
suite = unittest.TestLoader().loadTestsFromTestCase(TestChronology)
unittest.TextTestRunner().run(suite)
class TestChronology(unittest.TestCase):
def setUp(self):
print "Write your pre-test prerequisites here"
def test_equality(self):
"""
Tests that 1 + 1 always equals 2.
"""
from core.models import Yourmodel
self.failUnlessEqual(1 + 1, 2)
首先,如果你是在生产数据库上运行这个,那就不算真正的“单元”测试了。
这其实是一个重要的批处理任务,需要像对待正式的生产批处理任务一样来处理。
你不能用Django的test
命令来查看生产数据。这个命令总是会创建一个空的数据库,然后从测试用例中的数据填充进去。
你可以把处理生产数据库的过程做成一个合适的管理命令。这样环境就会配置好,你的命令可以直接使用Django的ORM来处理数据。
另一种方法是确保你配置好你的设置。你可以使用DJANGO_SETTINGS_MODULE
这个环境变量,或者用settings.configure()
函数来创建一个环境。
这样你就可以导入模型,进行你想在生产数据库上执行的处理。
你可以叫它“测试”,但因为你是在查看生产数据,所以必须像对待生产应用一样,认真对待设置文件和使用正确的ORM配置。