はじめに
全5回(予定なので変わる可能性あり)にかけて、Flaskでテスト駆動開発を行うために必要なノウハウを伝授
する。
本記事では、Flaskで開発したWebアプリやAPIを自動でテストするための最低限のサンプルコードとその実行例を紹介する。
1回目 本記事
2回目 Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 2 デコレータ編
3回目 [Flaskでテスト駆動開発(TDD)を行うためのチュートリアル - 3 GET編]
(https://qiita.com/kikusui6192/items/f01573f380d5f4e73456)
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
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を利用する。
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(テストコード)
詳細は最後のセクションで説明する。
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のテスト用クライアントの怪本的な使い方を紹介した。