AWSリソースをmotoを使ってモックしてみた

こんにちは、SCSKの齋藤です。

今回はAWSサービスのモックを作成し、プログラムをテストする方法の簡単な例をブログにしました。

 

モックとは?

ソフトウェアテストを行う際に、代用する下位モジュールスタブの一種です。

プログラムを作成した際に、作成したプログラムから別のモジュールを呼び出したりする際に、別のモジュールの代用品として理想的な値を返すようなオブジェクトです。

例えば、AWSリソースを操作するようなLambdaのソースコードをテストする場合、AWSリソースの部分を代用品としてモックを使うことで、ソースコードが正しく動作するかをテストできます。

 

AWSのモックツール

代表的なものとして、motoがあります。

Moto: Mock AWS Services — Moto 5.0.12.dev documentation

これを用いると、開発環境のPC上などで擬似的にAWSリソースを作成することができます。

全てのAWSリソースは網羅されていないらしいのですが、Lambdaと連携されるような代表的なサービス(S3、SQS、DynamoDB、STSなど)は、含まれております。

 

motoを使ってPythonのテストをしてみた!

今回は実際にmotoを使ったモックによるテストを行ってみます。

今回私が検証した環境は下記になります。

マシン:Mac Book Pro

IDE:Visual Studio Code

仮想環境構築

今回は、プログラムを実行するための仮想環境から構築していきたいと思います。

仮想環境構築の前に、プロジェクトフォルダの作成を行います。

PC上のどこでも良いので、空のプロジェクトフォルダをまず作成します。中身は何も作成しません。

 

その次に、ターミナルを開いて、下記コマンドを入力し、仮想環境をPython3代で作成します。

仮想環境名は各自で命名してください。(今回は、myvenvで作成しました。)

$ cd プロジェクトフォルダ名
$ python3 -m venv 仮想環境名

 

仮想環境を構築後、下記コマンドで仮想環境をアクティベートします。

・Linux・Mac

$ source 仮想環境名/bin/activate

もしくは、

$ . 仮想環境名/bin/activate

・Windows

$ .\仮想環境名\Scripts\activate

仮想環境に切り替わったため、Pythonのバージョン確認をします。

(仮想環境名)$ python -V

先頭に仮想環境名が付与され、Python3代がインストールされているのを確認できます。

そのまま、仮想環境にパッケージのインストールを行います。

今回インストールするのは、AWS SDK for Pythonであるboto3、モックツールのmoto、Pythonのテストツールのpytestの3点です。

pip install boto3
pip install moto
pip install pytest

あくまで仮想環境上でのインストールなので、仮想環境を閉じれば、これらのツールは使えません。

VSCodeでのフォルダ・ファイル作成

VSCode上で、先ほどのプロジェクトフォルダを開きます。

まだ空のフォルダしか作成されていないので、その中にさらにフォルダとファイルを作成していきます。

今回は、下記画像のようなフォルダ構成とすることを目標とします。

このフォルダを実現するために、新たに作成するフォルダは「src」フォルダと「tests」フォルダです。

それ以外のフォルダについては自動で作成されます。

srcフォルダとtestsフォルダ内で作成するファイルをそれぞれ解説いたします。

 

srcフォルダ

app.py
メインのソースコードをこのファイルに書きます。
boto3を用いて、S3のバケットの情報を取得して、返却する処理を実行します。
今回は簡略的に、取得したバケットの1つ目の情報のみを返却します。
boto3でのS3へのリクエストやレスポンスの形は、boto3のドキュメントを参照してください。
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/list_buckets.html
import boto3

def list_bucket():
    s3=boto3.client('s3')
    response=s3.list_buckets()
    bucket_info=response['Buckets'][0]
    return bucket_info

 

testsフォルダ

本フォルダはテストに必要なファイル類を定義します。

