# Django 4.1.8.dev20230308103347 ドキュメント

# テストを書いて実行する

参考

テストチュートリアル、 テストツールリファレンス、 テストに関する応用的なトピック も読んでください。

ドキュメントは2つの大きなセクションに分けられます。前半のパートでは、Django でのテストの書き方を説明します。後半では、テストの実行の仕方について説明します。

## テストを書く

Django のユニットテストには、Python スタンダードライブラリのモジュール、`unittest` を使用します。このモジュールは、テストをクラスベースのアプローチで定義します。

次の例では、 `unittest.TestCase` のサブクラスである `django.test.TestCase` から、テスト用の新しいサブクラスを作っています。各テストをトランザクションの内側で実行することで、独立性を実現しています。

    from django.test import TestCase
    from myapp.models import Animal

    class AnimalTestCase(TestCase):
        def setUp(self):
            Animal.objects.create(name="lion", sound="roar")
            Animal.objects.create(name="cat", sound="meow")

        def test_animals_can_speak(self):
            """Animals that can speak are correctly identified"""
            lion = Animal.objects.get(name="lion")
            cat = Animal.objects.get(name="cat")
            self.assertEqual(lion.speak(), 'The lion says "roar"')
            self.assertEqual(cat.speak(), 'The cat says "meow"')

自分で描いたテストを実行する とき、テストユーティリティのデフォルトの動作は次のようなものです。まず、 `test` で始まる名前を持つファイルからすべてのテストケース (つまり `unittest.TestCase` のすべてのサブクラス) を見つけ出します。次に、それらテストケースのテストスイートを自動的にビルドします。そして、ビルドしたテストスイートを実行します。

`unittest` の詳細については、Python のドキュメントを読んでください。

どこにテストを書くべき？

デフォルトの `startapp` テンプレートは、新しいアプリケーション内に `tests.py` ファイルを作成します。テストの数が少ないうちは、ここに書くのがいいかもしれません。しかし、テストスイートが大きくなってきたら、テストを複数のパッケージに再構成して、`test_models.py` 、 `test_views.py` 、 `test_forms.py` などの異なるサブモジュールに分離すると良いでしょう。ファイル名には、ちゃんと組織的な命名規則になっていれば、自由に好きな名前をつけて構いません。

Using the Django test runner to test reusable applications も参照してください。

警告

作成したテストが、データの新規作成やモデルのクエリなどのデータベースアクセスを必要とするときは、`unittest.TestCase` ではなく、 `django.test.TestCase` のサブクラスを作るようにしてください。

`unittest.TestCase` を使えば、各テストでデータベースのトランザクションとフラッシュに必要な実行コストを避けることができます。しかし、データベースと相互作用するテストの場合、テストランナーがテストを実行する順番によっては、異なる動作をすることがあります。そのため、孤立した環境では成功するテストユニットでも、一連のテストスイートの中で実行した時には失敗してしまうという状況が発生することがあります。

## テストの実行

テストが書けたら、プロジェクトの `manage.py` ユーティリティの `test` コマンドでテストが実行できます。

    $ ./manage.py test

Test discovery is based on the unittest module's built-in test discovery. By default, this will discover tests in any file named `test*.py` under the current working directory.

`/manage.py test` に好きな数の「テストラベル」を与えることで、特定のテストを指定することもできます。各テストラベルには、パッケージ、モジュール、 `TestCase` サブクラス、テストメソッドへのドット区切りの Python パスを指定します。たとえば:

    # Run all the tests in the animals.tests module
    $ ./manage.py test animals.tests

    # Run all the tests found within the 'animals' package
    $ ./manage.py test animals

    # Run just one test case
    $ ./manage.py test animals.tests.AnimalTestCase

    # Run just one test method
    $ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak

ディレクトリ下に置かれたテストを探索するために、ディレクトリのパスを指定することもできます。

    $ ./manage.py test animals/

`-p` (または `--pattern`) オプションを使って、カスタムのファイル名のパターンマッチを指定すれば、テストファイルの名前が `test*.py` というパターンとは違っていても実行することができます。

    $ ./manage.py test --pattern="tests_*.py"

テストの実行中に `Ctrl-C` を押すと、テストランナーは現在実行中のテストが完了するのを待って、gracefully にテストを終了します。graceful な終了では、テストランナーは失敗したテストの詳細を出力し、実行したテストの数と、エラーおよび失敗したテストの数をレポートし、通常通りにテストデータベースを破棄します。そのため、 `Ctrl-C` を押すのは、たとえば、 `--failfast` オプションを付けるのを忘れて、思わぬテストが失敗したとき、すべてのテストが終わるのを待たずにその失敗の詳細をすぐに知りたいような場合に大変役に立ちます。

