かべぎわブログ

ブログです

motoでboto3のテストをする

概要

motoをつかってboto3のテストをしてみたいと思います。

そもそもmotoとは

AWSサービスのモックをつくることができるやつです。
mock botoでmotoです(たぶん)

motoでテストしてみる

実際にやってみます。
こんかいはS3にオブジェクトを置くスクリプトのテストをしてみます。

motoのインストール

pipでできます。

pip install moto

テストされる.py

S3にオブジェクトを置くだけのスクリプトです。

import boto3

class s3(object):
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def put(self):
        s3 = boto3.client('s3', region_name='ap-northeast-1')
        s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)

テストする.py

オブジェクトをGETして中身が正しいかどうかを確かめています。
kabegiwa_blogという名前のオブジェクトの中身がawesomeであればOKです。

import boto3
from moto import mock_s3
from put_object import s3


@mock_s3
def test_put_object():
    conn = boto3.resource('s3', region_name='ap-northeast-1')
    conn.create_bucket(Bucket='mybucket')

    model_instance = s3('kabegiwa_blog', 'is awesome')
    model_instance.put()

    body = conn.Object('mybucket', 'kabegiwa_blog').get()['Body'].read().decode("utf-8")

    assert body == 'is awesome'

test_put_object()

実際にテストしてみる

テストしてみます。
テストする.pyを実行します。
わかりやすくするためにpytestを利用します。

pytestについてはまえにかきました。

www.kabegiwablog.com

テストがとおっていることがわかる。

pytest -v test_put_object.py

=== test session starts ===
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- c:\users\takak\appdata\local\programs\python\python37-32\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\takak\Downloads\moto_test
collected 1 item

test_put_object.py::test_put_object PASSED                                                                       [100%]

テストする.pyのassertの部分を以下のように変えてもう一度テストしてみます。

    assert body == 'is not awesome'

テスト実行するとエラーになっていることがわかります。

pytest -v .\test_put_object.py

=== test session starts ===
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- c:\users\takak\appdata\local\programs\python\python37-32\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\takak\Downloads\moto_test
collected 0 items / 1 errors

=== ERRORS ===
____ ERROR collecting test_put_object.py ___
test_put_object.py:18: in <module>
    test_put_object()
..\..\appdata\local\programs\python\python37-32\lib\site-packages\moto\core\models.py:80: in wrapper
    result = func(*args, **kwargs)
test_put_object.py:16: in test_put_object
    assert body == 'is not awesome'
E   AssertionError: assert 'is awesome' == 'is not awesome'

結局なにこれ?

mockなのでmybucketというAWSサービスはつくられていないです。
そしてオブジェクトも作成されていないです。
というかそんなバケット名はたぶんもうすでにつかわれているのでつくれないです。

でもなぜテストがとおったか(バケットからオブジェクトをGETできたか)というとmotoが仮想的にmockをつくって応答してくれているからです。

boto3のテストを実施するときはだいたいスクリプトを動かしてはAWSリソースを消してーとか、既存のものに影響がないように気をつけなくちゃーとかやっていたけれど、これを使うことでそういうことを気にしなくて良くなります。

注意点

すべてのAWSリソースがテストできるわけではないです
以下にいろいろかいてあります。
github.com

おわりに

kabegiwa_blog is awesome.

テスト駆動開発

テスト駆動開発