LoginSignup
0
1

【Django】APIキーを利用したPOSTリクエストをテストするためのテストケースの作成方法

Posted at

概要

  • djangoのテストフレームワークでAPIキーを使用したPOSTリクエストのテストケースを作成しました。ヘッダーのHTTP_プレフィックスとテストクライアントのpostメソッドの引数headersあたりで詰まったところも調べてまとめておきましたので、これからAPIテスト作る方のご参考となればと思います。

前提

  • Python:3.6.15
  • Django:3.0.5

APIのテストケース(サンプルコード)

  • 以下がHTTP_X-API-KEYを使用したDjangoのサンプルコードです。
    • 正しいAPIキーはSAMPLE_API_KEYとします。
    • 間違ったAPIキーをWRONG_API_KEYとします。
  • 以下のテストケースでは、正しいAPIキーと間違ったAPIキーを使用してリクエストを送信し、レスポンスのステータスコードを検証しています。
from django.test import TestCase

class ApiTestCase(TestCase):
    def test_post_sample_with_api_key(self):
        headers = {'HTTP_X_API_KEY': 'SAMPLE_API_KEY'}
        data = {'key': 'value'}
        response = self.client.post('/api/', data=data, follow=True, content_type='application/json', accept='application/json', **headers)

        self.assertEqual(response.status_code, 200)

    def test_sample_without_api_key(self):
        headers = {'HTTP_X_API_KEY': 'WRONG_API_KEY'}
        data = {'key': 'value'}
        response = self.client.post('/api/', data=data, follow=True, content_type='application/json', accept='application/json', **headers)

        self.assertEqual(response.status_code, 401)

リクエストヘッダーについて

  • ①ヘッダー名にHTTP_プレフィックスをつける必要がある
  • headerspostのキーワード引数として指定する必要がある
  • ③そのほかのヘッダー部分の説明

①ヘッダー名にHTTP_プレフィックスをつける必要がある

  • ちょっと詰まったのが、リクエストヘッダーのX-API-KEYです。APIのHTTPリクエストにはヘッダーとボディがありますが、X-API-KEYはヘッダー部分になります。
  • HTTP_プリフィックスは、HTTPリクエストヘッダーのキーを指定するために使用されます。Djangoのテストクライアントでは、ヘッダーをキーワード引数として渡す場合に、ヘッダー名にHTTP_プリフィックスを付ける必要があるのです。これがわからずに以下のように記載していたのですが、全然成功しないので結構詰まりました。
headers = {'X_API_KEY': 'SAMPLE_API_KEY'}

headerspostのキーワード引数として指定する必要がある

  • **headersは辞書として定義されたキーワード引数を展開するPythonの構文で、上記の場合は以下のような形で展開されます。
    self.client.post('/api/', data=data, follow=True, content_type='application/json', accept='application/json', HTTP_X_API_KEY='SAMPLE_API_KEY')
  • このheadersと先述のHTTP_が相まって詰まりました。というのも、**headersであれば成功しましたがheaders=headersだと失敗してしまったからです。Djangoのテストクライアントのpostメソッドでは、引数にキーワード引数を利用する必要があるのです。以下が公式ドキュメントからの引用です。

It requires no arguments at time of construction. However, you can use keyword arguments to specify some default headers.

  • キーワード引数を使用してリクエストで送信するヘッダを指定する、とありますね。なるほど。headersを使うことで、実質的に辞書を解凍し、各キーと値のペアを別々のキーワード引数としてpost()メソッドに渡していることになるんですね。
  • Djangoのself.client.post()メソッドでは、メソッドのシグネチャは次のようになります。**extraパラメータは、リクエストのHTTPヘッダとして扱われる追加のキーワード引数を渡すことができます。
def post(self, path, data=None, content_type='application/octet-stream', follow=False, secure=False, **extra)
  • ということで、今回の大きな学びは以下の二つ。
    • self.client.post()メソッドを使う場合、HTTP ヘッダは'HTTP_'を先頭につけて大文字に変換する必要があること
    • self.client.post()メソッドを使ってリクエストを行う場合、ヘッダーは辞書としてではなく、キーワード引数として渡す必要があること。
  • これで、x-api-keyヘッダーを指定する際に、キーワード引数のheaders辞書のキーとしてHTTP_X_API_KEYを使用することで無事にテストすることができました。

③そのほかのヘッダー部分の説明

  • self.client.postを使用して/api/へのPOSTリクエストをシミュレートします。
  • follow=True:リダイレクトを追跡する設定になります。
  • content_type='application/json':リクエストのコンテンツタイプはJSONを指定していることを示しています。
    • content_typeを指定しない場合、データはmultipart/form-dataのコンテンツタイプで送信されます。
  • accept='application/json':JSON形式のレスポンスを返すことを期待していることを示しています。
  • 他にも、secure=Trueにすると、HTTPSリクエストをエミュレートしたりできます。
  • 今回はself.client.post()メソッドを使用してPOSTリクエストを送信していますが、他のHTTPメソッド(GET、PUT、DELETEなど)も同様に使用することができます。必要に応じて、適切なメソッドを選択してテストケースを作成しましょう。この辺は上述の公式ドキュメントにも詳細に記載があります。

リクエストボディとアサーションについて

  • リクエストボディについてはdata = {'key': 'value'}が該当します。データとしてdata変数に{'key': 'value'}という辞書が定義されています。実際は、data変数に適切なデータを設定し、期待される振る舞いをテストすることになります。
  • テストケース内のresponseオブジェクトには、APIからのレスポンスに関する情報が含まれています。
  • Pythonではアサーションを使用して、レスポンスのステータスコードが200であることをテストできます。それが以下のコードです。
self.assertEqual(response.status_code, 200)
  • 一つ目ではSAMPLE_API_KEYという正しいAPIキーが入っているのでステータスコード200でテストに成功します。
  • 二つ目では、WRONG_API_KEYという間違ったAPIキーが入っているので、ステータスコード401でテストに成功します(任意のエラーステータスとエラーメッセージを返すようにしている場合は都度ここを変える必要あり)。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1