現在実行中のテストの終了も待ちたくないときは、もう一度 `Ctrl-C` を押すことで、テストを graceful ではなく、すぐに強制終了することができます。その場合、強制終了前に実行していたテストの詳細はリポートされず、実行中に作られたテストデータベースも破棄されません。

警告を有効にしてテストする

It's a good idea to run your tests with Python warnings enabled: `python -Wa manage.py test`. The `-Wa` flag tells Python to display deprecation warnings. Django, like many other Python libraries, uses these warnings to flag when features are going away. It also might flag areas in your code that aren't strictly wrong but could benefit from a better implementation.

### test データベース

データベースを必要とするテスト (すなわち、モデルテスト) には、"実際の" (production) 環境のデータベースは使用しません。代わりに、テスト用の空のデータベースを用意します。

テストが成功したかどうかにかかわらず、すべてのテストの実行が終わった時点で、テストデータベースは破棄されます。

`test --keepdb` オプションを指定すれば、テストデータベースの破棄を防ぐことができます。これにより、複数回テストを実行しても、テストデータベースを保存することができます。データベースが存在しないときは、最初に新しく作成され、そしてデータベースが最新の状態になるように、マイグレーションが順番に実行されます。

As described in the previous section, if a test run is forcefully interrupted, the test database may not be destroyed. On the next run, you'll be asked whether you want to reuse or destroy the database. Use the `test --noinput` option to suppress that prompt and automatically destroy the database. This can be useful when running tests on a continuous integration server where tests may be interrupted by a timeout, for example.

テストデータベースのデフォルトの名前は、 `DATABASES` 設定内の各 `NAME` の値の前に `test_` を付けたものになります。SQLite を使っているときは、デフォルトでは、テストにはインメモリのデータベースを使います (つまり、データベースはメモリ内に作成されるため、ファイルシステムへのアクセスを完全になくすことができるのです！)。設定の `DATABASES` 内の `TEST` ディクショナリには、テストデータベースに対するいろいろな設定を書くことができます。例えば、別のデータベース名を指定したければ、 `TEST` ディクショナリの `NAME` に、 `DATABASES` の中から好きなデータベースを選んで指定することができます。

PostgreSQL では、 `USER` が、ビルトインの `postgres` データベースへの読み取りアクセス権も持っている必要があります。

テストランナーの使うデータベースは、独立したデータベースだけでなく、設定ファイルで指定した通りのデータベースを使用させることもできます: `ENGINE`, `USER`, `HOST`, などです。テストデータベースは、`USER` で指定されたユーザによって作成されるため、そのユーザアカウントがシステム上で新しくデータベースを作成できる権限を持っている必要があります。

テストデータベースの文字エンコーディングに対するきめ細かい対応をするために、`CHARSET` TEST オプションを使用してください。MySQL を使用している場合は、`COLLATION` オプションを使用してテストデータベースが使用する特別な照合をコントロールすることができます。 これらおよびより進歩的な設定の詳細については、設定のドキュメント を参照してください。

If using an SQLite in-memory database with SQLite, shared cache is enabled, so you can write tests with ability to share the database between threads.

Finding data from your production database when running tests?

If your code attempts to access the database when its modules are compiled, this will occur before the test database is set up, with potentially unexpected results. For example, if you have a database query in module-level code and a real database exists, production data could pollute your tests. It is a bad idea to have such import-time database queries in your code anyway - rewrite your code so that it doesn't do this.

This also applies to customized implementations of `ready()`.

参考

The advanced multi-db testing topics.

### テストの実行順序

すべての `TestCase` コードがクリーンなデータベースで実行されることを保証するために、Django のテストランナーは次の方法でテストの実行順序を決定します。

- すべての `TestCase` サブクラスが最初に実行されます。
- つぎに、すべての Django ベースのテスト (`TransactionTestCase` を含む `SimpleTestCase` から作ったテストケース) を、実行順序が保証されず、また強制もされないような適当な順番で実行します。
- 最後に、その他の `unittest.TestCase` テスト (doctests を含む) が実行されます。このテストの中には、データベースを変更し、そのまま元の状態に戻さないようなテストがあることもあります。

注釈

この新しいテスト順序は、テストケース順序の予期しない依存関係を明らかにするかもしれません。これは、`TransactionTestCase` によってデータベース内に記述された宣言に依存する doctests のケースで、これらは独立的に実行できるように修正する必要があります。

