テスト、書いてますか?
私の担当業務の1つに、データマートの構築があります。
分析しやすいような分析用テーブルをいくつかのSQLを元に作っているのですが、元データ自体のバリデーションが弱かったり、ビジネスロジックが複雑ゆえ、論理エラーが多く発生していました。
そこで、Pythonのunittest
ライブラリを活用したテストを現在は導入しています。
良かったこと
テストを書くことで、枕を高くして寝れるようになりました。
具体的には、
- 過去指摘された論理エラーをテストに組み込むことで再発防止になる
- 別テーブルで発生した論理エラーが起きそうなテーブルに、同じテストを組み込む
- 将来発生しうるリスクに対して予めテストを仕込んでおく
といった取り組みができており、アウトプットの品質向上につながっています。
unittestとは
Pythonにおける標準のユニットテストフレームワークです。
テストの自動化、テストのセットアップおよびシャットダウンコードの共有、テストのコレクションへの集約、レポートフレームワークからのテストの独立性などを提供しています。
25.3. unittest — Unit testing framework — Python 2.7.17 documentation
テストのセットアップ
下記のように、setUpModule()関数を作れば、特別な呼び出し不要でセットアップが可能です。
今回はテストを実行したいcreate table
するSQLをここで呼び出して、実際にテーブルを作成しています。
このとき、本メソッドは単にテーブルを作るだけでなく、prefixとしてtest_
をつけるようにしています。
def setUpModule():
print("Setting up…")
test_table_name = test_util.generate_test_table(executing_file_name)
実行したいテストの記述
このように、事項したいテストをtest_hoge
という形式で記述します。
setUpModule()
によって作られたテスト用テーブルに対して集計をかけるSQLを記述しておいて、それを呼び出します。
結果は真偽値で返ってくるようにすることで、最後のself.assertTrue()
で一律で判定しています。
ここは、より複雑な判定方法も取ること可能ですが、今回はロジックをSQL側に持たせて関心を分離しています。
class TestQuery(unittest.TestCase):
def test_mrr_growth(self):
query = test_util.get_query_by_execution_info(executing_file_name, sys._getframe().f_code.co_name)
rows = test_util.get_result_in_dataframe(query)
actual = rows.iloc[0][0]
self.assertTrue(actual)
def test_gap_between_new_and_old_less_than_n(self):
query = test_util.get_query_by_execution_info(executing_file_name, sys._getframe().f_code.co_name)
rows = test_util.get_result_in_dataframe(query)
actual = rows.iloc[0][0]
self.assertTrue(actual)
def test_uniqueness(self):
query = test_util.get_query_by_execution_info(executing_file_name, sys._getframe().f_code.co_name)
rows = test_util.get_result_in_dataframe(query)
actual = rows.iloc[0][0]
self.assertTrue(actual)
テストのシャットダウン
最後に環境を汚さないよう、テーブルを削除して完了です。
def tearDownModule():
test_util.delete_test_table(test_table_name)
print("Tear down.")
工夫
このようにシンプルに扱うために、上記ではtest_util
という独自ライブラリを作成しています。
これは実装しているSQLスクリプトをよしなに扱うためのスクリプトです。
今回コードは公開しませんが、上記のように各create table
スクリプトに対するテストが、シンプルに書けるような設計にしておくと良いでしょう。