LoginSignup
2
1

More than 1 year has passed since last update.

はじめてのぎっとはぶあくしょんず

Posted at

きっかけ

GitHubActionsを最近学んでいます。もしGitHubActionsで自動テスト動作する環境を作るためには、どういう感じに書くのだろうか、と思い作ってみました。

実施した内容

  • CIの自動テストをGitHubActionsで動かす
    • 主なライブラリはPytestとLocalStackを使う
  • 疑似プロダクションコード(main.py)は、S3にオブジェクトをを作成する
  • テストコードでは(test_main,py)は、指定したオブジェクト名がS3に存在するかテストする
name: localstack-ci-example
on: pull_request

jobs:
  ci-example:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: start LocalStack
        run: docker-compose up -d localstack
      - name: Wait for LocalStack to start up for up to 60 seconds
        run: "end_time=$(( $(date +%s)+60));
              while [[ $(curl -s localhost:4566 | jq -r '.status') != 'running' ]];do
                [[ $(date +%s) > ${end_time} ]] && exit 1 || sleep 1;
              done"

      - run: pipx install pipenv
      - uses: actions/setup-python@v3
        with:
          python-version: '3.10'
      - run: pipenv install --dev

      - name: Execute unit test
        run: pipenv run pytest tests/
docker-compose.yml
version: '3.8'

services:
  localstack:
    image: localstack/localstack:latest
    environment:
      - SERVICES=s3
      - DEFAULT_REGION=ap-northeast-1
      - TZ=Asia/Tokyo
    ports:
      - 4566:4566
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
boto3 = "*"

[dev-packages]
pytest = "*"
pytest-mock = "*"

[requires]
python_version = "3.10"
main.py
import boto3
from datetime import datetime as dt

s3 = boto3.resource(
    's3'
)

def main():
    # ファイル名はカレント日時
    upload_object(dt.now().strftime('%Y%m%d%H%M%S'))

def upload_object(obj_name: str) -> None:
    bucket = s3.Bucket('test-bucket')
    bucket.Object(obj_name).put()

if __name__ == '__main__':
    main()
test_main.py
import pytest
import boto3
import botocore
import os
import sys
from datetime import datetime as dt

currrent_path = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(currrent_path, '../'))
import main

s3 = boto3.resource(
    's3',
    endpoint_url='http://localhost:4566',
    aws_access_key_id='DEFAULT_ACCESS_KEY',
    aws_secret_access_key='DEFAULT_SECRET'
)
obj_name :str = 'test_file_' + dt.now().strftime('%Y%m%d%H%M%S')

@pytest.fixture(scope='session', autouse=True)
def setup_s3():
    try:
        s3.create_bucket(
            Bucket='test-bucket',
            CreateBucketConfiguration={'LocationConstraint': 'ap-northeast-1'}
        )
    except s3.meta.client.exceptions.BucketAlreadyOwnedByYou:
        # バケットがすでに存在するなら何もしない
        pass


def test_uploead_object(mocker):
    # 向き先をlocalstackに変更
    mocker.patch('main.s3', s3)

    # テスト対象呼び出し
    main.upload_object(obj_name)

    bucket = s3.Bucket('test-bucket')
    # S3にファイルが存在するかassert
    ls_result = bucket.meta.client.list_objects_v2(Bucket=bucket.name, Prefix=obj_name)
    assert ls_result.get('Contents')

    # 後片付け
    bucket.Object(obj_name).delete()

おわりに

GiHubActionsで動かすならこういうことをやるんだろうな、と想像しながら書いてみました。
実際に使うときは、pipenv installLocalStackのpullとupは時間が掛かるので、cacheを使用したほうが良さそうですね。

参考リンク

https://dev.classmethod.jp/articles/localstack-on-github-actions-sample/
https://note.com/dd_techblog/n/n75bffb92874d
https://zenn.dev/alivelimb/articles/20220508-aws-python-testing

2
1
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
2
1