LoginSignup
17
15

More than 5 years have passed since last update.

git-flowを利用したAnsibleロールのテスト駆動開発の流れ

Last updated at Posted at 2016-01-08

以前、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に記述します。(雛形のままです)

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にタスクを記述します。

task/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を変数に書き換えます。

task/main.yml
- name: Install Docker Machine
  get_url: >
    url="{{ docker_machine_url }}"
    dest="{{ ansible_unit_test_prefix_dir }}/usr/local/bin/docker-machine"
    mode="755"

デフォルト値として以下を追加します。

defaults/main.yml
docker_machine_url: https://github.com/docker/machine/releases/download/v0.5.5/docker-machine_linux-amd64

テスト時はどこかもっと軽い物をダミーとして落とすことにします。
どこでもいいのですが私はGistを利用しました。
これをテスト側でセットします

tests/test.yml
- 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をお気軽に!

17
15
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
17
15