LoginSignup
8
7

More than 5 years have passed since last update.

Ansibleモジュールを自作したらunitテストをしてみよう

Last updated at Posted at 2018-10-24

前回は Ansibleモジュールを自作したらsanityテストをしてみよう という記事を書きましたが今回は自作したモジュールの unitテスト をしてみようと思います。
Ansibleのテストツールに組み込まれているunitテストはpytestが使われています。

1. 環境

項目 バージョン
OS CentOS7.5
Python 3.6.6
Ansible devel

2. テスト用ドキュメント

3. unitテストで使うソース

3-1. 作成したモジュール

前回作った output_name.py に手を入れてみます。
sum という関数を作って引数を足して戻すだけの関数を付け加えたものに対してユニットテストをしてみます。
イメージを持ってもらうということで簡単なものにしています。

output_name.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright: (c) 2018, sky_joker
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type


ANSIBLE_METADATA = {
    'metadata_version': '1.1',
    'status': ['preview'],
    'supported_by': 'community'
}


DOCUMENTATION = '''
module: output_name
short_description: module that outputs a name.
description:
    - Output the specified name.
requirements:
    - python >= 2.7
options:
    name:
        description:
            - Specify name.
        required: True
'''

EXAMPLE = '''
---
- output_name:
    name: taro
  register: r

- debug: msg="{{ r }}"
'''

from ansible.module_utils.basic import AnsibleModule


def sum(a, b):
    return a + b


def main():
    argument_spec = dict(
        name=dict(type="str", required=True)
    )

    module = AnsibleModule(argument_spec, supports_check_mode=True)

    result = dict(changed=False)

    name = module.params['name']
    if(name):
        result['name'] = name
        module.exit_json(**result)
    else:
        module.fail_json(msg="Please specify name.")


if __name__ == "__main__":
    main()

3-2. テストモジュール

テストモジュールは以下のものを使用します。

test_output_name.py
from ansible.modules.salf_made.output_name import sum

def test_sum():
    assert sum(1, 2) == 3

4. テストの準備

4-1. リポジトリのクローン

[example@localhost ~]$ git clone https://github.com/ansible/ansible.git

4-2. venv作成

テスト用にモジュールをインストールするのでvenvを作成します。

[example@localhost ~]$ cd ansible/
[example@localhost ansible]$ python36 -m venv venv

4-3. 必要なモジュールのインストール

[example@localhost ansible]$ source venv/bin/activate
(venv) [example@localhost ansible]$ yum -y install gcc python36-devel
(venv) [example@localhost ansible]$ pip3 install -r test/runner/requirements/units.txt

5. テスト実施

unitテストはテストモジュールから本体モジュールを呼び出す必要があるので、指定した場所に保存する必要があります。
ここでは以下の場所に保存します。

項目 場所
output_name.py $ANSIBLE/lib/ansible/modules/salf_made
test_output_name.py $ANSIBLE/test/units/modules/salf_made

5-1. ディレクトリの作成及びモジュールの移動

ディレクトリの作成をします。

(venv) [example@localhost ansible]$ mkdir lib/ansible/modules/salf_made
(venv) [example@localhost ansible]$ mkdir test/units/modules/salf_made

本体のモジュール及びテストモジュールを作成します。

(venv) [example@localhost ansible]$ vi lib/ansible/modules/salf_made/output_name.py
(venv) [example@localhost ansible]$ vi test/units/modules/salf_made/test_output_name.py

5-2. テスト実施

ansible ディレクトリ内でテストを実行します。
unitテスト では、モジュール本体ではなくモジュール名をテストツールに引数で渡します。

成功すると以下のようになります。

success_unit_test.gif

(venv) [example@localhost ansible]$ ./bin/ansible-test units --python 3.6 output_name
Unit test with Python 3.6
============================================= test session starts ==============================================
platform linux -- Python 3.6.6, pytest-3.9.2, py-1.7.0, pluggy-0.8.0
rootdir: /home/example/ansible, inifile: tox.ini
plugins: xdist-1.23.2, forked-0.2
gw0 [1] / gw1 [1]
scheduling tests via LoadScheduling
.
--------------- generated xml file: /home/example/ansible/test/results/junit/python3.6-units.xml ---------------
=========================================== 1 passed in 0.33 seconds ===========================================

失敗(テストが想定外の値を返したりした場合)すると以下のようになります。

fail_unit_test.gif

(venv) [example@localhost ansible]$ ./bin/ansible-test units --python 3.6 output_name
Unit test with Python 3.6
============================================= test session starts ==============================================
platform linux -- Python 3.6.6, pytest-3.9.2, py-1.7.0, pluggy-0.8.0
rootdir: /home/example/ansible, inifile: tox.ini
plugins: xdist-1.23.2, forked-0.2
gw0 [1] / gw1 [1]
scheduling tests via LoadScheduling
F
=================================================== FAILURES ===================================================
___________________________________________________ test_sum ___________________________________________________
[gw0] linux -- Python 3.6.6 /home/example/ansible/venv/bin/python
def test_sum():
>       assert sum(1, 2) == 4
E       assert 3 == 4
E        +  where 3 = sum(1, 2)

test/units/modules/salf_made/test_output_name.py:6: AssertionError
--------------- generated xml file: /home/example/ansible/test/results/junit/python3.6-units.xml ---------------
=========================================== short test summary info ============================================
FAIL test/units/modules/salf_made/test_output_name.py::test_sum
=========================================== 1 failed in 0.34 seconds ===========================================
ERROR: Command "pytest --boxed -r a -n auto --color yes --junit-xml test/results/junit/python3.6-units.xml test/units/modules/salf_made/test_output_name.py" returned exit status 1.

6. 参考

8
7
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
8
7