Python初心者かつAWS初心者の私がAWS Lambdaの開発をはじめて半年強、ようやくpytestを使って単体テストを本格的に書けるようになってきました。motoというAWSのモックサービスを使うとローカルであることをほぼ意識せずに単体テストが書けることも学習。
ただしmotoのもっとも手軽な使用法であるデコレータでの指定だとせっかくのAWSモックセットアップがテストケース間で共有できません。テストケースをクラスでグループ化してクラスにデコレータで指定しても駄目。
まあそんなものかと思っていたのですが、「共通化できるのでは?」との声があがったので本腰を入れて調べて、無事解決に至ったのでメモとして残しておきます。
ポイントは次。
- motoのモックインスタンスはデコレータやコンテキストマネージャでの指定だけででなく明示的な開始・終了が可能
- Pythonはクラス変数・クラスメソッドが定義可能
- pytestはクラスメソッドをセットアップ / ティアダウン用に指定可能
以上から次が解になります。
- セットアップを共有するテストクラスを定義
- 定義したクラスにクラスメソッド
setup_class(cls)
とteardown_class(cls)
を定義setup_class(cls)
でモック対象motoインスタンスを生成してクラス変数に保存、start
メソッド呼び出しteardown_class(cls)
でモック対象motoインスタンスのstop
メソッド呼び出し
たとえば次のようにするとバケット test-bucket
を TestClassTemplateUsingMoto
クラスで定義したすべてのテストケースメソッドで使えます。
以上、参考になりましたら幸いです。
付記。今回あらためて把握したのがPythonのオブジェクト指向機能サポートの強力さ。多重継承可であることはPython チュートリアルで目にした覚えがありましたが、静的メソッドでないクラスメソッドまで定義できるとは思いもしませんでした。凡百のオブジェクト指向言語よりはるかに強力なわけで、20年前の私なら狂喜したことでしょう。オブジェクト指向との向きあいかたも変わったので今後のPython利用でもクラス変数やクラスメソッドを活用するコーディングはしないでしょうが、オブジェクト指向の多様性を後世に伝える意味で、Pythonにはこの機能を維持し続けてもらいたいと思います。