LoginSignup
0
0

More than 5 years have passed since last update.

circleciでAWSサービスを使ったテストをするには?

Last updated at Posted at 2019-01-28

boto3がs3のサービスを使うAWSの接続なしでテストしたいですよね?

motoって?

そこでmotoを使ってきました。

(motoからの例)


import boto3
from moto import mock_s3
from mymodule import MyModel


@mock_s3
def test_my_model_save():
    conn = boto3.resource('s3', region_name='us-east-1')
    # We need to create the bucket since this is all in Moto's 'virtual' AWS account
    conn.create_bucket(Bucket='mybucket')

    model_instance = MyModel('steve', 'is awesome')
    model_instance.save()

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

    assert body == b'is awesome'

Decoratorだけで、サービスがモックされていて、シンプルでテスト書けますね。motoもs3だけじなくて、多くのサービスをサポートしています。

localstackって?

しかし、一昨年ぐらいから、localstack というmotoなどのパッケージをまとまって、完全にサーバとして動かせるAWS仮想環境が提供されてきました。

一応、motoも”Server Mode" (moto_server)がありますが、localstackのいいところは、docker imageを提供しています。大きな差がないのですが、個人的に開発環境に必要なmock(moto)をインストールしなくて済むことは多少すっきり感がします。

ただし、当然ですが、localstackのdockerを立ち上げるだけではすまないですね。現状のコードに工夫が必要になります。

いろいろな方法はあるかと思いますが、このように使っています:
(実際のコードですね。テストコードじゃない)

import os
import boto3

# reference: 
# https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html
DEFAULT_BOTO3_S3_ENDPOINT = 'https://s3.ap-northeast-1.amazonaws.com'
BOTO3_S3_ENDPOINT = os.getenv('BOTO3_S3_ENDPOINT', DEFAULT_BOTO3_S3_ENDPOINT)
s3 = boto3.client('s3', endpoint_url=BOTO3_S3_ENDPOINT)

... 

リジョンを跨ぐとめんどうだろうけど、これでロカールでテストしたい場合、BOTO3_S3_ENDPOINTの環境変数を指定だけでは済みます。

export BOTO3_S3_ENDPOINT=http://localhost:4572

これでこのようにlocalstackが起動されているなら、テストを実行して、AWSと同様にロカールで各サービスを使えます。

docker run --name development-localstack -d --rm -p 4567-4578:4567-4578 -p 8080:8080 localstack/localstack

circleciって?

circleciはCI環境で、そこにもAWSのようにテスト使いたいですよね。
そこでlocalstackでの導入が難しいかなと思ったんですが、以外とらくでした。

まず、dockerの定義配下でlocalstack/localstackのイメージを定義します。

(開発中のDjangoプロジェクトを一部を例として)


version: 2

jobs:
  build:
    working_directory: ~/erwin/
    docker:
      - image: circleci/python:3.6.5
        environment:
          PIPENV_VENV_IN_PROJECT: true
          DJANGO_SETTINGS_MODULE: myproject.settings.circleci
      - image: mdillon/postgis:9.6
        environment:
          POSTGRES_USER: circleci
          POSTGRES_DB: circle_test
      - image: localstack/localstack <---ここ!!!
...

次は、circleciのプロジェクト設定で、コード内で定義した環境変数をEnvironment Variables(環境変数)へ登録します。

BOTO3_S3_ENDPOINT=http://localhost:4572

以上

ポートどうなっているかなと思ったんですが、postgres/postgisのポート設定もないと気が付き、localstackも特別なポート設定なしで、プロジェクトのテストが無事にAWSの代わりにlocalstackを通信していて、テストが通りました。

嬉しい。

motoを使うかlocalstackを使うか正直にあまり変わらないですが、localstackでいいのかな?

次は、これをためしてみようかな:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0