유닛 테스트¶
장고는 코드베이스의 “테스트” 디렉토리에 자체 테스트 스위트가 있습니다. 우리의 정책은 모든 시험을 항상 통과하도록 하는 것입니다.
테스트 제품군에 대한 모든 기여에 감사드립니다!
Django 테스트는 모두 Django와 함께 제공되는 테스트 애플리케이션을 위한 테스트 인프라를 사용합니다. 새로운 테스트 작성 방법에 대한 설명은 :doc:’/topics/testing/개요’를 참조하십시오.
장치 테스트를 실행¶
빠른시작¶
우선 장고를 깃허브 <https://github.com/django/django/fork>에서 포크하세요
둘째, 가상 환경을 생성하고 활성화합니다. 자세한 내용은 :doc:’기여 튜토리얼’을 참조하십시오.
그런 다음 포크를 복제하고 몇 가지 요구 사항을 설치한 다음 테스트를 실행하십시오.
$ git clone https://github.com/YourGitHubName/django.git django-repo
$ cd django-repo/tests
$ python -m pip install -e ..
$ python -m pip install -r requirements/py3.txt
$ ./runtests.py
...\> git clone https://github.com/YourGitHubName/django.git django-repo
...\> cd django-repo\tests
...\> py -m pip install -e ..
...\> py -m pip install -r requirements\py3.txt
...\> runtests.py
요구 사항을 설치하려면 컴퓨터에 설치되지 않은 일부 운영 체제 패키지가 필요할 수 있습니다. 일반적으로 오류 메시지의 마지막 줄에 대해 웹 검색을 수행하여 설치할 패키지를 확인할 수 있습니다. 필요한 경우 검색 쿼리에 운영 체제를 추가해 보십시오.
요구 사항을 설치하는 데 문제가 있으면 해당 단계를 건너뛸 수 있습니다. 선택적 테스트 종속성 설치에 대한 자세한 내용은:ref:’running-unit-tests-dependencies’를 참조하십시오. 선택적 종속성이 설치되어 있지 않으면 종속성이 필요한 테스트는 건너뜁니다.
테스트를 실행하려면 사용할 데이터베이스를 정의하는 Django 설정 모듈이 필요합니다. 시작할 수 있도록 Django는 SQLite 데이터베이스를 사용하는 샘플 설정 모듈을 제공하고 사용합니다. 다른 설정 모듈을 사용하여 다른 데이터베이스로 테스트를 실행하는 방법에 대한 자세한 내용은:ref:’running-unit-tests-settings’를 참조하십시오.
문제가 있나요? 몇 가지 일반적인 문제는:ref:’문제 해결 장치 테스트’를 참조하십시오.
“tox”를 사용하여 테스트를 실행합니다.¶
“Tox <https://tox.wiki/>_는 서로 다른 가상 환경에서 테스트를 실행하기 위한 도구입니다. Django에는 빌드 서버가 풀 요청에 대해 수행하는 일부 검사를 자동화하는 기본 “tox.ini”가 포함되어 있습니다. 장치 테스트 및 기타 검사(예: :ref:’import sorting’, :ref:’documentation spelling checker’ 및 :ref:’code formating’)를 실행하려면 Django 원본 트리의 임의의 위치에서 “tox” 명령을 설치하고 실행합니다.
$ python -m pip install tox
$ tox
...\> py -m pip install tox
...\> tox
By default, tox
runs the test suite with the bundled test settings file for
SQLite, black
, blacken-docs
, flake8
, isort
, and the
documentation spelling checker. In addition to the system dependencies noted
elsewhere in this documentation, the command python3
must be on your path
and linked to the appropriate version of Python. A list of default environments
can be seen as follows:
$ tox -l
py3
black
blacken-docs
flake8>=3.7.0
docs
isort>=5.1.0
...\> tox -l
py3
black
blacken-docs
flake8>=3.7.0
docs
isort>=5.1.0
다른 Python 버전 및 데이터베이스 백엔드를 테스트합니다.¶
In addition to the default environments, tox
supports running unit tests
for other versions of Python and other database backends. Since Django’s test
suite doesn’t bundle a settings file for database backends other than SQLite,
however, you must create and provide your own test settings. For example, to run the tests on Python 3.10
using PostgreSQL:
$ tox -e py310-postgres -- --settings=my_postgres_settings
...\> tox -e py310-postgres -- --settings=my_postgres_settings
This command sets up a Python 3.10 virtual environment, installs Django’s
test suite dependencies (including those for PostgreSQL), and calls
runtests.py
with the supplied arguments (in this case,
--settings=my_postgres_settings
).
이 문서의 나머지 부분에서는 “tox” 없이 테스트를 실행하는 명령을 보여 주지만 “runtests.py”에 전달되는 모든 옵션은 위와 같이 인수 목록에 “`–“를 붙임으로써 “tox”에 전달될 수 있습니다.
Tox
also respects the DJANGO_SETTINGS_MODULE
environment
variable, if set. For example, the following is equivalent to the command
above:
$ DJANGO_SETTINGS_MODULE=my_postgres_settings tox -e py310-postgres
Windows 사용자는 다음을 사용해야 합니다.
...\> set DJANGO_SETTINGS_MODULE=my_postgres_settings
...\> tox -e py310-postgres
JavaScript 테스트를 실행합니다.¶
Django에는 특정 기여 앱의 기능을 위한 :ref:`JavaScript 세트가 포함되어 있습니다. JavaScript 테스트는 “Node.js”를 설치해야 하고 대부분의 패치에 필요하지 않기 때문에 기본적으로 ``tox``를 사용하여 실행되지 않습니다. “tox”를 사용하여 JavaScript 테스트를 실행하려면 다음과 같이 하십시오.
$ tox -e javascript
...\> tox -e javascript
이 명령은 테스트 요구 사항이 최신인지 확인하기 위해 “npm install”을 실행한 다음 “npm test”를 실행합니다.
‘’장고-도커박스’’를 사용하여 테스트를 실행합니다.¶
“django-docker-box”_를 사용하면 지원되는 모든 데이터베이스 및 python 버전에서 Django의 테스트 제품군을 실행할 수 있습니다. 설치 및 사용 지침은 ‘django-docker-box’_ 프로젝트 페이지를 참조하십시오.
다른 ‘’설정’’ 모듈을 사용합니다.¶
포함된 설정 모듈(‘’tests/test_sqlite.py’’)을 사용하여 SQLite를 사용하여 테스트 제품군을 실행할 수 있습니다. 다른 데이터베이스를 사용하여 테스트를 실행하려면 자체 설정 파일을 정의해야 합니다. ‘’기여’’와 같은 몇 가지 시험들이 있습니다.postgres²는 특정 데이터베이스 백엔드에 한정되며 다른 백엔드로 실행할 경우 건너뜁니다. 일부 테스트는 특정 데이터베이스 백엔드에서 건너뛰거나 실패할 것으로 예상됩니다(각 백엔드의 “DatabaseFeatures.django_test_skips” 및 “DatabaseFeatures.django_testpected_fails” 참조).
다른 설정으로 테스트를 실행하려면 모듈이 :envvar:’PYthonPATH’에 있는지 확인하고 ‘–settings’로 모듈을 통과시킵니다.
: 설정은 다음과 같습니다.모든 테스트 설정 모듈의 “DATABASES” 설정은 두 개의 데이터베이스를 정의해야 합니다.
‘’’기본’’’입니다. 이 데이터베이스는 기본 테스트에 사용할 백엔드를 사용해야 합니다.
별칭이 ‘’기타’’인 데이터베이스입니다. “기타” 데이터베이스는 쿼리를 다른 데이터베이스로 전송할 수 있는지 테스트하는 데 사용됩니다. 이 데이터베이스는 “default”와 동일한 백엔드를 사용해야 하며 이름이 달라야 합니다.
SQLite가 아닌 백엔드를 사용하는 경우 각 데이터베이스에 대한 기타 세부 정보를 제공해야 합니다.
: 설정은 다음과 같습니다.’USER’ 옵션은 데이터베이스에 대한 기존 사용자 계정을 지정해야 합니다. 해당 사용자는 테스트 데이터베이스를 만들려면 “CREATE DATABASE”를 실행할 수 있는 권한이 필요합니다.
:설정:’입니다.PASSWORD’ 옵션은 :setting에 대한 암호를 제공해야 합니다.지정된 ‘USER’입니다.
테스트 데이터베이스는 “test_” 값을 :setting 값에 “test_”로 추가하여 이름을 가져옵니다.:setting에 정의된 데이터베이스에 대한 “NAME” 설정은 다음과 같습니다.’데이터베이스’입니다. 이러한 테스트 데이터베이스는 테스트가 완료되면 삭제됩니다.
또한 데이터베이스에서 UTF-8을 기본 문자 집합으로 사용해야 합니다. 데이터베이스 서버가 UTF-8을 기본 문자 집합으로 사용하지 않는 경우, 해당 데이터베이스의 테스트 설정 사전에 :setting:`CHARSET 값을 포함해야 합니다.
일부 테스트만 실행합니다.¶
Django의 전체 테스트 제품군을 실행하는 데 시간이 오래 걸리며, 예를 들어 모든 테스트를 Django에 추가했을 때 다른 모든 테스트를 실행하지 않고 빠르게 실행하고자 하는 경우 모든 테스트를 실행하는 것은 중복될 수 있습니다. 명령줄에서 테스트 모듈의 이름을 ``runtests.py``에 추가하여 단위 테스트의 하위 집합을 실행할 수 있습니다.
예를 들어 일반 관계 및 국제화에 대해서만 테스트를 실행하려면 다음을 입력합니다.
$ ./runtests.py --settings=path.to.settings generic_relations i18n
...\> runtests.py --settings=path.to.settings generic_relations i18n
개별 시험의 이름은 어떻게 알 수 있나요? “tests/’를 찾습니다. 각 디렉토리 이름은 테스트 이름입니다.
특정 테스트 클래스만 실행하려면 개별 테스트 클래스에 대한 경로 목록을 지정할 수 있습니다. 예를 들어 ‘’i18n’’’ 모듈의 ‘’번역’을 실행하려면 타입:
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests
또한 다음과 같은 개별 검사 방법을 지정할 수 있습니다.
$ ./runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
...\> runtests.py --settings=path.to.settings i18n.tests.TranslationTests.test_lazy_objects
“–start-at’ 옵션을 사용하여 지정된 최상위 모듈에서 테스트를 시작할 수 있습니다. 예를 들어 다음과 같습니다.
$ ./runtests.py --start-at=wsgi
...\> runtests.py --start-at=wsgi
또한 ‘’–start-after’’’ 옵션을 사용하여 지정된 최상위 모듈 이후에 테스트를 실행할 수도 있습니다. 예를 들어 다음과 같습니다.
$ ./runtests.py --start-after=wsgi
...\> runtests.py --start-after=wsgi
‘’’–reverse’’’ 옵션은 ‘’’–start-at’’’ 또는 ‘’’–start-after’’’ 옵션에는 영향을 미치지 않습니다. 또한 이러한 옵션은 테스트 레이블과 함께 사용할 수 없습니다.
Selenium 테스트를 실행합니다.¶
Some tests require Selenium and a web browser. To run these tests, you must
install the selenium package and run the tests with the
--selenium=<BROWSERS>
option. For example, if you have Firefox and Google
Chrome installed:
$ ./runtests.py --selenium=firefox,chrome
...\> runtests.py --selenium=firefox,chrome
셀레늄을 보세요.webdriver’_package에서 사용할 수 있는 브라우저 목록입니다.
‘’–selenium’’을 지정하면 ‘’–selenium’’이 자동으로 셀레늄이 필요한 테스트만 실행되도록 설정됩니다.
일부 브라우저(예: Chrome 또는 Firefox)는 헤드리스 테스트를 지원하므로 더 빠르고 안정적입니다. 이 모드를 활성화하려면 “–headless” 옵션을 추가합니다.
For testing changes to the admin UI, the selenium tests can be run with the
--screenshots
option enabled. Screenshots will be saved to the
tests/screenshots/
directory.
To define when screenshots should be taken during a selenium test, the test
class must use the @django.test.selenium.screenshot_cases
decorator with a
list of supported screenshot types ("desktop_size"
, "mobile_size"
,
"small_screen_size"
, "rtl"
, "dark"
, and "high_contrast"
). It
can then call self.take_screenshot("unique-screenshot-name")
at the desired
point to generate the screenshots. For example:
from django.test.selenium import SeleniumTestCase, screenshot_cases
from django.urls import reverse
class SeleniumTests(SeleniumTestCase):
@screenshot_cases(["desktop_size", "mobile_size", "rtl", "dark", "high_contrast"])
def test_login_button_centered(self):
self.selenium.get(self.live_server_url + reverse("admin:login"))
self.take_screenshot("login")
...
This generates multiple screenshots of the login page - one for a desktop screen, one for a mobile screen, one for right-to-left languages on desktop, one for the dark mode on desktop, and one for high contrast mode on desktop when using chrome.
The --screenshots
option and @screenshot_cases
decorator were
added.
모든 테스트를 실행합니다.¶
전체 테스트 제품군을 실행하려면 다음과 같은 여러 종속성을 설치해야 합니다.
argon2-cffi 19.2.0+
asgiref 3.8.1+ (required)
colorama 0.4.6+
docutils 0.19+
Jinja2 2.11+
Pillow 6.2.1+
redis 3.4+
pymemcache, plus a supported Python binding
selenium 4.8.0+
sqlparse 0.3.1+ (required)
tblib 1.5.0+
You can find these dependencies in pip requirements files inside the
tests/requirements
directory of the Django source tree and install them
like so:
$ python -m pip install -r tests/requirements/py3.txt
...\> py -m pip install -r tests\requirements\py3.txt
설치 중 오류가 발생했다면, 시스템이 하나 이상의 Python 패키지에 대한 의존성을 해결하지 못한 것일 수 있습니다. 설치에 실패한 패키지의 문서를 참조하거나 오류 메시지를 웹에서 검색하십시오.
“oracle”을 사용하여 원하는 데이터베이스 어댑터를 설치할 수도 있습니다.txt,, ‘’’예’’’입니다.txt, 또는 ‘’postgres’’입니다.txt``입니다.
memcached 또는 Redis 캐시 백엔드를 테스트하려면 :setting도 정의해야 합니다.memcached 또는 Redis 인스턴스를 각각 가리키는 “CACHES” 설정입니다.
GeoDjango 테스트를 실행하려면 :doc:’공간 데이터베이스를 설정하고 Geospacial Libraries를 설치해야 합니다.
이러한 각 종속성은 선택 사항입니다. 누락된 테스트가 있으면 관련 테스트를 건너뜁니다.
To run some of the autoreload tests, you’ll need to install the Watchman service.
코드 적용 범위¶
기여자는 추가 테스트가 필요한 영역을 식별하기 위해 테스트 제품군에 대한 적용 범위를 실행할 것을 권장합니다. 커버리지 도구 설치 및 사용은 :ref:’테스트 코드 커버리지’에 설명되어 있습니다.
To run coverage on the Django test suite using the standard test settings:
$ coverage run ./runtests.py --settings=test_sqlite
...\> coverage run runtests.py --settings=test_sqlite
After running coverage, combine all coverage statistics by running:
$ coverage combine
...\> coverage combine
After that generate the html report by running:
$ coverage html
...\> coverage html
Django 테스트에 대한 적용 범위를 실행할 때 포함된 “.coverager” 설정 파일은 “coverage_html”을 보고서의 출력 디렉터리로 정의하고 결과와 관련이 없는 여러 디렉터리(테스트 코드 또는 Django에 포함된 외부 코드)도 제외합니다.
기여 어플리케이션¶
Tests for contrib apps can be found in the tests/ directory, typically
under <app_name>_tests
. For example, tests for contrib.auth
are located
in tests/auth_tests.
문제해결¶
테스트 제품군이 ‘’main’’ 분기에 중단되거나 오류가 표시됩니다.¶
이전 버전에는 테스트 제품군의 실패 또는 행업 원인이 될 수 있는 버그가 종종 있으므로 a:ref:’supported Python version 의 최신 포인트 릴리스가 있는지 확인합니다.
On macOS (High Sierra and newer versions), you might see this message logged, after which the tests hang:
objc[42074]: +[__NSPlaceholderDate initialize] may have been in progress in
another thread when fork() was called.
To avoid this set a OBJC_DISABLE_INITIALIZE_FORK_SAFETY
environment
variable, for example:
$ OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ./runtests.py
Or add export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
to your shell’s
startup file (e.g. ~/.profile
).
‘’UnicodeError’’로 많은 테스트가 실패합니다.¶
“locales” 패키지가 설치되지 않은 경우 일부 테스트는 “UnicodeError”와 함께 실패합니다.
예를 들어 Debian 기반 시스템에서 다음을 실행하여 이 문제를 해결할 수 있습니다.
$ apt-get install locales
$ dpkg-reconfigure locales
macOS 시스템의 경우 셸의 로케일을 구성하여 이 문제를 해결할 수 있습니다.
$ export LANG="en_US.UTF-8"
$ export LC_ALL="en_US.UTF-8"
“locale” 명령을 실행하여 변경 내용을 확인합니다. 선택적으로 이러한 내보내기 명령을 셸의 시작 파일(예: Bash의 경우 “~/.bashrc’’)에 추가하여 다시 입력할 필요가 없도록 합니다.
조합상으로만 실패하는 테스트입니다.¶
별도로 실행했을 때 테스트는 통과했지만 전체 제품군 내에서 실패할 경우 문제를 분석하는 데 도움이 되는 몇 가지 도구가 있습니다.
runtests.py``의 ``--bisect
옵션은 실패 테스트를 실행하는 동시에 각 반복에서 함께 실행되는 테스트 세트를 절반으로 줄여 실패와 관련이 있을 수 있는 적은 수의 테스트를 식별할 수 있게 합니다.
예를 들어, 자체적으로 작동하는 실패한 테스트가 ‘’ModelTest.test_eq’’라고 가정하고 다음을 사용합니다.
$ ./runtests.py --bisect basic.tests.ModelTest.test_eq
...\> runtests.py --bisect basic.tests.ModelTest.test_eq
지정된 테스트를 방해하는 테스트를 결정합니다. 먼저 테스트 스위트의 전반부에서 테스트를 실행합니다. 오류가 발생하면 테스트 스위트의 전반부가 두 그룹으로 분할되고 각 그룹이 지정된 테스트와 함께 실행됩니다. 테스트 스위트의 전반부에 고장이 없는 경우, 테스트 스위트의 후반부는 앞에서 설명한 대로 지정된 테스트와 함께 실행되고 적절히 분할됩니다. 이 프로세스는 실패한 테스트 집합이 최소화될 때까지 반복됩니다.
“–pair” 옵션은 제품군의 다른 모든 테스트와 함께 주어진 테스트를 실행하므로 다른 테스트에 실패의 원인이 되는 부작용이 있는지 확인할 수 있습니다. 그래서:
$ ./runtests.py --pair basic.tests.ModelTest.test_eq
...\> runtests.py --pair basic.tests.ModelTest.test_eq
“test_eq”는 모든 테스트 레이블과 쌍을 이룹니다.
“–bisect” 및 “–pair”를 모두 사용할 경우, 어떤 사례가 실패의 원인이 될 수 있는지 이미 의심하는 경우, 첫 번째 테스트 이후에 :ref:`specifying further test labels `가 교차 분석하도록 테스트를 제한할 수 있습니다.
$ ./runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
...\> runtests.py --pair basic.tests.ModelTest.test_eq queries transactions
또한 “–shuffle” 및 “–reverse” 옵션을 사용하여 임의의 테스트 세트를 랜덤 또는 역순으로 실행할 수 있습니다. 이렇게 하면 테스트를 다른 순서로 실행해도 문제가 발생하지 않는지 확인할 수 있습니다.
$ ./runtests.py basic --shuffle
$ ./runtests.py basic --reverse
...\> runtests.py basic --shuffle
...\> runtests.py basic --reverse
테스트 중에 실행되는 SQL 쿼리를 봅니다.¶
실패한 테스트에서 실행 중인 SQL을 검사하려면 A 옵션을 사용하여 “–debug-sql”을 설정할 수 있습니다. 이 값을 “–verbosity=2”와 결합하면 모든 SQL 쿼리가 출력됩니다.
$ ./runtests.py basic --debug-sql
...\> runtests.py basic --debug-sql
테스트 실패의 전체 추적 결과를 봅니다.¶
기본적으로 테스트는 코어당 하나의 프로세스와 병렬로 실행됩니다. 그러나 테스트가 병렬로 실행되면 테스트 실패에 대한 잘린 추적만 볼 수 있습니다. “–parallel” 옵션을 사용하여 이 동작을 조정할 수 있습니다.
$ ./runtests.py basic --parallel=1
...\> runtests.py basic --parallel=1
:envvar를 사용할 수도 있습니다.이 목적을 위한 “DJANGO_TEST_PROCESS” 환경 변수입니다.
쓰기 테스트에 대한 팁입니다.¶
모델 등록을 격리합니다.¶
To avoid polluting the global apps
registry and prevent
unnecessary table creation, models defined in a test method should be bound to
a temporary Apps
instance. To do this, use the
isolate_apps()
decorator:
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps("app_label")
def test_model_definition(self):
class TestModel(models.Model):
pass
...
‘’app_label’’을 설정합니다.
명시적 app_label
이 없는 테스트 방법에 정의된 모델에는 테스트 클래스가 위치한 앱의 레이블이 자동으로 할당됩니다.
isolate_apps()
인스턴스의 컨텍스트에 정의된 모델이 올바르게 설치되었는지 확인하려면 대상 app_label
집합을 인수로 전달해야 합니다.
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class TestModelDefinition(SimpleTestCase):
@isolate_apps("app_label", "other_app_label")
def test_model_definition(self):
# This model automatically receives app_label='app_label'
class TestModel(models.Model):
pass
class OtherAppModel(models.Model):
class Meta:
app_label = "other_app_label"
...