-
Notifications
You must be signed in to change notification settings - Fork 8
09 ユニットテスト
Flask でユニットテストを行うには nose テストフレームワークと flask のテストヘルパ、モック作成のために Factory-boy を組み合わせて用いるのがいいでしょう。 nose は python 製のテストフレームワークで、テスト結果を見やすく表示したり、 setup, teardown を簡単に作成したりできます。 Factory-boy は Ruby 製の モックデータ作成ツールの python 版です。テストには例えば以下のディレクトリ構造を想像してください。
application/
|- app/
|- __init__.py
|- models/
|- __init__.py
|- user.py
|- tests/
|- __init__.py
|- factories/
|- __init__.py
|- user.py
|- models/
|- __init__.py
|- user.py
本質的な部分だけを説明するために、 app/models/user.py tests/init.py tests/factories/user.py tests/models/user.py だけに絞ってソースを紹介します。
# app/models/user.py
from app import sa
class User(sa.Models):
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(128))
# tests/factories/user.py
from factory import Factory, fuzzy
from app.models import user
class UserFactory(Factory):
class Meta:
model = user.User
name = fuzzy.FuzzyText() # 適当な名前で生成
テストの基盤コードは例えば以下の様な書き方にします。 テストクライアントとして mock インスタンス変数と、 app_context.push をしておきましょう。テストの際は、実際に run しているわけではないので、アプリケーションコンテキストがもろもろ使えない状態にあるわけですが、ここで、 context を push/pop することで、テストの開始に アプリケーションが立ち上がり、終了時にアプリケーションが閉じるといったことが可能です。また、実際に API にアクセスし、挙動を確かめるために mock 変数を用意しておきます。
# tests/__init__.py
from unittest import TestCase
class Experiment(TestCase):
def setUp(self):
self.app = Flask('testing')
self.mock = self.app.test_client(self)
self.app_context = self.app.app_context()
self.app_context.push()
def tearDown(self):
self.app_context.pop()
いよいよ実際にテストコードを記述してみましょう。
from tests import Experiment
from tests.factories import UserFactory
class TestUser(Experiment):
def setUp(self):
super().setUp(self)
self.user_1 = UserFactory.build()
def test_user(self):
# テストしたいコードを記述
pass
以上の様にテスト作成のフローを整えて後で仕様変更があった場合、リファクタリングした場合のデグレの検出などが簡単に出来るようになります。テストされていないコードはこわれているとまで言われるくらいなので、テストを書く習慣を付けましょう。また、テストがし易いコードの書き方は基本的に品質が高くなりやすいのもテストを書く同期になるでしょう。