# Django 6.0.7 ドキュメント

# テストツール

Django は、テストを書くのに便利なツールをいくつか提供しています。

## テストクライアント

テストクライアントは、ダミーのウェブブラウザとして振る舞う Python のクラスです。これを使えば、ビューと Django で作ったアプリケーションとの関係をプログラムから自動でテストできるようになります。

テストクライアントでは、次のようなことができます。

- ある URL に対する GET および POST リクエストのシミュレートと、その結果の観察。低レベルの HTTP (レスポンスのヘッダーやステータスコードなど) から、ページのコンテンツまで、あらゆるレスポンスの内容を調査できます。

- 一連の (好きな数の) リダイレクトを見て、その各ステップごとに URL とステータスコードをチェックする。

- 指定したリクエストが特定の Django テンプレートによってレンダリングされたとき、テンプレートのコンテキストが正しく特定の値を含んでいるかどうかをテストする。

テストクライアントは Selenium や他の "ブラウザ内 (in-browser)" フレームワークの代替を目指すものではないことに注意してください。Django のテストクライアントの目的は別の点にあります。つまり、

- Django のテストクライアントは、正しいテンプレートがレンダリングされ、そのテンプレートが正しいコンテキストデータをちゃんと渡しているのかをチェックするために使います。

- ビューの機能を直接テストするには、`RequestFactory` を使用して、ルーティングとミドルウェアのレイヤーをバイパスしてください。

- Selenium などのブラウザー内フレームワークは、HTML の レンダリング や、ウェブページの 振る舞い 、つまり JavaScript の機能性をテストするために使います。また、Django はこれらのフレームワーク向けの特別なサポートも提供しています。詳細については、`LiveServerTestCase` のセクションを読んでください。

包括的なテストスイートを実現するには、これらすべてのタイプのテストを組み合わせて行うべきです。

### 概要と簡単な例

テストクライアントを使うには、`django.test.Client` からインスタンスを作り、次のようにウェブページを取得します。

    >>> from django.test import Client
    >>> c = Client()
    >>> response = c.post("/login/", {"username": "john", "password": "smith"})
    >>> response.status_code
    200
    >>> response = c.get("/customer/details/")
    >>> response.content
    b'<!DOCTYPE html...'

この例が示唆しているように、 `Client` のインスタンスは、Python のインタラクティブなインタプリタ上のセッションからでも作ることができます。

テストクライアントの動作の仕方に関して、いくつか大切な注意点があります。

- テストクライアントが動作するために、ウェブサーバーが動作している必要は ありません 。実際、ウェブサーバーを一切起動せずに動作するのです！ HTTP のオーバーヘッドを避けて、Django フレームワークと直接やりとりすることでこれを実現しています。これにより、高速なユニットテストが可能になっています。

- ページの取得時には、ドメイン全体ではなく、URL の path だけを指定することを覚えておいてください。たとえば、次は正しいです。

      >>> c.get("/login/")

  しかし、これは間違いです。

      >>> c.get("https://www.example.com/login/")

  テストクライアントには、自分の Django プロジェクト以外のウェブページを取得する機能はありません。他のウェブページが必要な場合には、 `urllib` などの Python のスタンダードライブラリモジュールを利用してください。

- URL を解決するとき、テストクライアントは `ROOT_URLCONF` 設定で指定されたすべての URLconf を使用します。

- 上の例では Python のインタラクティブなインタプリタ上でも動作するはずですが、テストクライアントの一部の機能、特にテンプレート関係の機能は、 テストの実行中 にしか使えないことがあります。

  というのも、Django のテストランナーは、与えられたビューによって読み込まれるテンプレートを決定する時に、ちょっとした黒魔術を使っています。この黒魔術 (具体的には Django のテンプレートシステムに対してメモリ上でパッチを当てています) は、テストの実行中にだけ使われるのです。

- デフォルトでは、テストクライアントはサイト上でのすべての CSRF チェックを無効にしています。

  何らかの理由でテストクライアントに CSRF チェックを実行して ほしい ときには、CSRF チェックの実行を強制するテストクライアントのインスタンスを作ることができます。これには、クライアントを作る時に次のように `enforce_csrf_checks` 引数を渡します。

      >>> from django.test import Client
      >>> csrf_client = Client(enforce_csrf_checks=True)

### リクエストの作成

リクエストの作成には、`django.test.Client` クラスを使います。