__init__.py
テスト対象のファイルがsrcフォルダにありますが、これをtestsフォルダのファイルが読み込めるようにしなければなりません。
そのため、testフォルダのファイルにパス情報を渡す必要があります。

その処理を、下記のコードで実現します。

import os
import sys

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src')))
上記コードで何をしているか内訳を見てみると、
1. os.path.dirname(__file__)・・・開いているファイル(__init__.py)のディレクトリ名を取得します。
(/Users/usename/Desktop/sample-project/tests)
2. os.path.join()関数により、1で取得したディレクトリに、”..”と”src”という文字列を連結します。
(/Users/usename/Desktop/sample-project/tests/../src)
3. os.path.abspath()関数により、2で連結したパスを正規化します。
(/Users/usename/Desktop/sample-project/src)
4. sys.path.append()関数により、3で正規化されたパスをpytestに渡しています。
 
conftest.py
このファイルが本記事の要である、モックをしている箇所になります。
環境構築の際にインストールしたmotoから、mock_awsというツールをインポートしています。
このmock_awsというツールが、ローカル上で、仮想的なAWS環境を実現してくれます。

この仮想的な環境に、「test_bucket」という名前のS3バケットを作成します。

import pytest
from moto import mock_aws
import boto3

@mock_aws
@pytest.fixture
def setup_s3():
    with mock_aws():
        s3=boto3.client('s3')
        s3.create_bucket(
            Bucket='test_bucket', 
            CreateBucketConfiguration={
            'LocationConstraint': 'ap-northeast-1',
        },)
        yield s3
test_app.py
これまで作成したファイルを元に、実際にテストを行うファイルです。
テストの関数に、conftest.pyのsetup_s3関数を継承させます。
これにより、このテストコードはsetup_s3関数内のモックしたS3を使うことができます。
この状態で、テスト対象である、srcフォルダのapp.pyのlist_bucket関数を実行します。
そして、モック化した際に「test_bucket」という名前でS3を作成しているので、その名前が取得できているのかをassert文で評価します。
import app

def test_list_bucket(setup_s3):
    response=app.list_bucket()
    assert response['Name']=='test_bucket'

テストの実行

VSCodeのターミナルを立ち上げて、下記コマンドを入力します。
python -m pytest

テストが合格してます!
これによりモック化して作成したS3バケット「test_bucket」の情報を、正しく取得できたことを確認できました。

モックしないとどうなるか?

今回conftest.pyでモックを作成しました。
しかし、それを作らずにテストした場合は、環境上にセットされているAWS CLIの情報を元に、実際にAWS環境にアクセスされてしまいます。
大規模な開発などの場合、まだAWS環境が用意されていないが、Pythonのソースコードを開発しなければならない場合などはあり得ます。
そうした場合、AWS環境に接続せずとも、正しく動作されていることをテストするには、モックというのがどうしても不可欠になりますね。
そもそも、単体テストというのは、作成したプログラム自身が正しいかどうかを確認するプロセスのため、それ以外のものについては正しい値が返却されるという想定で、モックを作って実施するのは当然かと考えられます。
実際にAWSリソースへのアクセスをしてプログラムが正しく動くかどうかは、機能テストなどの段階で検証するため、単体テストでは適切にモックを使うことを意識すると良いと思います。

まとめ

今回はPython上で、AWSリソースのモックのやり方を簡単に紹介しました。

motoは、大変便利なツールですので、単体テストを行う際はぜひ使うようにしましょう!

著者について

フロントエンドもバックエンドも両方少しずつ勉強して、フルスタックエンジニアを目指してます。
サーバレス開発の楽しさを実感中!

ANGEL Dojo 2021 ANGEL賞、ベストアーキテクチャ賞ダブル受賞
2023 Japan AWS Jr. Champions
2022〜24 Japan AWS All Certifications Engineers

齋藤友宏をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AWSアプリケーション開発クラウドソリューション
シェアする
タイトルとURLをコピーしました