DB를 설정하지 않고 장고 단위 테스트를 작성할 가능성이 있습니까? db를 설정하지 않아도되는 비즈니스 로직을 테스트하고 싶습니다. 그리고 db를 설정하는 것이 빠르지 만 실제로는 상황에 따라 필요하지 않습니다.
답변
DjangoTestSuiteRunner를 서브 클래 싱하고 setup_databases 및 teardown_databases 메소드를 대체하여 전달할 수 있습니다.
새 설정 파일을 작성하고 TEST_RUNNER를 방금 작성한 새 클래스로 설정하십시오. 그런 다음 테스트를 실행할 때 –settings 플래그를 사용하여 새 설정 파일을 지정하십시오.
여기 내가 한 일이 있습니다.
다음과 유사한 사용자 정의 테스트 슈트 러너를 작성하십시오.
from django.test.simple import DjangoTestSuiteRunner
class NoDbTestRunner(DjangoTestSuiteRunner):
""" A test runner to test without database creation """
def setup_databases(self, **kwargs):
""" Override the database creation defined in parent class """
pass
def teardown_databases(self, old_config, **kwargs):
""" Override the database teardown defined in parent class """
pass
사용자 정의 설정을 작성하십시오.
from mysite.settings import *
# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'
테스트를 실행할 때 –settings 플래그를 새 설정 파일로 설정하여 다음과 같이 실행하십시오.
python manage.py test myapp --settings='no_db_settings'
업데이트 : 2018 년 4 월
Django 1.8부터 모듈 이로 이동 했습니다 .django.test.simple.DjangoTestSuiteRunner
'django.test.runner.DiscoverRunner'
자세한 내용 은 사용자 정의 테스트 러너에 대한 공식 문서 섹션을 확인하십시오 .
답변
일반적으로 응용 프로그램의 테스트는 두 가지 범주로 분류 할 수 있습니다
- 단위 테스트-이러한 코드는 일사량의 개별 코드 스 니펫을 테스트하며 데이터베이스로 이동할 필요가 없습니다.
- 실제로 데이터베이스로 이동하여 완전히 통합 된 로직을 테스트하는 통합 테스트 사례.
Django는 단위 테스트와 통합 테스트를 모두 지원합니다.
단위 테스트는 데이터베이스를 설정 및 해제 할 필요가 없으며 SimpleTestCase 에서 상속해야합니다 .
from django.test import SimpleTestCase
class ExampleUnitTest(SimpleTestCase):
def test_something_works(self):
self.assertTrue(True)
통합 테스트 케이스의 경우 TestCase에서 상속하고 TransactionTestCase에서 상속하며 각 테스트를 실행하기 전에 데이터베이스를 설정 및 해제합니다.
from django.test import TestCase
class ExampleIntegrationTest(TestCase):
def test_something_works(self):
#do something with database
self.assertTrue(True)
이 전략은 데이터베이스에 액세스하는 테스트 케이스에 대해서만 데이터베이스를 작성하고 파괴하므로 테스트가 더 효율적입니다.
답변
에서 django.test.simple
warnings.warn(
"The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
"use django.test.runner.DiscoverRunner instead.",
RemovedInDjango18Warning)
따라서 DiscoverRunner
대신에 재정의하십시오 DjangoTestSuiteRunner
.
from django.test.runner import DiscoverRunner
class NoDbTestRunner(DiscoverRunner):
""" A test runner to test without database creation/deletion """
def setup_databases(self, **kwargs):
pass
def teardown_databases(self, old_config, **kwargs):
pass
그런 식으로 사용하십시오 :
python manage.py test app --testrunner=app.filename.NoDbTestRunner
답변
나는 메소드 를 상속 django.test.runner.DiscoverRunner
하고 run_tests
메소드에 몇 가지를 추가하기로 결정했습니다 .
첫 번째 추가 항목은 DB 설정이 필요한지 setup_databases
확인하고 DB가 필요한 경우 정상적인 기능을 시작하도록 허용합니다 . 두 번째 추가는 메소드 실행이 허용 된 teardown_databases
경우 정규 실행 setup_databases
을 허용합니다.
내 코드는 상속 된 TestCase django.test.TransactionTestCase
(및 따라서 django.test.TestCase
)에서 데이터베이스를 설정해야 한다고 가정합니다 . 장고 문서는 다음과 같이 말했기 때문에이 가정을했습니다.
… ORM 테스트 또는 사용 …과 같이 더 복잡하고 무거운 Django 관련 기능이 필요한 경우 TransactionTestCase 또는 TestCase를 대신 사용해야합니다.
https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase
mysite / scripts / settings.py
from django.test import TransactionTestCase
from django.test.runner import DiscoverRunner
class MyDiscoverRunner(DiscoverRunner):
def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""
Run the unit tests for all the test labels in the provided list.
Test labels should be dotted Python paths to test modules, test
classes, or test methods.
A list of 'extra' tests may also be provided; these tests
will be added to the test suite.
If any of the tests in the test suite inherit from
``django.test.TransactionTestCase``, databases will be setup.
Otherwise, databases will not be set up.
Returns the number of tests that failed.
"""
self.setup_test_environment()
suite = self.build_suite(test_labels, extra_tests)
# ----------------- First Addition --------------
need_databases = any(isinstance(test_case, TransactionTestCase)
for test_case in suite)
old_config = None
if need_databases:
# --------------- End First Addition ------------
old_config = self.setup_databases()
result = self.run_suite(suite)
# ----------------- Second Addition -------------
if need_databases:
# --------------- End Second Addition -----------
self.teardown_databases(old_config)
self.teardown_test_environment()
return self.suite_result(suite, result)
마지막으로 프로젝트의 settings.py 파일에 다음 줄을 추가했습니다.
mysite / settings.py
TEST_RUNNER = 'mysite.scripts.settings.MyDiscoverRunner'
이제 비 DB 의존 테스트 만 실행할 때 테스트 스위트가 훨씬 빠르게 실행됩니다! 🙂
답변
업데이트 됨 : 타사 도구 사용에 대한 이 답변 도 참조하십시오 pytest
.
@Cesar가 맞습니다. ./manage.py test --settings=no_db_settings
앱 이름을 지정하지 않고 실수로를 실행 한 후 개발 데이터베이스가 지워졌습니다.
보다 안전한 방식으로 NoDbTestRunner
다음을 함께 사용하십시오 mysite/no_db_settings.py
.
from mysite.settings import *
# Test runner with no database creation
TEST_RUNNER = 'mysite.scripts.testrunner.NoDbTestRunner'
# Use an alternative database as a safeguard against accidents
DATABASES['default']['NAME'] = '_test_mysite_db'
_test_mysite_db
외부 데이터베이스 도구를 사용하여 호출 된 데이터베이스를 작성해야합니다 . 그런 다음 다음 명령을 실행하여 해당 테이블을 작성하십시오.
./manage.py syncdb --settings=mysite.no_db_settings
South를 사용하는 경우 다음 명령도 실행하십시오.
./manage.py migrate --settings=mysite.no_db_settings
확인!
이제 다음을 통해 단위 테스트를 엄청나게 빠르고 안전하게 실행할 수 있습니다.
./manage.py test myapp --settings=mysite.no_db_settings
답변
NoDbTestRunner를 “안전”하도록 설정을 수정하는 대신 현재 데이터베이스 연결을 닫고 설정 및 연결 개체에서 연결 정보를 제거하는 수정 된 버전의 NoDbTestRunner가 있습니다. 나를 위해 일하고, 의존하기 전에 환경에서 테스트하십시오 🙂
class NoDbTestRunner(DjangoTestSuiteRunner):
""" A test runner to test without database creation """
def __init__(self, *args, **kwargs):
# hide/disconnect databases to prevent tests that
# *do* require a database which accidentally get
# run from altering your data
from django.db import connections
from django.conf import settings
connections.databases = settings.DATABASES = {}
connections._connections['default'].close()
del connections._connections['default']
super(NoDbTestRunner,self).__init__(*args,**kwargs)
def setup_databases(self, **kwargs):
""" Override the database creation defined in parent class """
pass
def teardown_databases(self, old_config, **kwargs):
""" Override the database teardown defined in parent class """
pass
답변
또 다른 해결책은 테스트 클래스 unittest.TestCase
가 Django의 테스트 클래스 대신 상속되는 것입니다. 장고 문서 ( https://docs.djangoproject.com/en/2.0/topics/testing/overview/#writing-tests )에는 다음에 대한 경고가 포함되어 있습니다.
unittest.TestCase를 사용하면 트랜잭션에서 각 테스트를 실행하고 데이터베이스를 플러시하는 비용을 피할 수 있지만 테스트가 데이터베이스와 상호 작용하는 경우 테스트 실행기가 실행하는 순서에 따라 동작이 달라집니다. 이로 인해 단독으로 실행될 때 통과하지만 스위트에서 실행될 때 실패하는 단위 테스트가 발생할 수 있습니다.
그러나 테스트에서 데이터베이스를 사용하지 않는 경우이 경고는 걱정할 필요가 없으며 트랜잭션에서 각 테스트 사례를 실행할 필요가 없다는 이점을 얻을 수 있습니다.
