Djangoでテストを速くするためにいろいろやってみた

4分程度かかってたテスト実行を速くするためにいろいろやってみたときのメモ


まず対応前

$ python manage.py test app --settings=settings.test
Creating test database for alias 'default'...
..............................................................................................................................................................................................
----------------------------------------------------------------------
Ran 190 tests in 248.277s

OK
Destroying test database for alias 'default'...

対応1 テストのリファクタリング

  • setUpで作成していたデータに無駄なものがあったので整理。
  • 一部dbに依存しないテストクラスのスーパークラスdjango.test.TestCaseからunittest.TestCaseに変更
$ python manage.py test app --settings=settings.test
Creating test database for alias 'default'...
..............................................................................................................................................................................................
----------------------------------------------------------------------
Ran 190 tests in 92.063s

OK
Destroying test database for alias 'default'...

大分マシになった。

対応2 sqlite3のin-memory databaseにしてみる

settings/test.py

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
    },
}
$ python manage.py test app --settings=settings.test
Creating test database for alias 'default'...
..............................................................................................................................................................................................
----------------------------------------------------------------------
Ran 190 tests in 84.815s

OK
Destroying test database for alias 'default'...

ちょっと効果があったっぽい

対応3 southでテスト時にmigrateを使わず、syncdbでテーブル作成を行わせる

Settings ― South 0.8.1 documentation

settings/test.py

SOUTH_TESTS_MIGRATE=False
python manage.py test app --settings=settings.test
Creating test database for alias 'default'...
..............................................................................................................................................................................................
----------------------------------------------------------------------
Ran 190 tests in 92.133s

OK
Destroying test database for alias 'default'...

効果がないのでやめた。

対応4 PASSWORD_HASHERSの変更

デフォルトでは以下の設定となっていて、一番最初のPBKDF2PasswordHasherが使用される

django.conf.global_settings.py

# the first hasher in this list is the preferred algorithm.  any
# password using different algorithms will be converted automatically
# upon login
PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
    'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)

PBKDF2PasswordHasherは結構処理が重いらしいのでテスト用のsettingsファイルでのみ順番を変えてみる

settings/test.py

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.SHA1PasswordHasher',		    
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
    'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)
python manage.py test app --settings=settings.test
Creating test database for alias 'default'...
..............................................................................................................................................................................................
----------------------------------------------------------------------
Ran 190 tests in 22.793s

OK
Destroying test database for alias 'default'...

かなり効果があってびっくり。


全体で1/10くらいになったので終わりにする。