class Client(enforce_csrf_checks=False, raise_request_exception=True, json_encoder=DjangoJSONEncoder, *, headers=None, query_params=None, **defaults)

  テスト用の HTTP クライアントです。いくつかの引数で動作をカスタマイズできます。

  `headers` にはリクエストごとに送信されるデフォルトのヘッダを指定できます。例えば、 `User-Agent` ヘッダの場合:

      client = Client(headers={"user-agent": "curl/7.79.1"})

  `query_params` を使用すると、すべてのリクエストに設定されるデフォルトのクエリ文字列を指定できます。

  `Defaults` 内の任意のキーワード引数には WSGI 環境変数 を指定します。例えば、スクリプト名の場合:

      client = Client(SCRIPT_NAME="/app/")

  注釈

  `HTTP_` プレフィックスで始まるキーワード引数がヘッダーとして設定されますが、可読性のために `headers` パラメーターの使用を推奨します。

  The values from the `headers`, `query_params`, and `extra` keyword arguments passed to `get()`, `post()`, etc. have precedence over the defaults passed to the class constructor.

  `enforce_csrf_checks` 引数を使うと、CSRF プロテクションのテストが実行できます (上の説明を参照)。

  `raise_request_exception` 引数を指定することで、リクエスト中に発生した例外をテストでも発生させるかどうかを制御できます。デフォルトは `True` です。

  `json_encoder` 引数を指定すると、 `post()` に記述されているJSONシリアライズ用のカスタムJSONエンコーダを指定できます。

  `Client` インスタンスを一度作れば、以下のメソッドを自由に使うことができます。

  get(path, data=None, follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して GET リクエストを作り、`Response` オブジェクトを返します。`Response` オブジェクトについては、下のセクションにドキュメントされています。

    `query_params` に渡された辞書のキーと値のペアは、クエリ文字列の設定に使用されます。例えば、次のように使います。

        >>> c = Client()
        >>> c.get("/customers/details/", query_params={"name": "fred", "age": 7})

    引数の評価の結果、次の GET リクエストの実行と等価になります。

        /customers/details/?name=fred&age=7

    これらのパラメータを `data` パラメータに渡すことも可能です。しかし、`query_params` を使用する方が推奨されます。なぜなら、`query_params` はすべてのHTTPメソッドで動作するからです。

    `headers` 引数は、リクエスト時に送信されるヘッダーの指定に使われます。たとえば、次のコード

        >>> c = Client()
        >>> c.get(
        ...     "/customers/details/",
        ...     query_params={"name": "fred", "age": 7},
        ...     headers={"accept": "application/json"},
        ... )

    ...will send the HTTP header `HTTP_ACCEPT` to the details view, which is a good way to test code paths that use the `django.http.HttpRequest.accepts()` method.

    任意のキーワード引数には、WSGI 環境変数 を指定します。たとえば、スクリプト名を設定するヘッダの場合:

        >>> c = Client()
        >>> c.get("/", SCRIPT_NAME="/app/")

    GET の引数がすでに URL エンコードされた形式である場合は、data 引数の代わりにエンコード済みの文字列を使うことができます。たとえば、先ほどの GET リクエストは次のようにも書けます。

        >>> c = Client()
        >>> c.get("/customers/details/?name=fred&age=7")

    エンコード済みのGETデータを含むURLと `query_params` または `data` 引数の両方を指定した場合、これらの引数が優先されます。

    `follow` を `True` を与えると、クライアントはすべてのリダイレクトを辿り、途中の URL とステータスコードのタプルが、レスポンスオブジェクトの `redirect_chain` 属性に追加されてゆきます。

    たとえば、URL `/redirect_me/` が `/next/` にリダイレクトし、それがさらに `/final/` にリダイレクトするような場合には、`redirect_chain` は次のような値になります。

        >>> response = c.get("/redirect_me/", follow=True)
        >>> response.redirect_chain
        [('http://testserver/next/', 302), ('http://testserver/final/', 302)]

    `secure` を `True` に設定すると、クライアントは HTTPS リクエストをエミュレートします。

  post(path, data=None, content_type=MULTIPART_CONTENT, follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して POST リクエストを作り、`Response` オブジェクトを返します。`Response` オブジェクトについては、下のセクションにドキュメントされています。

    `data` ディクショナリ内の key-value ペアは、POST データを送信するのに使われます。例えば、次の例では、

        >>> c = Client()
        >>> c.post("/login/", {"name": "fred", "passwd": "secret"})

    引数の評価の結果、次の URL へ POST リクエストが行われます。

        /login/

    リクエストで送られる POST データは次のものになります。

        name=fred&passwd=secret

    `content_type` に application/json を指定すると、 `data` が dict、リスト、タプルの場合、 `json.dumps()` を使ってシリアライズされます。デフォルトでは `DjangoJSONEncoder` でシリアライズを行いますが、 `Client` に `json_encoder` 引数を指定することでオーバーライドできます。このシリアライズは `put()`, `patch()`, `delete()` リクエストでも行われます。

    もし他の `content_type` (たとえば、XML データの場合は text/xml) を与えると、`data` のコンテンツは、HTTP の `Content-Type` ヘッダーの中で `content_type` を使ったものとして、POST リクエストで送られます。

    `content_type` に値を渡さなかったときは、`data` 内の値を multipart/form-data のコンテンツタイプとして送信します。この場合は、 `data` 内のkey-value ペアが multipart メッセージにえんこーどされ、POST データを生成するのに使われます。

    たとえば `<select multiple>` の複数の選択を指定する場合のように、特定のキーに対して複数の値を送信したいときは、必要なキーに対する値をリストまたはタプルとして与えます。たとえば、 `data` に次の値を与えれば、3つの選択した値を `choice` という名前のフィールドに対して送信できます。

        {"choices": ["a", "b", "d"]}

    ファイルの送信は特別なケースです。ファイルをPOSTするには、キーとしてファイルフィールド名を、値としてアップロードしたいファイルへのファイルハンドルを渡すだけで十分です。例えば、フォームに `name` と `attachment` のフィールドがあり、後者が `FileField` の場合:

        >>> c = Client()
        >>> with open("wishlist.doc", "rb") as fp:
        ...     c.post("/customers/wishes/", {"name": "fred", "attachment": fp})
        ...

    また、ファイルのようなオブジェクト (例えば `StringIO` や `BytesIO`) をファイルハンドルとして指定することもできます。もし `ImageField` にアップロードする場合、オブジェクトには `validate_image_file_extension` バリデータを渡す `name` 属性が必要です。たとえば下記のようにします:

        >>> from io import BytesIO
        >>> img = BytesIO(
        ...     b"GIF89a\x01\x00\x01\x00\x00\x00\x00!\xf9\x04\x01\x00\x00\x00"
        ...     b"\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01\x00\x00"
        ... )
        >>> img.name = "myimage.gif"

    複数の `post()` の呼び出しに対して同じファイルハンドラを使う時には、post 間でファイルポインタを手動でリセットする必要があります。これを一番簡単に扱う方法は、上に示したように、ファイルが `post()` に与えられた後に手動でファイルを close することです。

    データが読み込めるように、正しい方法でファイルを開くようにする必要があります。これはつまり、画像ファイルなどのバイナリデータが含まれている場合には、`rb` (read binary、バイナリ読み込み) モードで開かなければならないということです。

    `headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同じように動作します。

    POST でリクエストした URL にエンコード済みパラメータが含まれている場合には、これらのデータは request.GET データから利用できます。たとえば、次のようなリクエストを行った場合、

        >>> c.post(
        ...     "/login/", {"name": "fred", "passwd": "secret"}, query_params={"visitor": "true"}
        ... )

    このリクエストをハンドリングするビューでは、request.POST からはユーザー名とパスワードを取得し、request.GET からはユーザーが visitor であるかどうかを特定できます。

    `follow` を `True` を与えると、クライアントはすべてのリダイレクトを辿り、途中の URL とステータスコードのタプルが、レスポンスオブジェクトの `redirect_chain` 属性に追加されてゆきます。

    `secure` を `True` に設定すると、クライアントは HTTPS リクエストをエミュレートします。

  head(path, data=None, follow=False, secure=False, *, headers=None, query_params=None, **extra)

    指定された `path` に対して HEAD リクエストを行い、`Response` オブジェクトを返します。このメソッドは `Client.get()` と同様に動作しますが、`follow`、`secure`、`headers`、`query_params`、および `extra` パラメータを含みます。ただし、メッセージボディは返されません。

  options(path, data='', content_type='application/octet-stream', follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して OPTION リクエストを作り、`Response` オブジェクトを返します。RESTful インターフェイスのテスト時に有用です。

    `data` が与えられると、request body として使われます。 `content_type` は `Content-Type` ヘッダーに設定されます。

    `follow`、`secure`、`headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同様に動作します。

  put(path, data='', content_type='application/octet-stream', follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して PUT リクエストを作り、`Response` オブジェクトを返します。RESTful インターフェイスのテスト時に有用です。

    `data` が与えられると、request body として使われます。 `content_type` は `Content-Type` ヘッダーに設定されます。

    `follow`、`secure`、`headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同様に動作します。

  patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して PATCH リクエストを作り、`Response` オブジェクトを返します。RESTful インターフェイスのテスト時に有用です。

    `follow`、`secure`、`headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同様に動作します。

  delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して DELETE リクエストを作り、`Response` オブジェクトを返します。RESTful インターフェイスのテスト時に有用です。

    `data` が与えられると、request body として使われます。 `content_type` は `Content-Type` ヘッダーに設定されます。

    `follow`、`secure`、`headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同様に動作します。

  trace(path, follow=False, secure=False, *, headers=None, query_params=None, **extra)

    与えられた `path` に対して TRACE リクエストを作り、`Response` オブジェクトを返します。診断のための調査をシミュレートするときに役に立ちます。

    他のリクエストメソッドとは違い、 `data` がキーワード引数にありません。 RFC 9110 Section 9.3.8 に従うためです。そのため、TRACE リクエストには body を含むことが禁止されています。

    `follow`、`secure`、`headers`、`query_params`、および `extra` パラメータは、`Client.get()` の場合と同様に動作します。

  login(**credentials)
  alogin(**credentials)

    非同期バージョン: `alogin()`

    あなたのサイトが Django の 認証システム を使っていて、ユーザーのログインをテストしたければ、テストクライアントの `login()` メソッドを使うことで、ユーザーがサイトにログインしたときの状況をシミュレートできます。

    このメソッドを呼ぶ事で、テストクライアントはログインに基づいてビューを形成するテストを行う上で必要なクッキーとセッション情報を全て持ちます。

    引数 `credentials` の形式は利用している (`AUTHENTICATION_BACKENDS` の設定値に定義されています) 認証バックエンド に依存します。Django によって提供される標準の認証バックエンド (`ModelBackend`) を用いている場合は、 `credentials` は利用者のユーザー名とパスワードであり、キーワード引数として渡されます:

        >>> c = Client()
        >>> c.login(username="fred", password="secret")

        # Now you can access a view that's only available to logged-in users.

    もし標準以外の認証バックエンドを利用している場合、このメソッドは異なった認証情報を必要とします。この値では利用している認証バックエンドの `authenticate()` メソッドによって要求される認証情報が必要になります。

    `login()` returns `True` if the credentials were accepted and login was successful.

    Finally, you'll need to remember to create user accounts before you can use this method. As we explained above, the test runner is executed using a test database, which contains no users by default. As a result, user accounts that are valid on your production site will not work under test conditions. You'll need to create users as part of the test suite -- either manually (using the Django model API) or with a test fixture. Remember that if you want your test user to have a password, you can't set the user's password by setting the password attribute directly -- you must use the `set_password()` function to store a correctly hashed password. Alternatively, you can use the `create_user()` helper method to create a new user with a correctly hashed password.

  force_login(user, backend=None)
  aforce_login(user, backend=None)

    非同期バージョン: `aforce_login()`

    あなたのサイトが Django の 認証システム を使っている場合、 `force_login()` メソッドを使うと、ユーザがサイトにログインしたときの影響をシミュレーションできます。テストがユーザのログインを必要とするが、ユーザがどのようにログインしたかの詳細は重要ではない場合には `login()` の代わりにこのメソッドを使用してください。

    `login()` とは異なり、このメソッドは認証と確認のステップを省略します。アクティブでないユーザ (`is_active=False`) もログインを許可され、ユーザの認証情報を提供する必要はありません。

    ユーザーには、 `backend` 引数の値（ドットで区切られたPythonパスの文字列であるべき）が `backend` 属性としてセットされます。値が指定されていない場合は、 `settings.AUTHENTICATION_BACKENDS[0]` に設定されます。 `login()` によって呼び出される `authenticate()` 関数は、通常このようにユーザーにアノテーションを付けます。

    このメソッドは、高コストなパスワードハッシングアルゴリズムを回避するため、 `login()` よりも高速です。また、 テストに弱いハッシャーを使う ことで、 `login()` 処理を高速にすることもできます。

  logout()
  alogout()

    非同期バージョン: `alogout()`

    あなたのサイトが Django の 認証システム を使っている場合、 `logout()` メソッドを使うと、ユーザがサイトからログアウトしたときの効果をシミュレートできます。

    このメソッドを呼び出した後、テストクライアントはすべてのクッキーとセッションデータをデフォルトにクリアします。それ以降のリクエストは `AnonymousUser` から来たように見えるでしょう。

### レスポンスのテスト

`get()` および `post()` メソッドは、両方とも `Response` オブジェクトを返します。この `Response` オブジェクトは、Django のビューによって返される `HttpResponse` オブジェクトとは 異なるもの であり、テストのレスポンスには、テストコードの検証に便利な追加データがいくつかあります。

特に、`Response` オブジェクトは以下の属性を持ちます:

class Response
  client

    レスポンスの結果の元となるリクエストを作るために使われた、テストクライアントです。

  content

    Bytestring としてのレスポンスの本文です。ビューないしエラーメッセージによってレンダリングされる際の最終的なページコンテンツです。

  context

    テンプレートの `Context` インスタンスです。レスポンスの content を生成するテンプレートをレンダリングする際に使われます。

    描画されたページが複数のテンプレートを使っていた場合、`context` は `Context` オブジェクトのリストとなり、その順序はレンダリングされた順となります。

    レンダリングに使われるテンプレートの数にかかわらず、`[]` オペレータを使ってコンテキストの値を取り出すことができます。たとえば、コンテキストの変数 `name` は以下のように取り出せます。

        >>> response = client.get("/foo/")
        >>> response.context["name"]
        'Arthur'

    Django のテンプレートを使っていない？

    この属性は、`DjangoTemplates` バックエンドを使用しているときのみ格納されます。他のテンプレートエンジンを使っている場合、`context_data` がこの属性を扱うレスポンスの適切な選択肢となるでしょう。

  exc_info

    ビュー中で発生した未処理の例外 (もし存在すれば) に関する情報を提供する3つの値のタプル。

    値は (type, value, traceback) であり、Python の `sys.exc_info()` が返すのと同じものです。それぞれの値の意味は以下のとおりです。

    - type: 例外の型。

    - value: 例外インスタンス。

    - traceback: 例外がもともと発生した場所におけるロールスタックをカプセル化した、トレースバックオブジェクト。

    例外が発生しなかった場合、`exc_info` は `None` になります。

  json(**kwargs)

    JSON としてパースされた、レスポンスの本文です。追加のキーワード引数が `json.loads()` に渡されます。たとえば、次のようになります。

        >>> response = client.get("/foo/")
        >>> response.json()["name"]
        'Arthur'

    `Content-Type` ヘッダが `"application/json"` ではない場合、レスポンスをパースする際に `ValueError` が投げられます。

  request

    レスポンスを機能させるリクエストデータです。

  wsgi_request

    レスポンスを生成したテストハンドラーによって生成された `WSGIRequest` インスタンス。

  status_code

    レスポンスの HTTP ステータスで、数値です。 定義済みのコードの全リストは、IANA status code registry を参照してください。

  templates

    最終コンテンツをレンダリングするときに使われる `Template` インスタンスのリストで、 レンダリングされる順となります。テンプレートがファイルから読み込まれる場合、テンプレートのファイル名を取得するためには、リスト内の各テンプレートに対して `template.name` を使ってください (名前は `'admin/index.html'` のような文字列となります)。

    Django のテンプレートを使っていない？

    この属性は、`DjangoTemplates` バックエンドを使用しているときのみ格納されます。他のテンプレートを知使っている場合、`template_name` が、レンダリングに使われるテンプレートの名前のみが必要な場合の適切な代替策となるでしょう。

  resolver_match

    レスポンスに対する `ResolverMatch` のインスタンスです。たとえば、次のようにレスポンスを提供するビューを検証するために `func` 属性を使えます。

        # my_view here is a function based view.
        self.assertEqual(response.resolver_match.func, my_view)

        # Class-based views need to compare the view_class, as the
        # functions generated by as_view() won't be equal.
        self.assertIs(response.resolver_match.func.view_class, MyView)

    指定された URL が見つからない場合、この属性にアクセスすると `Resolver404` 例外が投げられます。

通常のレスポンスと同様に、`HttpResponse.headers` 経由でヘッダにアクセスできます。たとえば、レスポンスの content type は、`response.headers['Content-Type']` を使って決定できます。

### 例外

例外を発生させるビューをテストクライアントで指定し、`Client.raise_request_exception` が `True` である場合、例外はテストケース内で可視化されます。その後、標準の `try ... except` ブロックを使うか、`assertRaises()` で例外をテストできます。

テストクライアントに可視化されない唯一の例外は、`Http404`、`PermissionDenied`、`SystemExit`、`SuspiciousOperation` です。Django はこれらの例外を内部でキャッチし、適切な HTTP レスポンスコードに変換します。これらの場合、テストでは `response.status_code` をチェックできます。

`Client.raise_request_exception` が `False` の場合、テストクライアントはブラウザに返されることになる 500 レスポンスを返します。レスポンスには `exc_info` 属性があり、未処理の例外に関する情報が提供されます。

### 永続的なステート

テストクライアントはステートフルです。レスポンスがクッキーを返す場合、そのクッキーはテストクライアント内に保持され、以降すべての `get()` および `post()` リクエストともに送信されます。

クッキーに対する有効期限ポリシーは使えません。クッキーを期限切れにしたい場合、手動で削除するか、新たに (すべてのクッキーを削除するために) `Client` を作成してください。

テストクライアントは、永続的なステート情報を保持する属性を持ちます。テスト条件の一環として、これらのプロパティにアクセスできます。

Client.cookies

  Python の `SimpleCookie` オブジェクトで、すべてのクライアントのクッキーの現在の値を含みます。より詳しくは、`http.cookies` のドキュメントを参照してください。

Client.session

  辞書形式のようなオブジェクトで、セッション情報を含みます。セッションのドキュメント に網羅的情報があります。

  セッションを修正し保存するためには、まず変数に格納される必要があります (新しい `SessionStore` は、この属性がアクセスされるたびに作られるためです):

      def test_something(self):
          session = self.client.session
          session["somekey"] = "test"
          session.save()

Client.asession()

  `session` 属性と同様ですが、非同期コンテキストで動作します。

### 言語の設定

国際化とローカライズをサポートしているアプリケーションをテストする際、テストクライアントのリクエストに対して言語を設定するのがよいでしょう。その方法は、`LocaleMiddleware` が有効化されているか否かによって異なります。

ミドルウェアが有効化されている場合、`LANGUAGE_COOKIE_NAME` の名前でクッキーを作成することでセットすることができ、言語コードの値は次のようになります。

    from django.conf import settings

    def test_language_using_cookie(self):
        self.client.cookies.load({settings.LANGUAGE_COOKIE_NAME: "fr"})
        response = self.client.get("/")
        self.assertEqual(response.content, b"Bienvenue sur mon site.")

もしくは、`Accept-Language` HTTP ヘッダをリクエスト内に含めます。

    def test_language_using_header(self):
        response = self.client.get("/", headers={"accept-language": "fr"})
        self.assertEqual(response.content, b"Bienvenue sur mon site.")

注釈

これらのメソッドを使用するときは、必ず各テストの最後にアクティブな言語をリセットしてください。

    def tearDown(self):
        translation.activate(settings.LANGUAGE_CODE)

さらなる詳細は Django はどうやって言語の優先順位を検出するのか？ にあります。

ミドルウェアが有効化されていない場合、アクティブな言語は `translation.override()` を使って設定できます。

    from django.utils import translation

    def test_language_using_override(self):
        with translation.override("fr"):
            response = self.client.get("/")
        self.assertEqual(response.content, b"Bienvenue sur mon site.")

さらなる詳細は 明示的にアクティブな言語をセットする にあります。

### カスタマイズ例

以下は、テストクライアントを使ったユニットテストです。

    import unittest
    from django.test import Client

    class SimpleTest(unittest.TestCase):
        def setUp(self):
            # Every test needs a client.
            self.client = Client()

        def test_details(self):
            # Issue a GET request.
            response = self.client.get("/customer/details/")

            # Check that the response is 200 OK.
            self.assertEqual(response.status_code, 200)

            # Check that the rendered context contains 5 customers.
            self.assertEqual(len(response.context["customers"]), 5)

参考

`django.test.RequestFactory`

## 提供されるテストケースのクラス

標準の Python ユニットテストのクラスは、`unittest.TestCase` のベースクラスを拡張しています。Django は、このベースクラスのいくつかの拡張を提供します。

Django ユニットテストクラスの階層

通常の `unittest.TestCase` は、任意のサブクラスに変換できます。つまり、テストのベースクラスを `unittest.TestCase` からサブクラスに変更します。すべての標準の Python のユニットテスト機能が利用可能なまま、以下の各セクションで説明するような便利な追加機能を追加できます。

### `SimpleTestCase`

class SimpleTestCase

以下の機能を追加する、`unittest.TestCase` のサブクラスです。

- 便利なアサーションには以下のようなものがあります。

  Assertion | What it checks
  --- | ---
  `assertRaisesMessage()` | That a callable raises a certain exception
  `assertWarnsMessage()` | That a callable triggers a certain warning
  `assertFieldOutput()` | Form field rendering and error output
  `assertContains()` | Presence or absence of HTML fragments
  `assertTemplateUsed()` | Template usage in a response
  `assertURLEqual()` | That two URLs are equal
  `assertRedirects()` | That an HTTP redirect occurred
  `assertHTMLEqual()` | HTML fragment equality
  `assertInHTML()` | HTML fragment containment
  `assertXMLEqual()` | XML fragment equality or inequality
  `assertJSONEqual()` | JSON fragment equality

- 編集した設定 でテストを実行する機能。

- `client` `Client` を使う。

データベースクエリを作る手薄との場合、サブクラス `TransactionTestCase` や `TestCase` を使用してください。

SimpleTestCase.databases

  `SimpleTestCase` はデフォルトでデータベースクエリを許可しません。各 `SimpleTestCase` テストはトランザクション内で実行されないため、これにより、他のテストに影響する書き込みクエリの実行を避けられます。この問題が心配でない場合は、テストクラスの `databases` クラス属性を `'__all__'` に設定することで、この振る舞いを無効化できます。

警告

`SimpleTestCase` とそのサブクラス (例: `TestCase` など) は、クラス横断的な初期化を実現するために `setUpClass()` と `tearDownClass()` に依存しています (例: 設定のオーバーライド)。これらをオーバーライドする必要があるときは、次のように `super` 実装を呼び出すのを忘れないでください。

    class MyTestCase(TestCase):
        @classmethod
        def setUpClass(cls):
            super().setUpClass()
            ...

        @classmethod
        def tearDownClass(cls):
            ...
            super().tearDownClass()

`setUpClass()` で例外が発生した場合の Python の動作を必ず考慮してください。もし例外が起きた場合は、クラス内のテストも `tearDownClass()` も実行されません。`django.test.TestCase` の場合、`super()` 内で作成されたトランザクションがリークし、一部のプラットフォーム (macOS で報告されています) での segmentation fault を含む、さまざまな症状が起きる結果となります。`setUpClass()` 内での `unittest.SkipTest` などの例外を意図的に発生させたい場合は、この問題を避けるために、必ず `super()` を呼び出す前に実行するようにしてください。

### `TransactionTestCase`

class TransactionTestCase

`TransactionTestCase` は `SimpleTestCase` を継承し、以下のようなデータベースに特有の機能を追加しています。

- 各テストの終了時にデータベースを既知の状態にリセットすることで、テストの実施や ORM の利用を容易にします。

- データベースの `fixtures`。

- テストの データベースバックエンドの機能をもとにしたスキップ。

- それ以外の特別な `assert*` メソッド。

Django's `TestCase` class is a more commonly used subclass of `TransactionTestCase` that makes use of database transaction facilities to speed up the process of resetting the database to a known state at the end of each test. A consequence of this, however, is that some database behaviors cannot be tested within a Django `TestCase` class. For instance, you cannot test that a block of code is executing within a transaction, as is required when using `select_for_update()`. In those cases, you should use `TransactionTestCase`.

`TransactionTestCase` と `TestCase` は、以下のように、データベースを既知の状態にリセットする方法と、コミットとロールバックの効果をテストするコードの機能を除いて同一です。

- `TransactionTestCase` は、テスト実行後にすべてのテーブルを truncate することでデータベースをリセットします。`TransactionTestCase` はコミットとロールバックを呼び出して、これらの呼び出しのデータベースへの効果を観察できます。

- 一方、`TestCase` は、テスト後にテーブルを truncate しません。代わりに、テスト終了時にロールバックされるデータベーストランザクション内にテストコードを含めます。これにより、テスト終了時のロールバックによりデータベースが初期状態に復元されることを保証します。

警告

ロールバックをサポートしないデータベース (例: MyISAM ストレージエンジンを使用した MySQL) 上で実行される `TestCase` と、`TransactionTestCase` のすべてのインスタンスは、テスト終了時にテストデータベースからすべてのデータを削除することによってロールバックされます。

アプリは データの再読み込みを確認しません。そのため、この機能が必要な場合には (たとえば、サードパーティのアプリはこれを有効化する必要があります)、`TestCase` 本体内で `serialized_rollback = True` を設定できます。

### `TestCase`

class TestCase

これは、Django でテストを書く際に使われる、最も一般的なクラスです。`TransactionTestCase` (および、拡張による `SimpleTestCase`) を継承します。あなたの Django アプリケーションがデータベースを使用しない場合は、`SimpleTestCase` を使ってください。

クラス:

- 2 つのネストされた `atomic()` ブロックでテストをラップします。1 つはテスト全体、もう 1 つは各テストのためです。したがって、特定のデータベーストランザクションの振る舞いをテストしたい場合は、`TransactionTestCase` を使ってください。

- 各テストの最後に、deferrable なデータベース制約をチェックします。

さらに、以下のような追加メソッドを提供します。

classmethod TestCase.setUpTestData()

  上述のクラスレベルの `atomic` ブロックは、全体の `TestCase` に対して一度、クラスレベルでの初期データの作成を可能にします。 この技法により、`setUp()` を使うのに比べて高速なテストとなります。

  例:

      from django.test import TestCase

      class MyTests(TestCase):
          @classmethod
          def setUpTestData(cls):
              # Set up data for the whole TestCase
              cls.foo = Foo.objects.create(bar="Test")
              ...

          def test1(self):
              # Some test using self.foo
              ...

          def test2(self):
              # Some other test using self.foo
              ...

  テストがトランザクションサポートのないデータベース (たとえば MyISAM エンジンの MySQL) で実行される場合、各テストの前に `setUpTestData()` が呼ばれ、高速化のメリットはなくなります。

  Objects assigned to class attributes in `setUpTestData()` must support creating deep copies with `copy.deepcopy()` in order to isolate them from alterations performed by each test methods.

classmethod TestCase.captureOnCommitCallbacks(using=DEFAULT_DB_ALIAS, execute=False)

  指定されたデータベースコネクションに対する `transaction.on_commit()` コールバックをキャプチャしたコンテキストマネージャを返します。コンテキストの終了時に、キャプチャされたコールバック関数を含むリストを返します。このリストから、コールバック上のアサーションを作成したり、その副作用を起こすために呼び出したり、コミットをエミュレートしたりできます。

  `using` は、コールバックをキャプチャするためのデータベースコネクションのエイリアスです。

  `execute` が `True` の場合、コンテキストマネージャの終了時に、すべてのコールバックが呼ばれます。これは、ラップされたコードブロック後のコミットをエミュレートします。

  例:

      from django.core import mail
      from django.test import TestCase

      class ContactTests(TestCase):
          def test_post(self):
              with self.captureOnCommitCallbacks(execute=True) as callbacks:
                  response = self.client.post(
                      "/contact/",
                      {"message": "I like your site"},
                  )

              self.assertEqual(response.status_code, 200)
              self.assertEqual(len(callbacks), 1)
              self.assertEqual(len(mail.outbox), 1)
              self.assertEqual(mail.outbox[0].subject, "Contact Form")
              self.assertEqual(mail.outbox[0].body, "I like your site")

### `LiveServerTestCase`

class LiveServerTestCase

`LiveServerTestCase` は `TransactionTestCase` とほぼ同じですが、セットアップ時に実際の Django サーバーをバックグラウンドで起動し、終了時に破棄するという追加機能が1つあります。これにより、たとえば Selenium クライアントのような Django ダミークライアント 以外の自動化されたテストクライアントを使えるようになり、ブラウザ内での一連の機能テストを実施して、実際のユーザーの行動をシミュレートできます。

ライブサーバーは `localhost` をリッスンして、オペレーティングシステムが空きポートに割り当てるために使われるポート 0 にバインドします。サーバーの URL はテスト中は `self.live_server_url` でアクセスできます。

`LiveServerTestCase` の使用方法を紹介するために、Selenium テストを書いてみましょう。最初に、 selenium パッケージをインストールする必要があります。

/ 

    $ python -m pip install "selenium >= 4.23.0"

    ...\> py -m pip install "selenium >= 4.23.0"

その後、`LiveServerTestCase` ベースのテストをアプリのテストモジュール (例: `myapp/tests.py`) に追加します。たとえば、`staticfiles` アプリを使っていて、開発時に `DEBUG=True` を使用したときと同じように、つまり、`collectstatic` を使って静的ファイルを集める必要なく、静的ファイルがテストの実行中に配信されてほしいとします。その機能を提供する `StaticLiveServerTestCase` サブクラスを使うことになります。それが必要ない場合は、`django.test.LiveServerTestCase` で置き換えてください。

このテストに対するコードは、以下のようになるでしょう。

    from django.contrib.staticfiles.testing import StaticLiveServerTestCase
    from selenium.webdriver.common.by import By
    from selenium.webdriver.firefox.webdriver import WebDriver

    class MySeleniumTests(StaticLiveServerTestCase):
        fixtures = ["user-data.json"]

        @classmethod
        def setUpClass(cls):
            super().setUpClass()
            cls.selenium = WebDriver()
            cls.selenium.implicitly_wait(10)

        @classmethod
        def tearDownClass(cls):
            cls.selenium.quit()
            super().tearDownClass()

        def test_login(self):
            self.selenium.get(f"{self.live_server_url}/login/")
            username_input = self.selenium.find_element(By.NAME, "username")
            username_input.send_keys("myuser")
            password_input = self.selenium.find_element(By.NAME, "password")
            password_input.send_keys("secret")
            self.selenium.find_element(By.XPATH, '//input[@value="Log in"]').click()

最後に、次のようにテストを実行できます。

/ 

    $ ./manage.py test myapp.tests.MySeleniumTests.test_login

    ...\> manage.py test myapp.tests.MySeleniumTests.test_login

この例では、Firefox が自動的に開き、ログインページに行き、クレデンシャルを入力して、「Log in」ボタンをクリックします。Selenium は、Firefox をインストール済みでないか、他のブラウザを使いたいときのために、他のドライバも提供します。上の例は、Selenium クライアントができることのほんの一部に過ぎません。詳細については、完全なリファレンス を確認してください。

注釈

インメモリ SQLite データベースを使用してテストを実行する場合、同じデータベース接続を 2 つのスレッドで並行して共有します。ライブサーバを実行するスレッドとテストケースを実行するスレッドです。この 2 つのスレッドが共有接続を介して同時にデータベースをクエリしないようにすることが重要です。これは、テストがランダムに失敗する可能性があるからです。そのため、2 つのスレッドが同時にデータベースにアクセスしないようにする必要があります。特に、場合によっては (たとえばリンクをクリックしたりフォームを送信したりした直後に) Selenium がレスポンスを受け取り、次のページが読み込まれたことを確認してからテストを実行する必要があるかもしれません。たとえば、レスポンスの中に `<body>` という HTML タグが見つかるまで Selenium を待たせるには、下記のようにします (Selenium > 2.13 が必要です):

    def test_login(self):
        from selenium.webdriver.support.wait import WebDriverWait

        timeout = 2
        ...
        self.selenium.find_element(By.XPATH, '//input[@value="Log in"]').click()
        # Wait until the response is received
        WebDriverWait(self.selenium, timeout).until(
            lambda driver: driver.find_element(By.TAG_NAME, "body")
        )

ここで厄介なのは、特にサーバーが最初のドキュメントを生成した後に動的にHTMLを生成する最近のウェブアプリでは、「ページの読み込み」というものが実際には存在しないということです。そのため、レスポンスに `<body>` があるかどうかをチェックすることは、必ずしもすべてのユースケースに適しているとは限りません。詳しくは Selenium FAQ と Selenium documentation を参照してください。

## テストケースの機能

### デフォルトのテストクライアント

SimpleTestCase.client

`django.test.*TestCase` インスタンス内のすべてのテストケースは、Django のテストクライアントにアクセスできます。このクライアントは、`self.client` としてアクセスできます。このクライアントはテストごとに再作成されるため、(クッキーのような) ステートがテスト間で持ち越されることを心配する必要はありません。

つまり、各テスト内で `Client` をインスタンス化する代わりに、次のようにします。

    import unittest
    from django.test import Client

    class SimpleTest(unittest.TestCase):
        def test_details(self):
            client = Client()
            response = client.get("/customer/details/")
            self.assertEqual(response.status_code, 200)

        def test_index(self):
            client = Client()
            response = client.get("/customer/index/")
            self.assertEqual(response.status_code, 200)

次のように `self.client` を参照できます。

    from django.test import TestCase

    class SimpleTest(TestCase):
        def test_details(self):
            response = self.client.get("/customer/details/")
            self.assertEqual(response.status_code, 200)

        def test_index(self):
            response = self.client.get("/customer/index/")
            self.assertEqual(response.status_code, 200)

### テストクライアントをカスタムする

SimpleTestCase.client_class

異なる `Client` クラスを使用したい場合 (たとえば独自の動作を持つサブクラス)、次のように `client_class` クラス属性を使ってください。

    from django.test import Client, TestCase

    class MyTestClient(Client):
        # Specialized methods for your environment
        ...

    class MyTest(TestCase):
        client_class = MyTestClient

        def test_my_stuff(self):
            # Here self.client is an instance of MyTestClient...
            call_some_test_code()

### フィクスチャのロード

TransactionTestCase.fixtures

データベースを利用したウェブサイト向けのテストケースクラスは、データベースにデータが何もなければあまり役に立ちません。`TestCase.setUpTestData()` などで ORM を使用してオブジェクトを作成すると、テストがよりリーダブルになってメンテナンス性が高まりますが、フィクスチャ を活用することもできます。

フィクスチャは、Django がどうやってデータベースにインポートするか分かっているデータのコレクションです。たとえば、サイトがユーザーアカウントを持つ場合、テスト内でデータベースに格納させるために、フェイクのユーザーアカウントのフィクスチャをセットアップできます。

フィクスチャを作成するもっとも分かりやすい方法は、`manage.py dumpdata` コマンドを使うことです。これは、データベース内にすでに何らかのデータがあるという仮定に基づいています。詳細は、`dumpdata のドキュメント` 参照してください。

いったんフィクスチャを作成して `INSTALLED_APPS` 内ののどれかで `fixtures` 辞書に記述したら、`django.test.TestCase` サブクラスで `fixtures` クラス属性を指定することで、ユニットテスト内でこのフィクスチャを使えます。

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

    class AnimalTestCase(TestCase):
        fixtures = ["mammals.json", "birds"]

        def setUp(self):
            # Test definitions as before.
            call_setup_methods()

        def test_fluffy_animals(self):
            # A test that uses the fixtures.
            call_some_test_code()

具体的には、以下のことが起こります。

- `setUpClass()` の実行中に、指定された名前のフィクスチャがすべて読み込まれます。この例では、Django はまず `mammals` という名前の JSON フィクスチャを、続いて `birds` という名前のフィクスチャを読み込みます。フィクスチャの定義方法やインストール方法については、 フィクスチャ (fixture) トピックを参照してください。

多くのユニットテストで使用される `TestCase` の場合、パフォーマンス向上のために各テスト終了後にトランザクションを使ってデータベースをクリアするため、それ以外の処理を Django が行う必要はありません。しかし `TransactionTestCase` を使った場合は、以下の処理が実行されます：

- 各テストの終了時に、Django はデータベースを flush し、 `migrate` 実行直後の状態に戻します。

- その後の各テストにおいては、 `setUp()` が実行される前にフィクスチャが再読み込みされます。

いずれの場合でも、あるテストの結果が他のテストやテストの実行順によって影響を受けることはありません。

デフォルトでは、フィクスチャは `default` データベースにだけロードされます。複数のデータベースと `TransactionTestCase.databases` を使用している場合は、フィクスチャは指定されたすべてのデータベースにロードされます。

### URLconf の設定

アプリケーションがヴューを提供する場合、テストクライアントを使ってビューを実行するテストを含めたくなるかもしれません。しかし、エンドユーザーは、アプリケーション内で選択した任意の URL に自由にビューをデプロイできます。これが意味するのは、テストはビューが特定の URL で利用可能であるという事実に頼ることができないということです。URLconf の設定のためには、テストクラスまたはメソッドを `@override_settings(ROOT_URLCONF=...)` を使用してデコレーションしてください。

### マルチデータベースのサポート

TransactionTestCase.databases

Django は、設定の `DATABASES` で定義され、`databases` を介して少なくとも1つのテストで参照されるデータベースそれぞれに対応するテストデータベースをセットアップします。

しかし、 Django の `TestCase` の実行にかかる時間の大部分は、各テストの終了時にデータベースがクリーンであることを保証する `flush` の呼び出しに消費されます。複数のデータベースがある場合、複数回のフラッシュが必要であり (各データベースに 1 回ずつ)、特に複数データベースの動作をテストする必要がないテストでは、これは時間のかかる作業です。

最適化として、Django は各テスト実行の終了時に `default` データベースだけをフラッシュします。セットアップに複数のデータベースが含まれていて、全てのデータベースをクリーンにする必要があるテストがある場合、テストスイートで `databases` 属性を使って、追加のデータベースのフラッシュを要求できます。

例:

    class TestMyViews(TransactionTestCase):
        databases = {"default", "other"}

        def test_index_page_view(self):
            call_some_test_code()

このテストケースクラスは `test_index_page_view` を実行したあとに `default` と `other` のテストデータベースをフラッシュします。また、`'__all__'` を使用すると、すべてのテストデータベースをフラッシュするように指定できます。

`databases` フラグは `TransactionTestCase.fixtures` がどのデータベースに読み込まれるかを制御します。デフォルトでは、フィクスチャは `default` データベースにのみ読み込まれます。

`databases` にないデータベースに対するクエリは、テスト間で状態が漏れるのを防ぐためにアサーションエラーを出します。

TestCase.databases

デフォルトでは、`TestCase` の実行中にトランザクションにラップされるのは `default` データベースだけで、他のデータベースにクエリを実行しようとすると、テスト間の状態リークを防ぐためにアサーションエラーが発生します。

デフォルト以外のデータベースに対してトランザクションラッピングを要求するには、テストクラスの `databases` クラス属性を使用します。

例:

    class OtherDBTests(TestCase):
        databases = {"other"}

        def test_other_db_query(self): ...

このテストは `other` データベースに対するクエリのみを許可します。 `SimpleTestCase.databases` や `TransactionTestCase.databases` と同様に、定数 `'__all__'` を使用して、すべてのデータベースに対するクエリを許可するように指定できます。

### 設定のオーバーライド

警告

テストの設定値を一時的に変更するには、以下の関数を使います。 `django.conf.settings` を直接操作しないでください。Django はそのような操作の後、元の値を復元しません。

SimpleTestCase.settings()

For testing purposes it's often useful to change a setting temporarily and revert to the original value after running the testing code. For this use case Django provides a standard context manager called `settings()`, which can be used like this:

    from django.test import TestCase

    class LoginTestCase(TestCase):
        def test_login(self):
            # First check for the default behavior
            response = self.client.get("/sekrit/")
            self.assertRedirects(response, "/accounts/login/?next=/sekrit/")

            # Then override the LOGIN_URL setting
            with self.settings(LOGIN_URL="/other/login/"):
                response = self.client.get("/sekrit/")
                self.assertRedirects(response, "/other/login/?next=/sekrit/")

この例では、 `with` ブロック内のコードに対して、 `LOGIN_URL` 設定をオーバーライドし、その後にその値を以前の状態にリセットします。

SimpleTestCase.modify_settings()

値のリストを含む設定の再定義は難しいことがあります。実際には、値の追加や削除で十分なことも多いです。Django には設定を簡単に変更するための `modify_settings()` コンテキストマネージャがあります:

    from django.test import TestCase

    class MiddlewareTestCase(TestCase):
        def test_cache_middleware(self):
            with self.modify_settings(
                MIDDLEWARE={
                    "append": "django.middleware.cache.FetchFromCacheMiddleware",
                    "prepend": "django.middleware.cache.UpdateCacheMiddleware",
                    "remove": [
                        "django.contrib.sessions.middleware.SessionMiddleware",
                        "django.contrib.auth.middleware.AuthenticationMiddleware",
                        "django.contrib.messages.middleware.MessageMiddleware",
                    ],
                }
            ):
                response = self.client.get("/")
                # ...

各アクションに対して、値のリストまたは文字列を指定できます。値がすでにリストに存在する場合、 `append` と `prepend` は何もしません。同様に、値が存在しない場合、 `remove` は何もしません。

override_settings(**kwargs)

In case you want to override a setting for a test method, Django provides the `override_settings()` decorator:

    from django.test import TestCase, override_settings

    class LoginTestCase(TestCase):
        @override_settings(LOGIN_URL="/other/login/")
        def test_login(self):
            response = self.client.get("/sekrit/")
            self.assertRedirects(response, "/other/login/?next=/sekrit/")

このデコレータは `TestCase` クラスにも適用できます:

    from django.test import TestCase, override_settings

    @override_settings(LOGIN_URL="/other/login/")
    class LoginTestCase(TestCase):
        def test_login(self):
            response = self.client.get("/sekrit/")
            self.assertRedirects(response, "/other/login/?next=/sekrit/")

modify_settings(*args, **kwargs)

同様に、Django には `modify_settings()` デコレータがあります:

    from django.test import TestCase, modify_settings

    class MiddlewareTestCase(TestCase):
        @modify_settings(
            MIDDLEWARE={
                "append": "django.middleware.cache.FetchFromCacheMiddleware",
                "prepend": "django.middleware.cache.UpdateCacheMiddleware",
            }
        )
        def test_cache_middleware(self):
            response = self.client.get("/")
            # ...

このデコレータはテストケースクラスにも適用できます:

    from django.test import TestCase, modify_settings

    @modify_settings(
        MIDDLEWARE={
            "append": "django.middleware.cache.FetchFromCacheMiddleware",
            "prepend": "django.middleware.cache.UpdateCacheMiddleware",
        }
    )
    class MiddlewareTestCase(TestCase):
        def test_cache_middleware(self):
            response = self.client.get("/")
            # ...

注釈

クラスが渡されると、これらのデコレータはそのクラスを直接変更して返します。変更したコピーを作成して返すわけではありません。そのため、上記の例を微調整して `LoginTestCase` や `MiddlewareTestCase` と異なる名前を返り値に割り当てようとすると、元のテストケースクラスがデコレータの影響を受けていることに驚くかもしれません。あるクラスに対して、 `modify_settings()` は常に `override_settings()` の後に適用されます。

警告

設定ファイルには、Django の内部の初期化時にだけ参照されるいくつかの設定が含まれています。設定ファイルを `override_settings` で変更した場合、 `django.conf.settings` モジュール経由でアクセスすれば設定は変更されますが、 Django の内部からは別の方法でアクセスはされます。これらの設定に `override_settings()` や `modify_settings()` を使っても、実際には期待通りの動作をすることはないでしょう。

`DATABASES` の設定を変更することはお勧めしません。 `CACHES` の設定を変更することは可能ですが、 `django.contrib.sessions` のようなキャッシュを使用する内部機能を使用している場合は少し厄介です。例えば、キャッシュされたセッションを使用し、 `CACHES` を上書きするテストでは、セッションバックエンドを再初期化する必要があります。

最後に、設定をモジュールレベルの定数としてエイリアスすることは避けてください。なぜなら、`override_settings()` はそのような値には機能しないからです。それらの値はモジュールが最初にインポートされた時にのみ評価されます。

下記のように、設定が上書きされた後にその設定を削除することで、設定がない状態をシミュレートすることもできます:

    @override_settings()
    def test_something(self):
        del settings.LOGIN_URL
        ...

設定を上書きする場合、アプリのコードが、キャッシュや設定が変更されても状態を保持するような機能を使用しているケースにも対処してください。Django には `django.test.signals.setting_changed` シグナルがあり、設定が変更されたときに状態をクリーンアップしたり、リセットしたりするためのコールバックを登録できます。

Django 自身は、このシグナルを使って様々なデータをリセットします:

オーバーライドされた設定 | データのリセット
--- | ---
USE_TZ, TIME_ZONE | データベースのタイムゾーン
TEMPLATES | テンプレートエンジン
FORM_RENDERER | デフォルトのレンダラー
SERIALIZATION_MODULES | シリアライザーのキャッシュ
LOCALE_PATHS、LANGUAGE_CODE | デフォルトの翻訳と読み込まれた翻訳
STATIC_ROOT, STATIC_URL, STORAGES | ストレージの設定

### アプリの隔離

utils.isolate_apps(*app_labels, attr_name=None, kwarg_name=None)

  ラップされたコンテキスト内で定義されたモデルを、独自の隔離された `apps` レジストリに登録します。この機能は、クラスが後できれいに削除され、名前衝突のリスクがないため、テスト用にモデルクラスを作成するときに便利です。

  隔離されたレジストリが含む必要があるアプリラベルは、個別の引数として渡す必要があります。`isolate_apps()` をデコレータまたはコンテキストマネージャとして使用できます。以下に例を示します。

      from django.db import models
      from django.test import SimpleTestCase
      from django.test.utils import isolate_apps

      class MyModelTests(SimpleTestCase):
          @isolate_apps("app_label")
          def test_model_definition(self):
              class TestModel(models.Model):
                  pass

              ...

  あるいは、次のようにします。

      with isolate_apps("app_label"):

          class TestModel(models.Model):
              pass

          ...

  デコレータ形式は、クラスにも適用できます。

  2つのオプション引数が指定できます。

  - `attr_name`: クラスデコレータとして使用される場合に、隔離されたレジストリに割り当てられる属性。

  - `kwarg_name`: 関数デコレータとして使用された場合に、隔離されたレジストリに渡されるキーワード引数。

  モデル登録を隔離するために使用される一時的な `Apps` インスタンスは、クラスデコレータとして使用する際に `attr_name` パラメータを使用して属性として取得できます。

      @isolate_apps("app_label", attr_name="apps")
      class TestModelDefinition(SimpleTestCase):
          def test_model_definition(self):
              class TestModel(models.Model):
                  pass

              self.assertIs(self.apps.get_model("app_label", "TestModel"), TestModel)

  あるいは、`kwarg_name` パラメータを使ってメソッドデコレータとして使用する際に、 テストメソッドの引数として指定することもできます。

      class TestModelDefinition(SimpleTestCase):
          @isolate_apps("app_label", kwarg_name="apps")
          def test_model_definition(self, apps):
              class TestModel(models.Model):
                  pass

              self.assertIs(apps.get_model("app_label", "TestModel"), TestModel)

### テスト用の送信トレイを空にする

Django のカスタムの `TestCase` クラスを使うと、テストランナーは各テストケースの開始時に、テスト用のメール送信トレイの中身を消去します。

テスト中のメールサービスの詳細については、以下の Email services を参照してください。

### アサーション

Python の通常の `unittest.TestCase` クラスが `assertTrue()` や `assertEqual()` のようなアサーションメソッドを実装しているように、 Django のカスタム `TestCase` クラスは、Web アプリケーションのテストに便利なカスタムのアサーションメソッドを多数提供しています。

これらのアサーションメソッドで出力される失敗メッセージは、 `msg_prefix` 引数でカスタマイズできます。この文字列は、アサーションが生成する失敗メッセージの先頭に付加されます。これにより、テストスイートで発生した失敗の場所や原因を特定しやすくなります。

SimpleTestCase.assertRaisesMessage(expected_exception, expected_message, callable, *args, **kwargs)
SimpleTestCase.assertRaisesMessage(expected_exception, expected_message)

  `callable` の実行が `expected_exception` を引き起こし、かつその例外のメッセージに `expected_message` が含まれていることをアサートします。他の結果はすべて失敗として報告されます。これは `unittest.TestCase.assertRaisesRegex()` の簡易版で、 `expected_message` が正規表現として扱われない点が違います。

  `expected_exception` と `expected_message` パラメータのみが与えられた場合、テストされるコードを関数としてではなくインラインで記述できるように、コンテキストマネージャを返します。

      with self.assertRaisesMessage(ValueError, "invalid literal for int()"):
          int("a")

SimpleTestCase.assertWarnsMessage(expected_warning, expected_message, callable, *args, **kwargs)
SimpleTestCase.assertWarnsMessage(expected_warning, expected_message)

  これは `SimpleTestCase.assertRaisesMessage()` に似ていますが、 `assertRaisesRegex()` の代わりに `assertWarnsRegex()` と同様のものです。

SimpleTestCase.assertFieldOutput(fieldclass, valid, invalid, field_args=None, field_kwargs=None, empty_value='')

  様々な入力に対してフォームフィールドが正しく動作することをアサートします。

  パラメータ:

    - fieldclass -- テストされるフィールドのクラス。

    - valid -- 有効な入力をそれらの期待されるクリーンな値にマッピングする辞書。

    - invalid -- 無効な入力を一つ以上の発生したエラーメッセージにマッピングする辞書。

    - field_args -- フィールドをインスタンス化するために渡される引数。

    - field_kwargs -- フィールドをインスタンス化するために渡されるキーワード引数。

    - empty_value -- `empty_values` における入力の期待されるクリーンな出力。

  たとえば、以下のコードは `EmailField` が `a@a.com` を有効なメールアドレスとして受け入れるが、`aaa` を合理的なエラーメッセージと共に拒否することをテストします:

      self.assertFieldOutput(
          EmailField, {"a@a.com": "a@a.com"}, {"aaa": ["Enter a valid email address."]}
      )

SimpleTestCase.assertFormError(form, field, errors, msg_prefix='')

  フォーム上のフィールドが提供されたエラーのリストを発生させることをアサートします。

  `form` は `Form` インスタンスです。フォームは バインドされている (bound である) 必要がありますが、必ずしもバリデートされている必要はありません (`assertFormError()` はフォームに対して自動的に `full_clean()` を呼び出します)。

  `field` はチェックするフォームのフィールド名です。フォームの `特定のフィールドに関連付けられていないエラー` をチェックするには、 `field=None` を使用します。

  `errors` は、フィールドが持つことが期待されるすべてのエラー文字列のリストです。1つのエラーのみが期待される場合は、単一のエラー文字列を渡すこともできます。つまり、 `errors='error message'` は `errors=['error message']` と同じです。

SimpleTestCase.assertFormSetError(formset, form_index, field, errors, msg_prefix='')

  レンダリング時に `formset` が指定されたエラーリストを発生させることをアサートします。

  `formset` は `FormSet` のインスタンスです。フォームセットはバインドされている (bound である) 必要がありますが、必ずしもバリデートされている必要はありません (`assertFormSetError()` は自動的にフォームセットの `full_clean()` を呼び出します)。

  `form_index` は `FormSet` 内のフォームの番号です (0 から始まります)。フォームセットのフォーム以外のエラー、つまり `formset.non_form_errors()` を呼び出したときに表示されるエラーをチェックするには `form_index=None` を使用します。この場合、 `field=None` も指定する必要があります。

  `field` と `errors` は `assertFormError()` のパラメータと同じ意味です。

SimpleTestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)

  Asserts that an `HttpResponse` produced the given `status_code` and that `text` appears in its `content`. If `count` is provided, `text` must occur exactly `count` times in the response.

  `text` を HTML として扱うには `html` を `True` に設定します。レスポンスの内容との比較は、一文字ずつ等しくするのではなく、HTMLのセマンティクスに基づいて行われます。ほとんどの場合、空白文字は無視され、属性の順序は重要ではありません。詳細は `assertHTMLEqual()` を参照してください。

SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)

  Asserts that an `HttpResponse` produced the given `status_code` and that `text` does not appear in its `content`.

  `text` を HTML として扱うには `html` を `True` に設定します。レスポンスの内容との比較は、一文字ずつ等しくするのではなく、HTMLのセマンティクスに基づいて行われます。ほとんどの場合、空白文字は無視され、属性の順序は重要ではありません。詳細は `assertHTMLEqual()` を参照してください。

SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='', count=None)

  指定された名前のテンプレートがレスポンスのレンダリングに使われたことをアサートします。

  `response` must be a `Response` instance returned by the test client.

  `template_name` には `'admin/index.html'` のような文字列を指定します。

  `count` 引数はテンプレートがレンダリングされるべき回数を示す整数です。デフォルトは `None` で、テンプレートが1回以上レンダリングされるべきことを意味します。

  このようにコンテキストマネージャとして使用できます:

      with self.assertTemplateUsed("index.html"):
          render_to_string("index.html")
      with self.assertTemplateUsed(template_name="index.html"):
          render_to_string("index.html")

SimpleTestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')

  指定された名前のテンプレートがレスポンスのレンダリングに使われて いない ことをアサートします。

  `assertTemplateUsed()` と同じようにコンテキストマネージャとして使うことができます。

SimpleTestCase.assertURLEqual(url1, url2, msg_prefix='')

  同じ名前のパラメータを除いて、クエリ文字列パラメータの順序を無視して、2つのURLが同じであることをアサートします。例えば、 `/path/?x=1&y=2` は `/path/?y=2&x=1` と等しいですが、 `/path/?a=1&a=2` は `/path/?a=2&a=1` と等しくありません。

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)

  Asserts that the `HttpResponse` returned a response with a redirect status (based on its `status_code`), redirected to `expected_url` (including any `GET` data), and that the final response was received with `target_status_code`.

  リクエストが `follow` 引数を使った場合、 `expected_url` と `target_status_code` はリダイレクトチェーンの最終地点の url とステータスコードになります。

  `fetch_redirect_response` が `False` の場合、最終ページは読み込まれません。テストクライアントは外部 URL を取得できないので、 `expected_url` が Django アプリの一部でない場合、これは特に便利です。

  スキームは、2つのURL間の比較を行う際に正しく処理されます。リダイレクト先にスキームが指定されていない場合、元のリクエストのスキームが使われます。もし存在すれば、 `expected_url` のスキームが比較に使われます。

SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)

  文字列 `html1` と `html2` が等しいことをアサートします。比較はHTMLのセマンティクスに基づいて行われます。比較は以下のことが考慮されます:

  - HTMLタグの前後の空白は無視されます。

  - すべての種類の空白は同等とみなされます。

  - すべての開いたタグは暗黙的に閉じられます。例えば、周囲のタグが閉じられるかHTMLドキュメントが終了したときなど。

  - 空のタグは自己終了 (self-closing) タグと等価です。

  - HTML要素の属性の順序は重要ではありません。

  - 引数を持たないブール属性 (例: `checked`) は、名前と値が同じ属性と等しいです (例を参照)。

  - 同じ文字を参照するテキスト、文字参照、およびエンティティ参照は等価です。

  以下の例は有効なテストであり、どれも `AssertionError` を引き起こしません。

      self.assertHTMLEqual(
          "<p>Hello <b>&#x27;world&#x27;!</p>",
          """<p>
              Hello   <b>&#39;world&#39;! </b>
          </p>""",
      )
      self.assertHTMLEqual(
          '<input type="checkbox" checked="checked" id="id_accept_terms" />',
          '<input id="id_accept_terms" type="checkbox" checked>',
      )

  `html1` と `html2` はHTMLを含んでいなければなりません。どちらかが解析できない場合は `AssertionError` が発生します。

  エラー時の出力は `msg` 引数でカスタマイズできます。

SimpleTestCase.assertHTMLNotEqual(html1, html2, msg=None)

  文字列 `html1` と `html2` が等しく ない ことをアサートします。比較はHTMLのセマンティクスに基づいて行われます。詳細は `assertHTMLEqual()` を参照してください。

  `html1` と `html2` はHTMLを含んでいなければなりません。どちらかが解析できない場合は `AssertionError` が発生します。

  エラー時の出力は `msg` 引数でカスタマイズできます。

SimpleTestCase.assertXMLEqual(xml1, xml2, msg=None)

  文字列 `xml1` と `xml2` が等しいことをアサートします。比較はXMLセマンティクスに基づいて行われます。`assertHTMLEqual()` と同様に、比較は構文解析された内容に基づいて行われるため、構文の違いは考慮されず、意味の違いだけが考慮されます。無効なXMLがパラメータに渡された場合、両方の文字列が同じであっても、常に `AssertionError` が発生します。

  XML宣言、ドキュメントタイプ、処理命令、コメントは無視されます。比較されるのはルート要素とその子要素だけです。

  エラー時の出力は `msg` 引数でカスタマイズできます。

SimpleTestCase.assertXMLNotEqual(xml1, xml2, msg=None)

  文字列 `xml1` と `xml2` が等しく ない ことをアサートします。比較はXMLセマンティクスに基づいて行われます。詳細は `assertXMLEqual()` を参照してください。

  エラー時の出力は `msg` 引数でカスタマイズできます。

SimpleTestCase.assertInHTML(needle, haystack, count=None, msg_prefix='')

  HTML フラグメント `needle` が `haystack` に含まれていることをアサートします。

  もし `count` という整数の引数が指定された場合、さらに `needle` の出現数が厳密に検証されます。

  ほとんどの場合、空白は無視され、属性の順序は重要ではありません。詳細は `assertHTMLEqual()` を参照してください。

SimpleTestCase.assertNotInHTML(needle, haystack, msg_prefix='')

  HTMLフラグメント `needle` が `haystack` に含まれて いない ことをアサートします。

  ほとんどの場合、空白は無視され、属性の順序は重要ではありません。詳細は `assertHTMLEqual()` を参照してください。

SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)

  JSON フラグメント `raw` と `expected_data` が等しいことをアサートします。重要な部分は `json` ライブラリに委譲されているため、通常の JSON の重要でない空白のルールが適用されます。

  エラー時の出力は `msg` 引数でカスタマイズできます。

SimpleTestCase.assertJSONNotEqual(raw, expected_data, msg=None)

  JSON フラグメント `raw` と `expected_data` が等しく ない ことをアサートします。詳細は `assertJSONEqual()` を参照してください。

  エラー時の出力は `msg` 引数でカスタマイズできます。

TransactionTestCase.assertQuerySetEqual(qs, values, transform=None, ordered=True, msg=None)

  クエリセット `qs` が特定の値のイテラブル `values` にマッチすることをアサートします。

  `transform` が指定された場合、 `values` は `qs` の各メンバに `transform` を適用したリストと比較されます。

  デフォルトでは、比較は順序に依存します。もし `qs` が暗黙の順序を提供しない場合、 `ordered` パラメータを `False` に設定することで、比較を `collections.Counter` 比較に変更できます。順序が未定義の場合 (指定された `qs` が順序付けされておらず、複数の順序付けられた値との比較の場合)、`ValueError` が発生します。

  エラー時の出力は `msg` 引数でカスタマイズできます。

TransactionTestCase.assertNumQueries(num, func, *args, **kwargs)

  `func` が `*args` と `**kwargs` で呼び出されると、 `num` 個のデータベースクエリが実行されることをアサートします。

  もし `kwargs` に `"using"` キーがあれば、それをクエリの数をチェックするためのデータベースのエイリアスとして使用します。

      self.assertNumQueries(7, my_function, using="non_default_db")

  もし `using` パラメータを持つ関数を呼び出したい場合は、呼び出しを `lambda` でラップして追加のパラメータを指定できます。

      self.assertNumQueries(7, lambda: my_function(using=7))

  コンテキストマネージャとしても使えます。

      with self.assertNumQueries(2):
          Person.objects.create(name="Aaron")
          Person.objects.create(name="Daniel")

### テストにタグをつける

テストにタグをつけることで、特定のサブセットを簡単に実行できるようになります。たとえば、速いテストや遅いテストにラベルをつけることができます。

    from django.test import tag

    class SampleTestCase(TestCase):
        @tag("fast")
        def test_fast(self): ...

        @tag("slow")
        def test_slow(self): ...

        @tag("slow", "core")
        def test_slow_but_core(self): ...

テストケースクラスにタグを付けることもできます。

    @tag("slow", "core")
    class SampleTestCase(TestCase): ...

サブクラスは基底クラスからタグを継承し、メソッドはそのクラスからタグを継承します。以下の例を考えてみましょう。

    @tag("foo")
    class SampleTestCaseChild(SampleTestCase):
        @tag("bar")
        def test(self): ...

`SampleTestCaseChild.test` は `'slow'`, `'core'`, `'bar'`, そして `'foo'` というラベルが付けられます。

その後、どのテストを実行するか選択できます。例えば、速いテストのみを実行するには、次にようにします。

/ 

    $ ./manage.py test --tag=fast

    ...\> manage.py test --tag=fast

または、速いテストとコアなテスト (それが遅いとしても) を実行することもできます。

/ 

    $ ./manage.py test --tag=fast --tag=core

    ...\> manage.py test --tag=fast --tag=core

タグによってテストを除外することもできます。遅くない場合にコアテストを実行するには、次にようにします。

/ 

    $ ./manage.py test --tag=core --exclude-tag=slow

    ...\> manage.py test --tag=core --exclude-tag=slow

`test --exclude-tag` は `test --tag` よりも優先されるので、テストに2つのタグがあり、片方を選択してもう片方を除外すると、テストは実行されません。

## 非同期コードをテストする

単に非同期ビューの出力をテストしたいだけであれば、標準のテストクライアントが非同期ループの中で実行するので、追加の作業は必要ありません。

しかし、Django プロジェクトで完全な非同期テストを書きたい場合、いくつかの点を考慮する必要があります。

まず、テストはテストクラスの `async def` メソッドでなければなりません (非同期コンテキストを与えるため)。Django は自動的に `async def` テストを検出し、独自のイベントループで実行されるようにラップします。

非同期関数からテストする場合は、非同期テストクライアントも使用する必要があります。これは `django.test.AsyncClient` として、あるいは任意のテスト上で `self.async_client` として利用できます。

class AsyncClient(enforce_csrf_checks=False, raise_request_exception=True, *, headers=None, query_params=None, **defaults)

`AsyncClient` は同期 (通常の) テストクライアントと同じメソッドとシグネチャを持ちますが、 以下の例外があります。

- 初期化では、 `defaults` にある任意のキーワード引数が直接 ASGI スコープに追加されます。

- キーワード引数 `extra` として渡されるヘッダには、同期クライアントが必要とする `HTTP_` プレフィックスを付けてはいけません (`Client.get()` を参照してください)。例えば、HTTPの `Accept` ヘッダを設定する方法を示します。

      >>> c = AsyncClient()
      >>> c.get("/customers/details/", {"name": "fred", "age": 7}, ACCEPT="application/json")

`AsyncClient` を使用する場合、リクエストを行うあらゆるメソッドは await にする必要があります。

    async def test_my_thing(self):
        response = await self.async_client.get("/some-url/")
        self.assertEqual(response.status_code, 200)

非同期クライアントは同期ビューを呼び出すこともできます。Django の 非同期のリクエスト経路 を通して実行され、両方に対応しています。`AsyncClient` を通して呼び出されたビューは、通常のクライアントが作成する `WSGIRequest` ではなく、`ASGIRequest` オブジェクトを `request` として取得します。

警告

テストデコレータを使う場合、正しく動作するためには非同期対応でなければなりません。Django のビルトインデコレータは正しく動作しますが、サードパーティ製のデコレータは実行されないように見えるかもしれません (実行フローの間違った部分を「ラップ」してしまい、あなたのテストは実行されません)。

これらのデコレータを使用する必要がある場合は、テストメソッドをそれらの 内部で `async_to_sync()` でデコレートするべきです。

    from asgiref.sync import async_to_sync
    from django.test import TestCase

    class MyTests(TestCase):
        @mock.patch(...)
        @async_to_sync
        async def test_my_thing(self): ...

## メールサービス

If any of your code sends email using Django's email functionality, you probably don't want to send email each time you run a test that exercises that code. For this reason, Django's test runner automatically redirects all Django-sent email to an in-memory outbox. This lets you test every aspect of sending email -- from the number of messages sent to the contents of each message -- without actually sending the messages.

The test runner accomplishes this by transparently replacing the `BACKEND` for each configured `MAILERS` alias with the `'locmem'` memory email backend. (Don't worry -- this has no effect on any other email senders outside of Django, such as your machine's mail server, if you're running one.)

django.core.mail.outbox

During test running, each outgoing email is saved in `django.core.mail.outbox`. This is a list of all `EmailMessage` instances that have been sent. The `outbox` attribute is a special attribute that is created only when the `locmem` email backend is used. It doesn't normally exist as part of the `django.core.mail` module and you can't import it directly. The code below shows how to access this attribute correctly.

以下は `django.core.mail.outbox` の長さと内容を調べるテスト例です。

    from django.core import mail
    from django.test import TestCase

    class EmailTest(TestCase):
        def test_send_email(self):
            # Send message.
            mail.send_mail(
                "Subject here",
                "Here is the message.",
                "from@example.com",
                ["to@example.com"],
            )

            # Test that one message has been sent.
            self.assertEqual(len(mail.outbox), 1)

            # Verify that the subject of the first message is correct.
            self.assertEqual(mail.outbox[0].subject, "Subject here")

            # Verify the message was sent with the "default" mailer.
            self.assertEqual(mail.outbox[0].sent_using, "default")

Changed in Django 6.1:

The `sent_using` attribute was added to messages in the outbox.

前述の ように、テストの送信トレイは Django `*TestCase` の各テストの開始時に空になります。手動で送信トレイを空にするには、`mail.outbox` に空のリストを代入してください。

    from django.core import mail

    # Empty the test outbox
    mail.outbox = []

## 管理コマンド

管理コマンドは、`call_command()` 関数を使用してテストできます。以下のように、出力は `StringIO` インスタンスにリダイレクトできます。

    from io import StringIO
    from django.core.management import call_command
    from django.test import TestCase

    class ClosepollTest(TestCase):
        def test_command_output(self):
            out = StringIO()
            call_command("closepoll", poll_ids=[1], stdout=out)
            self.assertIn('Successfully closed poll "1"', out.getvalue())

## テストのスキップ

unittest ライブラリは `@skipIf` デコレータと `@skipUnless` デコレータを提供しており、特定の条件下でテストが失敗することがわかっている場合にテストをスキップできます。

例えば、テストを成功させるために特定のオプションライブラリが必要な場合に、テストケースを `@skipIf` でデコレートすることができます。そうすると、テストランナーはテストを失敗させたり完全に省略したりする代わりに、テストが実行されなかったこととその理由を報告します。

これらのテストスキップ動作を補うために、 Django はさらに 2 つのスキップデコレータを提供しています。一般的な真偽値をテストする代わりに、これらのデコレータはデータベースの機能をチェックし、データベースが特定の機能をサポートしていなければテストをスキップします。

デコレータは、データベース機能を表す文字列識別子を使用します。この文字列はデータベース接続の features クラスの属性に対応します。 django.db.backends.base.features.BaseDatabaseFeatures クラス に、テストをスキップするベースとして使用できるデータベース機能の完全なリストがあります。

skipIfDBFeature(*feature_name_strings)

指定したデータベース機能がすべてサポートされている場合は、デコレートされたテストや `TestCase` をスキップします。

例えば、データベースがトランザクションをサポートしている場合、以下のテストは実行されません (例えば、PostgreSQLでは実行 されません が、MyISAMテーブルを持つMySQLでは実行されます)。

    class MyTests(TestCase):
        @skipIfDBFeature("supports_transactions")
        def test_transaction_behavior(self):
            # ... conditional test code
            pass

skipUnlessDBFeature(*feature_name_strings)

指定したデータベース機能がサポートされていない場合は、デコレートされたテストや `TestCase` をスキップします。

例えば、以下のテストはデータベースがトランザクションをサポートしている場合だけ実行されます (たとえば、PostgreSQLでは実行されますが、MyISAMテーブルを持つMySQLでは実行 されません)。

    class MyTests(TestCase):
        @skipUnlessDBFeature("supports_transactions")
        def test_transaction_behavior(self):
            # ... conditional test code
            pass