PythonでMongoDBを使うunittestのひな形
タイトルのとおりですが、ケースとしてはFlaskみたいな軽いフレームワークでMongoDBをデータベースに使うModelを自分で実装するような場合です。
実際にデータベースを動かすModelのテストを書くときに、FlaskはフルスタックのDjangoと違って何も面倒を見てくれないので、自分でテストのときだけ使用するdbの作成、破棄などを行う必要があります。
やりたいことは、
- テスト起動時にテスト用のdb('test')を作成
- テスト用のデータ(json)を予めdbに入れておく
- Modelクラスのメソッドをテスト
- テスト終了時にテスト用のdbの破棄
という流れです。mongodの起動と終了まで面倒を見てくれるともっと便利なはずですが、今回はそこまで求めなかったので、mongodは事前に起動しているという前提になります。 *1
コードにするとこんな感じです。Python2.7で動作確認しています。
#coding: utf-8 import unittest import json import pymongo TEST_DATABASE = 'test' TEST_COLLECTION = 'user' class Model(object): """シンプルなModelのサンプル""" def __init__(self, host, port, db): self._client = pymongo.MongoClient(host, port) self._db = self._client[db] def insert_user(self, user_id, user_name): self._db.user.insert({'id': user_id, 'name': user_name}) def find_user(self, user_id): return self._db.user.find_one({'id': user_id}) class TestMongoModel(unittest.TestCase): @classmethod def setUpClass(cls): """テストで使用するdbの用意""" cls.client = pymongo.MongoClient('localhost', 27017) cls.db = cls.client[TEST_DATABASE] @classmethod def tearDownClass(cls): """テストで使用したdbの破棄""" cls.client.drop_database(TEST_DATABASE) def setUp(self): """Modelインスタント取得、テスト用データの読み込み""" self.model = Model('localhost', 27017, TEST_DATABASE) with open('user.json', 'r') as fp: fixture = json.load(fp) self.db.user.insert(fixture) def tearDown(self): """テストケース終了後にコレクション破棄""" self.db.drop_collection(TEST_COLLECTION) def test_find_user(self): """Modelのfind_user()のテストケースサンプル""" self.model.insert_user(1, 'Alice') got = self.model.find_user(1) expect = 'Alice' self.assertEqual(got['name'], 'foo') if __name__ == '__main__': unittest.main()
テスト用のdbの用意、破棄をそれぞれのテストケースで毎回行う必要はないので、setUpとtearDownのクラス版であるsetUpClass, tearDownClassで1度だけ行います。上のコードだと、'test'という名前のdbがテスト開始時に作られて、終了時に破棄されることになります。
あるテストケースの処理が前のテストケースでの処理(insert, delete, update)に依存しているとよくないので、setUpで各テストケースが実行される前にテストデータを読み込み、終了時にtearDownで毎回コレクションを破棄しています。
Mongo回りのセットアップが終われば、後はtest_find_user()のようにModelクラスのメソッドのテストケースを書いていくだけです。 今回はMongoDBの情報やdb、collection名を直接書いていますが、実際には設定ファイルや環境変数に追い出した方がアプリケーション本体からも使いまわせるので良いと思います。
ModelのテストがあるとControllerやViewを気にせずにロジック部分を作っていけるので、慣れないフレームワークで新しいDB(MongoDB)の練習をするときこそオススメです。
参考
*1:mongodまで面倒をみるなら、参考にあるブログや、test.mysqldが参考になりそうです