[python] Django의 테스트 데이터베이스를 메모리에서만 실행하는 방법은 무엇입니까?

내 Django 단위 테스트는 실행하는 데 오랜 시간이 걸리므로 속도를 높이는 방법을 찾고 있습니다. SSD 설치를 고려하고 있지만 단점도 있다는 것을 알고 있습니다. 물론 내 코드로 할 수있는 일이 있지만 구조적 수정을 찾고 있습니다. 매번 데이터베이스를 다시 빌드 / 마이그레이션해야하기 때문에 단일 테스트를 실행하는 것조차 느립니다. 그래서 여기 내 생각이 있습니다.

테스트 데이터베이스가 항상 매우 작다는 것을 알고 있기 때문에 전체 테스트 데이터베이스를 항상 RAM에 유지하도록 시스템을 구성 할 수없는 이유는 무엇입니까? 디스크를 절대 만지지 마십시오. Django에서 어떻게 구성합니까? 나는 그것이 내가 프로덕션에서 사용하는 것이므로 MySQL 을 계속 사용하는 것을 선호 하지만 SQLite  3 또는 다른 것들이 이것을 쉽게 만든다면 나는 그렇게 할 것입니다.

SQLite 또는 MySQL에 완전히 메모리에서 실행할 수있는 옵션이 있습니까? RAM 디스크를 구성한 다음 데이터를 저장하도록 테스트 데이터베이스를 구성 할 수 있어야합니다.하지만 Django / MySQL에 특정 데이터베이스에 대해 다른 데이터 디렉터리를 사용하도록 지시하는 방법을 잘 모르겠습니다. 특히 계속 지워지기 때문입니다. 각 실행을 재현했습니다. (저는 Mac FWIW를 사용하고 있습니다.)



답변

테스트를 실행할 때 데이터베이스 엔진을 sqlite3로 설정하면 Django는 메모리 내 데이터베이스를 사용합니다. .

settings.py테스트를 실행할 때 엔진을 sqlite로 설정하기 위해 다음 과 같은 코드를 사용하고 있습니다 .

if 'test' in sys.argv:
    DATABASE_ENGINE = 'sqlite3'

또는 Django 1.2에서 :

if 'test' in sys.argv:
    DATABASES['default'] = {'ENGINE': 'sqlite3'}

마지막으로 Django 1.3 및 1.4에서 :

if 'test' in sys.argv:
    DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}

(백엔드에 대한 전체 경로는 Django 1.3에서 꼭 필요한 것은 아니지만 설정이 앞으로 호환되도록합니다.)

South 마이그레이션에 문제가있는 경우 다음 줄을 추가 할 수도 있습니다.

    SOUTH_TESTS_MIGRATE = False


답변

나는 일반적으로 테스트를 위해 별도의 설정 파일을 만들고 테스트 명령에서 사용합니다.

python manage.py test --settings=mysite.test_settings myapp

두 가지 이점이 있습니다.

  1. testsys.argv에서 확인 하거나 그러한 마법의 단어 를 확인할 필요가 없습니다 test_settings.py.

    from settings import *
    
    # make tests faster
    SOUTH_TESTS_MIGRATE = False
    DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}

    또는 테스트 설정을 프로덕션 설정과 명확하게 분리하여 필요에 따라 추가로 조정할 수 있습니다.

  2. 또 다른 이점은 미묘한 버그를 피하는 sqlite3 대신 프로덕션 데이터베이스 엔진으로 테스트를 실행할 수 있다는 것입니다.

    python manage.py test --settings=mysite.test_settings myapp

    코드를 커밋하기 전에 한 번 실행

    python manage.py test myapp

    모든 테스트가 실제로 통과되었는지 확인합니다.


답변

MySQL은 데이터베이스 구성 ( settings.py)에서 다음과 같이 구성 할 수있는 “MEMORY”라는 스토리지 엔진을 지원합니다 .

    'USER': 'root',                      # Not used with sqlite3.
    'PASSWORD': '',                  # Not used with sqlite3.
    'OPTIONS': {
        "init_command": "SET storage_engine=MEMORY",
    }

MEMORY 저장소 엔진은 blob / text 열을 지원하지 않으므로 django.db.models.TextField이를 사용하는 경우 작동하지 않습니다.


답변

주요 질문에 답할 수는 없지만 작업 속도를 높이기 위해 할 수있는 몇 가지가 있습니다.

먼저 MySQL 데이터베이스가 InnoDB를 사용하도록 설정되어 있는지 확인하십시오. 그런 다음 트랜잭션을 사용하여 각 테스트 전에 db의 상태를 롤백 할 수 있는데, 내 경험상 엄청난 속도 향상을 가져 왔습니다. settings.py (Django 1.2 구문)에서 데이터베이스 init 명령을 전달할 수 있습니다.

DATABASES = {
    'default': {
            'ENGINE':'django.db.backends.mysql',
            'HOST':'localhost',
            'NAME':'mydb',
            'USER':'whoever',
            'PASSWORD':'whatever',
            'OPTIONS':{"init_command": "SET storage_engine=INNODB" }
        }
    }

둘째, 매번 South 마이그레이션을 실행할 필요가 없습니다. 설정 SOUTH_TESTS_MIGRATE = False당신의 settings.py에서 데이터베이스는 더 빨리 모든 역사적인 마이그레이션을 통해 실행하는 것보다 될 것입니다 일반 syncdb로 생성됩니다.


답변

이중 조정을 수행 할 수 있습니다.

  • 트랜잭션 테이블 사용 : 초기 조명기 상태는 모든 TestCase 후 데이터베이스 롤백을 사용하여 설정됩니다.
  • 데이터베이스 데이터 디렉토리를 ramdisk에 넣으십시오. 데이터베이스 생성에 관한 한 많은 것을 얻을 수 있으며 테스트를 실행하는 것이 더 빠를 것입니다.

나는 두 가지 트릭을 모두 사용하고 있으며 매우 행복합니다.

Ubuntu에서 MySQL 용으로 설정하는 방법 :

$ sudo service mysql stop
$ sudo cp -pRL /var/lib/mysql /dev/shm/mysql

$ vim /etc/mysql/my.cnf
# datadir = /dev/shm/mysql
$ sudo service mysql start

메모리에서 데이터베이스를 다시 부팅 한 후에는 테스트 용일뿐입니다.


답변

또 다른 접근 방식 : RAM 디스크를 사용하는 tempfs에서 MySQL의 다른 인스턴스를 실행하는 것입니다. 이 블로그 게시물의 지침 : Django 테스트를 위해 MySQL 속도 향상 .

장점 :

  • 프로덕션 서버에서 사용하는 것과 똑같은 데이터베이스를 사용합니다.
  • 기본 mysql 구성을 변경할 필요가 없습니다.

답변

Anurag의 답변을 확장하여 동일한 test_settings를 만들고 manage.py에 다음을 추가하여 프로세스를 단순화했습니다.

if len(sys.argv) > 1 and sys.argv[1] == "test":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.test_settings")
else:
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")

sys가 이미 가져오고 manage.py는 명령 줄을 통해서만 사용되므로 더 깔끔해 보입니다. 설정을 복잡하게 만들 필요가 없습니다.