CircleCIでFlaskアプリの自動テストができるようにする(Flaskで簡単なWebサービスを作ってみる[第6回])
はじめに
PythonのWebアプリケーションフレームワークFlaskを使って、「消耗品買い物リスト」を作ってみます。
今回はテスト自動化の設定を行います。
前回まで
- 0回 : Flaskで簡単なWebサービスを作ってみる
- 1回 : スプレッドシート+Google Apps Scriptでプロトタイプを作る
- 2回 : FigmaでUI制作をしてみたが早々に次のフェーズに進んだ件
- 3回 : DockerでFlaskが動き、簡単なテストが通る状態を作る
- 4回 : [スクショ付き]AWSにVPCを構築し、EC2を立てる
- 5回 : EC2でDockerコンテナを起動し、Flaskを動かす
今回やること
前回までで、本番環境へのデプロイができるようになったところで、テスト自動化・デプロイ自動化の設定をしていきます。
実現したいこと
- テスト自動化 ← 本記事はここまで
- 変更がPushされたらテストが自動で走る
- デプロイ自動化
- masterに変更がPush(基本的にはブランチのマージ)がされたらテストが自動で走り、テストが通ると自動で本番環境にデプロイする
採用ツール: CircleCI
CI/CDツールはCircleCIを採用します。
以前CI/CD何もわからん奴がCircleCIでPythonリポジトリのビルドを通すまでで触ったのと、業務でも使い込もうと取り組んでいるのが理由です。
流れ
- CircleCIプロジェクト作成
- 設定ブランチをPull
- requirements.txtを作成
- config.ymlを調整
- ビルド・テストが通ることを確認
- 設定ブランチをmasterにマージ
CircleCIプロジェクト作成
※前提 : CircleCIアカウントは作成済み、GitHubアカウントとの連携済み
CircleCIページからログインし、ビルドするプロジェクトをGitHubリポジトリから選択します。
Pythonの設定がデフォルトで表示されますが、後で変更するので気にせずAdd Projectしてビルドを開始します。
色々あって落ちます。
このあとは、当該リポジトリをチェックアウトしてきてから作業進めていきます。
設定ブランチをPull
※ここからは、ローカル開発環境にて作業します。
前項の操作によって、circleci-project-setupというブランチが作成されるので、リモートリポジトリからfetchしてチェックアウトします。
$ git fetch
$ git checkout -b circleci-project-setup origin/circleci-project-setup
requirements.txtを作成
Pythonアプリのビルドにおいては、requirements.txtというファイルをリポジトリ直下に配置し、その中身をインストールするというプロセスが入ります。
なので、必要なライブラリを記載したrequirements.txtを生成します。
ローカルで作業しているコンテナに入り、pip freeze
を使って使用ライブラリを書き出します。
(コンテナ内でやらないと、ホストPCに入っているライブラリがすべて書き出されてしまうため)
# ローカルのコンテナ起動
$ docker ps -a
$ docker start [container_name]
# コンテナに入る
$ docker exec -it [container_name] /bin/bash
# コンテナ内で書き出し
root@1caa75e54efb:/workdir# pip freeze > requirements.txt
requirements.txtの中身は私の場合は以下でした。
astroid==2.4.2
click==7.1.2
Flask==1.1.2
isort==4.3.21
itsdangerous==1.1.0
Jinja2==2.11.2
lazy-object-proxy==1.4.3
MarkupSafe==1.1.1
mccabe==0.6.1
pylint==2.5.3
six==1.15.0
toml==0.10.1
typed-ast==1.4.1
Werkzeug==1.0.1
wrapt==1.12.1
生成されたファイルをリポジトリ直下に配置しておきます。
config.ymlを調整
調整前
デフォルトでは以下のようなテンプレートがconfig.ymlとして追加されます。
version: 2.1
orbs:
python: circleci/python@0.2.1
jobs:
build-and-test:
executor: python/default
steps:
- checkout
- python/load-cache
- python/install-deps
- python/save-cache
- run:
command: ./manage.py test
name: Test
workflows:
main:
jobs:
- build-and-test
このままでは動かないので、調整していきます。
調整後
version: 2
jobs:
build-and-test:
working_directory: ~/to-buy-list
docker:
- image: circleci/python:3.7.3
steps:
- checkout
- restore_cache:
keys:
- pip--{{ checksum "requirements.txt" }}
- run:
name: Install dependencies
command: pip install --user -r requirements.txt
- save_cache:
key: pip--{{ checksum "requirements.txt" }}
paths: /home/circleci/.local/bin/
- run:
command: python -m unittest discover tests
name: Test
working_directory: ~/to-buy-list/src
workflows:
version: 2
workflows:
jobs:
- build-and-test
ローカルでCircleCIを実行できるようにする
GitHubにPushするとCircleCIが実行されるようになるのですが、細かな構文の修正や動作確認には煩雑すぎるので、ローカルでCircleCIを実行できるようにします。
ちなみに、デフォルトで追加されるconfig.ymlはversion: 2.1ですが、ローカルでのCircleCIにはまだ対応していないので、対応済みの2.0で書きます。
CircleCIのインストール
$ curl https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh --fail --show-error |bash
$ circleci update check
構文チェック
$ circleci config validate
Config file at .circleci/config.yml is valid.
と出れば構文はOKです。
実行
$ circleci build --job build-and-test
--job [job名]
でjobを指定して実行します。
config.ymlの変更点
主な変更点は以下です。
- versionを2.1→2に
- orbs, executorなど、2.1以降対応の記法を削除
- Orbのコマンド(python/load-cacheなど)を書き換え
- Test部分、テストディレクトリのテストを実行するコマンドに変更
「Orbのコマンド(python/load-cacheなど)を書き換え」については補足します。
それ以外は調整後のconfig.ymlをご確認ください。
Orbのコマンド(python/load-cacheなど)を書き換え
python/load-cache以降の3行は、2.1での書き方(正確には、Orbという、コマンドなどを再利用可能なパッケージにしたもの)なので、2.0での書き方に直します。
- python/load-cache
- python/install-deps
- python/save-cache
公式ドキュメントのCircleCI Orb Registry
のページにて、当該コマンドのShow Command Source
をクリックすると、実行されているコマンドの中身を調べることができるので、これを見ながら置き換えていきます。
python/load-cache
description: Load cached Pip packages.
parameters:
dependency-file:
default: requirements.txt
description: The file to install dependencies from.
type: string
key:
default: pip
description: The cache key to use. The key is immutable.
type: string
steps:
- restore_cache:
keys:
- '<< parameters.key >>-{{ checksum "<<parameters.dependency-file>>" }}'
同様の内容を実行するため、以下のように記載
- restore_cache:
keys:
- pip--{{ checksum "requirements.txt" }}
python/install-deps
description: Install packages from requirements.txt (or any other file) via Pip.
parameters:
dependency-file:
default: requirements.txt
description: The file to install dependencies from.
type: string
local:
default: true
description: 'Install packages for local user, not globally. Defaults to true.'
type: boolean
steps:
- run:
command: |
if << parameters.local >>; then
pip install --user -r << parameters.dependency-file >>
else
pip install -r << parameters.dependency-file >>
fi
name: Install Dependencies
同様の内容を実行するため、以下のように記載
- run:
name: Install dependencies
command: pip install --user -r requirements.txt
python/save-cache
description: Save Pip packages to cache.
parameters:
dependency-file:
default: requirements.txt
description: The file that the dependencies are installed from.
type: string
key:
default: pip
description: The cache key to use. The key is immutable.
type: string
lib-path:
default: /home/circleci/.local/lib/
description: The path where the requirements are saved to.
type: string
steps:
- save_cache:
key: '<< parameters.key >>-{{ checksum "<<parameters.dependency-file>>" }}'
paths:
- /home/circleci/.local/bin/
- << parameters.lib-path >>
同様の内容を実行するため、以下のように記載
- save_cache:
key: pip--{{ checksum "requirements.txt" }}
paths: /home/circleci/.local/bin/
ビルド・テストが通ることを確認
config.ymlの編集が終わったら、$ circleci build --job build-and-test
を実行し、Success!
となることを確認し、変更内容をCommit, Pushします。
CircleCIのダッシュボードを見ると、ビルド・テストが成功していることが確認できます。
※ローカルCircleCIの注意点
config.yml以外のソースに変更を入れた場合、その変更をリモートリポジトリにPushしてからでないとローカルのCircleCIがうまく動かないことがあります。
ローカルで動かす場合も、仕組みとしてはリモートリポジトリをチェックアウト→ビルドプロセスという流れなので、例えばリモートリポジトリに存在しないファイルがビルドプロセスに含まれていると落ちます。
今回だと、requirements.txtやtestsディレクトリを作成しましたが、それらをPushした上で、ローカルで動作チェックという流れになります。
設定ブランチをmasterにマージ
ここまでで、基本的なビルド・テストの設定は完了できたので、設定ブランチ(circleci-project-setup
)をmasterにマージします。
これで、リモートリポジトリに何かをPushされると、そのブランチでCircleCIがビルド・テストを自動でしてくれるようになりました。
これで自動テストの準備は完了です。あとは開発を進めていく中で、必要に応じてカスタマイズをしていこうと思います。
終わりに
今回で自動テストまで構築できました。
次回は自動デプロイの構築をやっていきます。
ディスカッション
コメント一覧
まだ、コメントがありません