2010-03-28 10 views
8

Ich hätte gerne ein Python-Modul mit einigen Komponententests, die ich an hg bisect --command weitergeben kann.Wie Setup und Teardown temporäre Django Db für Komponententests?

die Unit-Tests testen einige Funktionen eines django app, aber ich glaube nicht, dass ich hg bisect --command manage.py test mytestapp weil mytestapp in settings.py aktiviert hätte verwenden können, und die Änderungen an settings.py verprügelt werden würden, wenn hg bisect aktualisiert das Arbeitsverzeichnis.

Deshalb würde ich gerne wissen, ob so etwas wie die folgende ist der beste Weg zu gehen:

import functools, os, sys, unittest 

sys.path.append(path_to_myproject) 
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings' 


def with_test_db(func): 
    """Decorator to setup and teardown test db.""" 
    @functools.wraps 
    def wrapper(*args, **kwargs): 
     try: 
      # Set up temporary django db 
      func(*args, **kwargs) 
     finally: 
      # Tear down temporary django db 


class TestCase(unittest.TestCase): 

    @with_test_db 
    def test(self): 
     # Do some tests using the temporary django db 
     self.fail('Mark this revision as bad.') 


if '__main__' == __name__: 
    unittest.main() 

ich sollte die meisten dankbar, wenn Sie entweder beraten könnten:

  1. Wenn es ein einfacherer Weg, möglicherweise Unterklasse django.test.TestCase, aber nicht editieren von settings.py oder, wenn nicht;
  2. Was die Zeilen oben sagen, dass "temporäre django db einrichten" und "Teal down temporäre django db" sollte sein?

Antwort

8

Gebrochen es. Ich habe jetzt eine Python-Datei völlig unabhängig von django app, die Unit-Tests mit einer Testdatenbank ausführen kann:

#!/usr/bin/env python 
"""Run a unit test and return result. 

This can be used with `hg bisect`. 
It is assumed that this file resides in the same dir as settings.py 

""" 

import os 
from os.path import abspath, dirname 
import sys 
import unittest 

# Set up django 
project_dir = abspath(dirname(dirname(__file__))) 
sys.path.insert(0, project_dir) 
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' 

from django.db import connection 
from django.test import TestCase 
from django.test.utils import setup_test_environment, teardown_test_environment 

from myproject import settings 
from myproject.myapp.models import MyModel 


class MyTestCase(TestCase): 

    def test_something(self): 
     # A failed assertion will make unittest.main() return non-zero 
     # which if used with `hg bisect` will mark the revision as bad 
     self.assertEqual(0, len(MyModel.objects.all())) # and so on 


if '__main__' == __name__: 
    try: 
     setup_test_environment() 
     settings.DEBUG = False  
     verbosity = 0 
     old_database_name = settings.DATABASE_NAME 
     connection.creation.create_test_db(verbosity) 
     unittest.main() 
    finally: 
     connection.creation.destroy_test_db(old_database_name, verbosity) 
     teardown_test_environment() 
+0

+1 für die endgültige Lösung. –

+0

Danke. Ich hoffe, dass dies anderen zeigt, wie man die django-Testdatenbank für beliebige Einzeltests, einschließlich Nasentests, aufbaut. – blokeley

5

Sie müssen dazu das interne Django TestCase verwenden.

from django.test import TestCase 

class TestCase(TestCase): 

    # before every call to setUp(), the db is automatically 
    # set back to the state is was after the first syncdb then 
    # all these fixture files will be loaded in the db 
    fixtures = ['mammals.json', 'birds'] 

    # put whatever you want here, you don't need to call the 
    # super() 
    def setUp(self): 
     # Test definitions as before. 
     call_setup_methods() 

    def test(self): 
     # Do some tests using the temporary django db 
     self.fail('Mark this revision as bad.') 

Es ist voll kompatibel mit unittest, so dass Ihr Code nicht viel ändern muss.

Sie können mehr über die Befehle , flush und loaddata erfahren.

Wenn Sie einen Dekorator verwenden möchten, können Sie mit dem call_command in Ihrem Python-Programm einen beliebigen django-Befehl verwenden. Beispiel:

from django.core.management import call_command 

call_command('flush', 'myapp') 
call_command('loaddata', 'myapp') 
+0

Wenn ich Ihren Code in eine Datei namens mytest.py setzen, ich kann immer noch nicht einfach laufen 'Python mytest.py' um die Komponententests auszuführen, was ich brauche. – blokeley

+1

@blokeley: Sie haben zwei offensichtliche Entscheidungen. Die Tests gehen in 'models.py' oder sie gehen in' tests.py'. Wenn du 'tests.py' anstelle von' mytest.py' verwendest, wirst du glücklich sein. –

Verwandte Themen