2010-03-28 3 views
8

hg bisect --command에 전달할 수있는 단위 테스트가 포함 된 Python 모듈을 갖고 싶습니다. 유닛 테스팅을 위해 임시 django db를 설정하고 해체하는 방법은 무엇입니까?

단위 테스트

는 장고 응용 프로그램의 일부 기능을 테스트하고 있습니다,하지만 난 mytestapp이 settings.py에서 활성화되어야 할 것이다 hg bisect --command manage.py test mytestapp 때문에 내가 사용하는 수 있다고 생각하지 않으며, settings.py에 대한 편집은 사방 될 때 hg bisect 작업 디렉토리를 갱신합니다.

따라서, 나는 다음과 같은 무언가가 갈 수있는 가장 좋은 방법입니다 있는지 알고 싶습니다

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() 

당신도 조언을 수 있다면 가장 감사해야 :

  1. 이있는 경우 더 간단한 방법, 아마도 django.test.TestCase을 서브 클래스 화하고 settings.py를 편집하지 않거나 그렇지 않은 경우;
  2. 위의 줄은 "임시 django db 설정"및 "임시 django db 분리"라고해야합니다?

답변

8

균열이 있습니다. 이제 하나의 python 파일을 완전히 독립적 인 테스트 데이터베이스를 사용하여 단위 테스트를 실행할 수있는 모든 장고 응용 프로그램이 있습니다 :

#!/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 최종 해결책 게시. –

+0

감사합니다. 이것은 코 테스트를 포함한 임의의 유닛 테스트를 위해 장고 테스트 데이터베이스를 설정하는 방법을 다른 사람들에게 보여주기를 바랍니다. – blokeley

5

이렇게하려면 내부 Django TestCase를 사용해야합니다.

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.') 

이 코드는 unittest와 완벽하게 호환되므로 코드를 많이 변경할 필요가 없습니다.

django.test, fixtures, flushloaddata 명령에 대해 자세히 알아볼 수 있습니다.

데코레이터를 사용하여 작업을 수행하려는 경우 call_command을 사용하여 Python 프로그램에서 django 명령을 사용할 수 있습니다. 예 :

from django.core.management import call_command 

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

나는 코드를 mytest.py라는 파일에 넣었지만'python mytest.py'를 사용하여 필요한 단위 테스트를 실행합니다. – blokeley

+1

@blokeley : 두 가지 확실한 선택이 있습니다. 테스트는'models.py' 또는'tests.py'에 들어갑니다. 'mytest.py' 대신'tests.py'를 사용하면 행복 할 것입니다. –

관련 문제