背景
業務では boto3 を使って取得したデータをデータベースに格納するスクリプトを書きました。
テストを書くために boto3 を stub する方法を調べてると、stubber というものがありました。
boto3 を stub する方法について調査すると、ネットには stubber と unittest の組み合わせを使った方法が多く紹介されていました。
しかし stubber と pytest の mock を組み合わせたは記事が少ないように感じました。
今回は boto3 を pytest の monkeypatch で stub する方法を備忘録として残します。
環境構築
必要なモジュールをインストールします。
boto3 を実行できるようにするため環境変数を設定します。
exampleクラス
今回は Example クラスにある __get_client
を patch します。
エントリーポイントは main.py
です
コードを実行するとロール一覧を取得できます。
pytestでテストを書く
Example クラスにある get_roles
メソッドをテストしたいと思います。
stubber で iam client の stub を作成する
Stubber Reference にある Example を参考にしてコード書いてみます。
monkeypatch には fixture がついているので、テストの関数やメソッドには引数に monkeypatch を取ることができます。
https://github.com/pytest-dev/pytest/blob/d2b214220f63e1fc90120495d600893cfba6219f/src/_pytest/monkeypatch.py#L29-L30
info: pytest fixture 一覧
テストは問題なさそうです。
テストコードには monkeypatch.setattr
を使って Example クラスのプライベートメソッドを置き換えました。 monkeypatch.setattr(Example, "_Example__get_client", lambda _: iam)
プライベートメソッド名
プライベートメソッドの名前は、_classname_private-methodname
になります。
これは組み込み関数の dir を使うと確認できます。
__get_client
の名前は、_Example__get_client
であることがわかります。
__spam (先頭に二個以上の下線文字、末尾に一個以下の下線文字) という形式の識別子は、 _classname__spam へとテキスト置換されるようになりました。
引用:https://docs.python.org/ja/3/tutorial/classes.html#private-variables
stub の作成を fixture にする
stubber の箇所を fixture にして再利用しやすいようにしてみます。
無事にテストも通りました。これで stub する箇所を再利用できるようになりました。
リファクタリングする
テスト用のクラスを作成したい場合もあると思います。
pytest の fixtureの説明で、“Arrange”、“Act”、“Assert”、“Cleanup” の話があるので、これに沿ってリファクタしてみます。
記述量が増えてしまいましたが、まとまりがわかりやすいためテストを追加しやすくなったと思います。
最後に
今回使用したコードは、下のリンクに置いてあります。
https://github.com/kntks/blog-code/tree/main/2023/09/boto3-monkeypatch
pytest の monkeypatch と boto3 の stubber の組み合わせに焦点を当てて記事を書いたため、全体的に説明不足なところもあると思いますが、テストコードを書くときの参考になれば幸いです。