LoginSignup
5
3

More than 3 years have passed since last update.

Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 1 テスト用クライアント編

Last updated at Posted at 2020-09-09

はじめに

全5回(予定なので変わる可能性あり)にかけて、Flaskでテスト駆動開発を行うために必要なノウハウを伝授する。
本記事では、Flaskで開発したWebアプリやAPIを自動でテストするための最低限のサンプルコードとその実行例を紹介する。

1回目 本記事
2回目 Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 2 デコレータ編
3回目 Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 3 GET編
4回目 執筆中
5回目 執筆中

対象読者

  • FlaskでこれからWebアプリまたはAPIを開発する方
  • テスト自動化の勉強をしたい方

概要

Flaskで作成したHello, World!を戻り値とするAPIの最低限のテストをテスト用クライアントを用いて自動で行う。

ディレクトリ構造

本記事で利用するサンプルコードは以下のようなディレクトリ構造で配置してください。

flask_01/
├── Dockerfile 
└── app
    ├── flask_app.py
    └── test
        └── test.py

dockerのバージョン

$ docker --version
Docker version 19.03.12, build 48a66213fe

コードの準備

Dockerfile

Dockerfile
FROM python:3.6
USER root

RUN apt update
RUN /usr/local/bin/python -m pip install --upgrade pip
RUN pip install flask==1.1.2

COPY ./app /root/

WORKDIR /root/test

flask_app.py(テスト対象)

Hello, World!を出力するシンプルなAPIを利用する。

flask_app.py
from flask import Flask
app = Flask(__name__)

@app.route('/hello_world')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(host="0.0.0.0",port=5000)

test.py(テストコード)

詳細は最後のセクションで説明する。

test.py
import sys
sys.path.append('../')
# flaskアプリケーションのファイル名のから.pyを消したもの
import flask_app
import unittest

# クラス名は日本語でも動く
class Test_flask_app_正常系(unittest.TestCase):
    # 1. 共通しているパラメータを設定
    def setUp(self):
        self.ENDPOINT    = "http://localhost:5000/{}"
        self.DATA        = None
        self.STATUS      = "200 OK"
        self.STATUS_CODE = 200
        self.ROUTE       = None
    # テストケースは日本語でも動く
    def test_1_hello_worldにアクセスできること(self):
        # ケースごとに必要なパラメータを設定
        self.DATA  = b"Hello, World!"
        self.ROUTE = "hello_world"
        # 2. with分でテスト用クライアントとコンテキストとを結び付ける
        with flask_app.app.test_client() as client:
            # 3. テスト用クライアントを用いてAPIを実行
            response = client.get(self.ENDPOINT.format(self.ROUTE))
        # 4. assert文を利用してテストを実施
        assert response.data        == self.DATA
        assert response.status      == self.STATUS 
        assert response.status_code == self.STATUS_CODE

        return

if __name__ == '__main__':
    unittest.main()

テストを実行

ディレクトリ構造を確認し、以下のコマンドを実行する。

$ ls
Dockerfile      app
$ docker build -t pytest1 .
~ 省略 ~
$ docker run -rm -it pytest1 /usr/local/bin/python /root/test/test.py
.
----------------------------------------------------------------------
Ran 1 test in 0.004s

OK

test.py(テストコード)の解説

1. 共通しているパラメータを設定

unittest.TestCaseを継承したクラスは、テストケースを実行前に必ずsetUp(self)を実行する。
具体的には、test_1_flask_appのにアクセスできること(self)を実行する前にsetUp(self)が実行される。
そのため、テストケースが複数あった場合も同様に実行されるため、class内で利用する共通のパラメータの初期化を行うと良い。
厳密には異なるが、setUp(self)内で初期化した変数はclass内のあらゆるテストケースで共通利用できるという認識で良い。

2. with文でテスト用クライアントとコンテキストとを結び付ける

with構文を用いることでテスト用クライアントを利用することが可能となる。
flask_app.app.test_client()の先頭は、テストの対象であるpythonファイルのベースネームから拡張子を取り除いたものである。
今回はテスト対象がflask_app.pyなのでflask_appとなる。

3. テスト用クライアントを用いてAPIを実行

2.のテスト用クライアントのgetメソッドを利用してflask_app.pyに対してAPIを実行する。
実行結果はresponseのプロパティに格納される。

4. assert文を利用してテストを実施

assert文を用いてresponseのプロパティ1.で設定した想定された結果を比較する。
今回のテストコードでは、APIの戻り値(response.data)とステータス(response.status)、ステータスコード(response.status_code)の3種類のみ比較する。
他の実行結果と比較したい場合は、以下のpythonの関数を利用するとresponseのプロパティを確認することができる。


dir(response)

そのため、適宜確認が必要なプロパティを選択し、assert文で比較するとよい。

まとめ

テストコードでFlaskのテスト用クライアントの怪本的な使い方を紹介した。

次回

Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 2 デコレータ編

5
3
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
5
3