CI初心者なので、CircleCIを使ってローカルでpytestを動かしてみた。
年末に挙げた目標通り『テスト駆動Python』を読んで、pytestをCIツールで使ってみたくなりました。
興味があった点がわかったので、早速ローカルのCircleCIでpytestを試してみたメモです。
極力手短に、ほかの資料で分かりにくかった点をまとめたので、ご了承ください。
『テスト駆動Python』以外に、ネット記事2件も参考にさせていただきました。ありがとうございました。
qiita.com
blog.vtryo.me
pytestについて
公式で挙げられている特徴としては以下の6点です。
Features
- Detailed info on failing assert statements (no need to remember self.assert* names);
- Auto-discovery of test modules and functions;
- Modular fixtures for managing small or parametrized long-lived test resources;
- Can run unittest (including trial) and nose test suites out of the box;
- Python 3.5+ and PyPy 3;
- Rich plugin architecture, with over 315+ external plugins and thriving community;
pytest: helps you write better programs — pytest documentation
個人的には、fixtureにより、シンプルにUnitテストを書くことができるのが最大の特徴だと思いました。
fixtureを使うと、Unitテストを実施する前に、前処理的に実行しておかないといけないテストの条件を、関数としてまとめておくことができます。
実行するテストは条件を満たすと自動的にpytestが発見して実行してくれます("test_xxx"や"xxx_test"という関数名になっているなど)。
pytestの使い心地
(当たり前ですけど、)パラメータを振ってテストを作成することが多いので、特にどのようにパラメータを決定できるかに興味がありました。
テストにパラメータを渡す場合
@pytest.mark.parametrizeデコレータでテストに渡すパラメータを設定することができます。
import pytest @pytest.mark.parametrize('item',[(1,2,3),(4,5,6)]) def test_defaults(item): assert 1 in item
fixtureを使って前処理のパラメータを変える
fixtureにも@pytest.fixtureデコレータの引数としてparams=xxxを渡すことでパラメータを渡すことができます。
import pytest @pytest.fixture(params=[(1,2,3),(4,5,6)]) def default(request): return request.param def test_defaults(default): assert 1 in default
これで様々な前処理条件でテストを実行することが可能です。
ローカルでのCircleCIの実行
次に、CircleCIで実行してみます。
CircleCIはSaaSですが、動作確認用にローカル環境で動くものが提供されています。
クラウド版でやった方が実践的ですが、pytestと合わせると話が長くなってしまって自分で勉強した時につらかったので、今回はローカルでの実行に留めます。
ローカルでのCircleCIのインストール
macだとhomebrewでインストールが可能です。
※Docker for Desktopはインストール済みの前提です。
brew update brew install circleci
CircleCI用のymlの作成
ルートに.circleci/config.ymlを作成する必要があります。
これはdockerfileやembulkなどのconfigファイルに慣れているとだいぶ分かりやすいので、ちんぷんかんぷんの場合はこの辺を色々やってみると良さそうでした。
version: 2 jobs: build: docker: - image: circleci/python:3.6.3 steps: - checkout - run: name: install dependencies command: | python3 -m venv venv . venv/bin/activate pip install pytest pip install pytest-cov - run: name: run test command: | . venv/bin/activate pytest --junitxml=test-reports/junit.xml - run: name: run test-cov command: | . venv/bin/activate pytest --cov=src
実行
"テストにパラメータを渡す場合"のコードをtest_sample.pyとして保存し、CircleCIにpytestを実行してもらいます。
ディレクトリ構成は以下のようにしておけばひとまず動きます。
. ├── .circleci │ └── config.yml ├── README.md └── test_sample1.py
まずconfig.yml自体に構文ミスがないことを確認します。
circleci config validate #大丈夫だったら"Config file at .circleci/config.yml is valid."が出力される。
続いて、コードをcommitし、CircleCiを実行します。
circleci local execute #テストが成功だった場合、最後に"Success!"を出力する。 #失敗だった場合は、"Task failed"などが出力される。
ちなみに、コードをcommitしないとCircleCIで使うDockerイメージをビルドする際にコードが反映されないようでした。
初めて試してみる用に、スクラッチでディレクトリを作った人は注意が必要です。
また、circleci local executeはテストが失敗だった場合は"Task failed"などが出力されます。
初めてだったので、なんか設定が間違っているのかと思って右往左往しましたが、これで正常みたいですね。。。
次のステップ
ともあれ、これで自分で書いたUnitテストをpytestで実行し、これを(localですが)CircleCIで動かすことができるようになりました。
次のステップは、
を目指します。
CircleCIの方は、localでできているのでクラウド版でももうちょい頑張ればできそうです。
テスト駆動開発の方は学習済みですが、全然実践でできるレベルではないので、カリカリコードを書いたり、『テスト駆動開発』を読んでやっていこうかなと思っています。
参考
『テスト駆動Python』:
- 作者:Brian Okken
- 出版社/メーカー: 翔泳社
- 発売日: 2018/08/29
- メディア: 単行本(ソフトカバー)
『テスト駆動開発』:
TDDの有名な本。