mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
dev_guide: format code in testing_units_modules.rst (#33009)
* dev_guide: highlight Python code snippets * dev_guide: use monospace for inline source code * dev_guide: use links for classes and methods Methods and classes prefixed with :method: and :class: will become links once we have documentation for the relevant classes and methods. Thanks to Toshio for pointing that.
This commit is contained in:
parent
7b19c28438
commit
16bcb0393e
1 changed files with 15 additions and 14 deletions
|
@ -2,6 +2,8 @@
|
|||
Unit Testing Ansible Modules
|
||||
****************************
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
Introduction
|
||||
|
@ -154,12 +156,12 @@ Mock objects (from https://docs.python.org/3/library/unittest.mock.html) can be
|
|||
useful in building unit tests for special / difficult cases, but they can also
|
||||
lead to complex and confusing coding situations. One good use for mocks would be in
|
||||
simulating an API. As for 'six', the 'mock' python package is bundled with Ansible (use
|
||||
'import ansible.compat.tests.mock'). See for example
|
||||
``import ansible.compat.tests.mock``). See for example
|
||||
|
||||
Ensuring failure cases are visible with mock objects
|
||||
----------------------------------------------------
|
||||
|
||||
Functions like module.fail_json() are normally expected to terminate execution. When you
|
||||
Functions like :meth:`module.fail_json` are normally expected to terminate execution. When you
|
||||
run with a mock module object this doesn't happen since the mock always returns another mock
|
||||
from a function call. You can set up the mock to raise an exception as shown above, or you can
|
||||
assert that these functions have not been called in each test. For example::
|
||||
|
@ -272,8 +274,8 @@ There are two problems with running the main function of a module:
|
|||
|
||||
* Since the module is supposed to accept arguments on ``STDIN`` it is a bit difficult to
|
||||
set up the arguments correctly so that the module will get them as parameters.
|
||||
* All modules should finish by calling either the ``module.fail_json`` or
|
||||
``module.exit_json``, but these won't work correctly in a testing environment.
|
||||
* All modules should finish by calling either the :meth:`module.fail_json` or
|
||||
:meth:`module.exit_json`, but these won't work correctly in a testing environment.
|
||||
|
||||
Passing Arguments
|
||||
-----------------
|
||||
|
@ -283,7 +285,7 @@ Passing Arguments
|
|||
|
||||
To pass arguments to a module correctly, use a function that stores the
|
||||
parameters in a special string variable. Module creation and argument processing is
|
||||
handled through the AnsibleModule object in the basic section of the utilities. Normally
|
||||
handled through the :class:`AnsibleModule` object in the basic section of the utilities. Normally
|
||||
this accepts input on ``STDIN``, which is not convenient for unit testing. When the special
|
||||
variable is set it will be treated as if the input came on ``STDIN`` to the module.::
|
||||
|
||||
|
@ -309,9 +311,9 @@ Handling exit correctly
|
|||
.. This section should be updated once https://github.com/ansible/ansible/pull/31456 is
|
||||
closed since the exit and failure functions below will be provided in a library file.
|
||||
|
||||
The ``module.exit_json()`` function won't work properly in a testing environment since it
|
||||
The :meth:`module.exit_json` function won't work properly in a testing environment since it
|
||||
writes error information to ``STDOUT`` upon exit, where it
|
||||
is difficult to examine. This can be mitigated by replacing it (and module.fail_json) with
|
||||
is difficult to examine. This can be mitigated by replacing it (and :meth:`module.fail_json`) with
|
||||
a function that raises an exception::
|
||||
|
||||
def exit_json(*args, **kwargs):
|
||||
|
@ -331,7 +333,7 @@ testing for the correct exception::
|
|||
with self.assertRaises(AnsibleExitJson) as result:
|
||||
my_module.main()
|
||||
|
||||
The same technique can be used to replace ``module.fail_json()`` (which is used for failure
|
||||
The same technique can be used to replace :meth:`module.fail_json` (which is used for failure
|
||||
returns from modules) and for the ``aws_module.fail_json_aws()`` (used in modules for Amazon
|
||||
Web Services).
|
||||
|
||||
|
@ -358,11 +360,10 @@ the arguments as above, set up the appropriate exit exception and then run the m
|
|||
Handling calls to external executables
|
||||
--------------------------------------
|
||||
|
||||
Module must use AnsibleModule.run_command in order to execute an external command. This
|
||||
Module must use :meth:`AnsibleModule.run_command` in order to execute an external command. This
|
||||
method needs to be mocked:
|
||||
|
||||
Here is a simple mock of AnsibleModule.run_command (taken from test/units/modules/packaging/os/test_rhn_register.py and
|
||||
test/units/modules/packaging/os/rhn_utils.py)::
|
||||
Here is a simple mock of :meth:`AnsibleModule.run_command` (taken from :file:`test/units/modules/packaging/os/test_rhn_register.py`)::
|
||||
|
||||
with patch.object(basic.AnsibleModule, 'run_command') as run_command:
|
||||
run_command.return_value = 0, '', '' # successful execution, no output
|
||||
|
@ -379,7 +380,7 @@ A Complete Example
|
|||
------------------
|
||||
|
||||
The following example is a complete skeleton that reuses the mocks explained above and adds a new
|
||||
mock for Ansible.get_bin_path::
|
||||
mock for :meth:`Ansible.get_bin_path`::
|
||||
|
||||
import json
|
||||
|
||||
|
@ -466,7 +467,7 @@ mock for Ansible.get_bin_path::
|
|||
Restructuring modules to enable testing module set up and other processes
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Often modules have a main() function which sets up the module and then performs other
|
||||
Often modules have a ``main()`` function which sets up the module and then performs other
|
||||
actions. This can make it difficult to check argument processing. This can be made easier by
|
||||
moving module configuration and initialization into a separate function. For example::
|
||||
|
||||
|
@ -510,7 +511,7 @@ This now makes it possible to run tests against the module initiation function::
|
|||
|
||||
See also ``test/units/module_utils/aws/test_rds.py``
|
||||
|
||||
Note that the argument_spec dictionary is visible in a module variable. This has
|
||||
Note that the ``argument_spec`` dictionary is visible in a module variable. This has
|
||||
advantages, both in allowing explicit testing of the arguments and in allowing the easy
|
||||
creation of module objects for testing.
|
||||
|
||||
|
|
Loading…
Reference in a new issue