注釈

Failures detected when loading tests are ordered before all of the above for quicker feedback. This includes things like test modules that couldn't be found or that couldn't be loaded due to syntax errors.

You may randomize and/or reverse the execution order inside groups using the `test --shuffle` and `--reverse` options. This can help with ensuring your tests are independent from each other.

Changed in Django 4.0:

In older versions, failures detected when loading tests were not ordered first.

### ロールバックのエミュレーション

マイグレーションで呼び出されるあらゆる初期データは、`TestCase` テスト内のみで有効で、 `TransactionTestCase` 内では無効です。加えて、トランザクションがサポートされるバックエンドのみで有効です (最も重要な例外は MyISAM です)。これは、`LiveServerTestCase` や `StaticLiveServerTestCase` といった `TransactionTestCase` に依存するテストに関しても同様です。

Django can reload that data for you on a per-testcase basis by setting the `serialized_rollback` option to `True` in the body of the `TestCase` or `TransactionTestCase`, but note that this will slow down that test suite by approximately 3x.

Third-party apps or those developing against MyISAM will need to set this; in general, however, you should be developing your own projects against a transactional database and be using `TestCase` for most tests, and thus not need this setting.

The initial serialization is usually very quick, but if you wish to exclude some apps from this process (and speed up test runs slightly), you may add those apps to `TEST_NON_SERIALIZED_APPS`.

To prevent serialized data from being loaded twice, setting `serialized_rollback=True` disables the `post_migrate` signal when flushing the test database.

### その他のテストに関する条件

設定ファイルで指定した `DEBUG` の値にかかわらず、Django のテストは `DEBUG`=False を指定したものとして実行されます。これは、表示されるコードの出力が、実際の環境設定で見られるものと同じになるようにするためです。

Caches are not cleared after each test, and running `manage.py test fooapp` can insert data from the tests into the cache of a live system if you run your tests in production because, unlike databases, a separate "test cache" is not used. This behavior may change in the future.

### テストの出力を理解する

テストを実行すると、テストランナーが用意したたくさんのメッセージが表示されます。表示するメッセージの詳細レベルは、コマンドラインで `verbosity` オプションを指定することで、自由にコントロールできます。

    Creating test database...
    Creating table myapp_animal
    Creating table myapp_mineral

このメッセージは、テストランナーが前のセクションで説明したテスト用のデータベースを作成していることを表しています。

テスト用データベースが作成されると、Django はテストを実行します。すべてのテストが成功すれば、次のようなメッセージが表示されるはずです。

    ----------------------------------------------------------------------
    Ran 22 tests in 0.221s

    OK

しかし、もしテストが失敗した場合には、どのテストが失敗したのかとその詳細が表示されます。

    ======================================================================
    FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
        self.assertIs(future_poll.was_published_recently(), False)
    AssertionError: True is not False

    ----------------------------------------------------------------------
    Ran 1 test in 0.003s

    FAILED (failures=1)

このエラー出力の詳しい説明は、このドキュメントの範囲外ですが、極めて直感的に理解できるものです。詳しく知りたければ、Python の `unittest` ライブラリのドキュメントを読んでみてください。

Note that the return code for the test-runner script is 1 for any number of failed tests (whether the failure was caused by an error, a failed assertion, or an unexpected success). If all the tests pass, the return code is 0. This feature is useful if you're using the test-runner script in a shell script and need to test for success or failure at that level.

Changed in Django 4.1:

In older versions, the return code was 0 for unexpected successes.

### テストのスピードアップ

#### テストの並列実行

各テストが適切に独立性を保ったものであれば、マルチコアのハードウェア上でテストを並列実行することでスピートアップさせることができます。詳しくは `test --parallel` を読んでください。

#### パスワードのハッシュ生成

デフォルトのパスワードのハッシュ生成器は、設計上、時間のかかるものになっています。テストの中で多数のユーザーを認証する必要がある場合、カスタムの設定ファイルを用意して、`PASSWORD_HASHERS` 設定に、より高速なハッシュ生成アルゴリズムを設定すると良いでしょう。

    PASSWORD_HASHERS = [
        'django.contrib.auth.hashers.MD5PasswordHasher',
    ]

`PASSWORD_HASHERS` には、必要なハッシュアルゴリズムが複数あっても、追加しておくことを忘れないようにしてください。

#### テストデータベースを保存する

`test --keepdb` オプションで、テスト間でテストデータベースを保存することができます。テスト実行の際、データベース作成および破棄にかかる時間を大幅に短縮できます。