以前、AnsibleロールのユニットテストからTravis CIまでという記事を書きました。
この方法にgit-flowを加えた**テスト駆動開発(TDD)**がいい感じに出来るようになったのでまとめます。
新規Ansible
ロールの作り方からTDDしながら機能追加していく流れを、
docker-machineのインストールを例に説明します。
Ansibleロール開発プロジェクトを始める
ロールを開発するgitリポジトリ名をansible-role-docker-machine
とします。
このような名前にする理由は、将来Ansible Galaxy
に登録される時にansible-role-
部分は無視されるからです。(Ansible Galaxy
ではロール名がユーザー名.docker-machine
となります)
ロールの雛形ファイルを生成する
以下のコマンドでロールの雛形を自動生成します。
ansible-galaxy init ansible-role-docker-machine
git
リポジトリを作ってコミットします
cd ansible-role-docker-machine
git init
git add .
git commit -a -m 'Generated by `ansible-galaxy init ansible-role-docker-machine`'
AnsibleロールのユニットテストからTravis CIまでに書いた
セットアップ手順を自動化するスクリプトでユニットテストをインストールします。
curl -sL https://raw.githubusercontent.com/tumf/ansible-unit-test/master/ansible-role-test-init |bash
git add .
git commit -a -m 'Generated by `ansible-role-test-init`'
以上で雛形ファイルの準備は完了です。
docker-machine
のインストールを実装する
docker-machine
は公式のドキュメントにある通り、以下のコマンドでインストールできます。
$ curl -L https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64 >/usr/local/bin/docker-machine && \
chmod +x /usr/local/bin/docker-machine
つまり、https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64
から/usr/local/bin/docker-machine
をダウンロードして実行権限をつける...ということが当面の目的(Spec)となります。
テストを**テストファーストで(!!重要!!)**書きます。ここではテストケース名を単にinstall
とします。
テストケースは以下のようにしてtests/cases/install
以下に作成します。
mkdir -p tests/cases/install/usr/local/bin
curl -L https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64 >tests/cases/install/usr/local/bin/docker-machine
chmod +x tests/cases/install/usr/local/bin/docker-machine
またこのテストケースを実現するためのプレイブックをtests/test.yml
に記述します。(雛形のままです)
---
- hosts: 127.0.0.1
connection: local
tags:
- install
roles:
- role: ../..
tasks:
- debug: msg="The test case is succeeded."
これでテストの準備完了です。早速テストを実行してみます。
$ ./tests/run
* Test: install
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [debug msg="The test case is succeeded."] *******************************
ok: [127.0.0.1] => {
"msg": "The test case is succeeded."
}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0
Binary files tests/cases/install/usr/local/bin/docker-machine and tests/outputs/install/usr/local/bin/docker-machine differ
TestCase: install ERROR
1 error(s)
テストファーストなので期待通り失敗しました。これを成功させることが当面の目標となります。
ロールを実装する
ロールを実装します。tasks/main.yml
にタスクを記述します。
- name: Create Install Directory
file: path="{{ ansible_unit_test_prefix_dir }}/usr/local/bin" state=directory recurse=yes
- name: Install Docker Machine
get_url: >
url="https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64"
dest="{{ ansible_unit_test_prefix_dir }}/usr/local/bin/docker-machine"
mode="755"
簡単に上記のようにしました、ポイントは出力先をテスト先に向けるためのansible_unit_test_prefix_dir
の記述です。
テストすると以下のように無事テストがパスするようになりました。(DockerMachineをダウンロードするため時間がかかります)
-> % ./tests/run
* Test: install
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [../.. | Create Install Directory] **************************************
changed: [127.0.0.1]
TASK: [../.. | Install Docker Machine] ****************************************
changed: [127.0.0.1]
TASK: [debug msg="The test case is succeeded."] *******************************
ok: [127.0.0.1] => {
"msg": "The test case is succeeded."
}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=4 changed=2 unreachable=0 failed=0
TestCase: install OK
1 test case(s) passed
ここまで一度gitにコミットしておきましょう
git-flowでfeatureを追加
粗くではありますが動くようになりましたので、git-flowでfeatureを追加していきます。
まず、git-flow
を全てデフォルト設定で初期化します
git flow init -d
さて、やりたいことは沢山ありますが、まずはTDDを快適に回せるようにテスト時にDockerMachine
を毎回ダウンロードするのを抑制したいと思います。
実現方法としてダウンロードURLをdocker_machine_url
のような変数として、
テスト時はこれを上書きするようにします。
まず、git-flow
でfeatureを開始します
git flow feature start add_docker_machine_url
ブランチがfeatures/add_docker_machine_url
に切り替わります。
次にtaskに直書きしているURLを変数に書き換えます。
- name: Install Docker Machine
get_url: >
url="{{ docker_machine_url }}"
dest="{{ ansible_unit_test_prefix_dir }}/usr/local/bin/docker-machine"
mode="755"
デフォルト値として以下を追加します。
docker_machine_url: https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64
テスト時はどこかもっと軽い物をダミーとして落とすことにします。
どこでもいいのですが私はGistを利用しました。
これをテスト側でセットします
- hosts: 127.0.0.1
connection: local
tags:
- install
roles:
- role: ../..
docker_machine_url: https://gist.githubusercontent.com/tumf/579c84e276b6d2d88e09/raw
tasks:
- debug: msg="The test case is succeeded."
これでテスト時のみ軽いGist
からのダミーファイルダウンロードに切り替わるはずです。
早速テストしてみます。
-> % ./tests/run
* Test: install
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [../.. | Create Install Directory] **************************************
changed: [127.0.0.1]
TASK: [../.. | Install Docker Machine] ****************************************
changed: [127.0.0.1]
TASK: [debug msg="The test case is succeeded."] *******************************
ok: [127.0.0.1] => {
"msg": "The test case is succeeded."
}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=4 changed=2 unreachable=0 failed=0
Binary files tests/cases/install/usr/local/bin/docker-machine and tests/outputs/install/usr/local/bin/docker-machine differ
TestCase: install ERROR
1 error(s)
上記の用にテストは失敗します。最初にテストケースinstall
を作った時においた本物のバイナリとGistのダミーファイルが違うと言われています。
この結果は正しいので、テストケースの方を修正します。
このような場合、テストケースの修正は以下のコマンドで上書きできます。
-> % ./tests/run -w install
テストが正しく通るようになりました。
-> % ./tests/run
* Test: install
PLAY [127.0.0.1] **************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [../.. | Create Install Directory] **************************************
changed: [127.0.0.1]
TASK: [../.. | Install Docker Machine] ****************************************
changed: [127.0.0.1]
TASK: [debug msg="The test case is succeeded."] *******************************
ok: [127.0.0.1] => {
"msg": "The test case is succeeded."
}
PLAY RECAP ********************************************************************
127.0.0.1 : ok=4 changed=2 unreachable=0 failed=0
TestCase: install OK
1 test case(s) passed
上手く行ったようなので、コミットしてadd_docker_machine_url
のfeatureを終了します。
git commit -a -m 'Impliments add_docker_machine_url feature'
git flow feature finish add_docker_machine_url
これで、develop
ブランチに戻りました。featureの完了ですお疲れ様でした!
以上のように、ローカルマシン上で手軽にテストを繰り返すことにより安心してAnsible
ロールに機能追加することができるようになりました。
Ansible
のユニットテストは従来のVagrant
等を利用したテストに変わるものではなく、
あくまでも、開発中に不具合が紛れ込む可能性を防ぎ開発効率を上げる1手です。
今回作ったUnitTesting Framework for Ansible rolesはリンク先に公開していますので不具合やご要望などありましたらPRやIssueをお気軽に!