1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
Examples
========
Parametrize your tests
~~~~~~~~~~~~~~~~~~~~~~
Pytest support `test parametrization <https://pytest.org/latest/parametrize.html>`_::
# BAD: If the test fails on nginx, python is not tested
def test_packages(host):
for name, version in (
("nginx", "1.6"),
("python", "2.7"),
):
pkg = host.package(name)
assert pkg.is_installed
assert pkg.version.startswith(version)
# GOOD: Each package is tested
# $ pytest -v test.py
# [...]
# test.py::test_package[local-nginx-1.6] PASSED
# test.py::test_package[local-python-2.7] PASSED
# [...]
import pytest
@pytest.mark.parametrize("name,version", [
("nginx", "1.6"),
("python", "2.7"),
])
def test_packages(host, name, version):
pkg = host.package(name)
assert pkg.is_installed
assert pkg.version.startswith(version)
.. _make modules:
Using unittest
~~~~~~~~~~~~~~
Testinfra can be used with the standard Python unit test framework `unittest
<https://docs.python.org/3/library/unittest.html>`_ instead of pytest::
import unittest
import testinfra
class Test(unittest.TestCase):
def setUp(self):
self.host = testinfra.get_host("paramiko://root@host")
def test_nginx_config(self):
self.assertEqual(self.host.run("nginx -t").rc, 0)
def test_nginx_service(self):
service = self.host.service("nginx")
self.assertTrue(service.is_running)
self.assertTrue(service.is_enabled)
if __name__ == "__main__":
unittest.main()
::
$ python test.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.705s
OK
Integration with Vagrant
~~~~~~~~~~~~~~~~~~~~~~~~
`Vagrant <https://www.vagrantup.com/>`_ is a tool to setup and provision
development environments (virtual machines).
When your Vagrant machine is up and running, you can easily run your testinfra
test suite on it::
vagrant ssh-config > .vagrant/ssh-config
pytest --hosts=default --ssh-config=.vagrant/ssh-config tests.py
Integration with Jenkins
~~~~~~~~~~~~~~~~~~~~~~~~
`Jenkins <https://jenkins-ci.org/>`_ is a well known open source continuous
integration server.
If your Jenkins slave can run Vagrant, your build scripts can be like::
pip install pytest-testinfra paramiko
vagrant up
vagrant ssh-config > .vagrant/ssh-config
pytest --hosts=default --ssh-config=.vagrant/ssh-config --junit-xml junit.xml tests.py
Then configure Jenkins to get tests results from the `junit.xml` file.
Integration with Nagios
~~~~~~~~~~~~~~~~~~~~~~~
Your tests will usually be validating that the services you are deploying run correctly.
This kind of tests are close to monitoring checks, so let's push them to
`Nagios <https://www.nagios.org/>`_ !
The Testinfra option `--nagios` enables a behavior compatible with a nagios plugin::
$ pytest -qq --nagios --tb line test_ok.py; echo $?
TESTINFRA OK - 2 passed, 0 failed, 0 skipped in 2.30 seconds
..
0
$ pytest -qq --nagios --tb line test_fail.py; echo $?
TESTINFRA CRITICAL - 1 passed, 1 failed, 0 skipped in 2.24 seconds
.F
/usr/lib/python3/dist-packages/example/example.py:95: error: [Errno 111] error msg
2
You can run these tests from the nagios master or in the target host with
`NRPE <https://en.wikipedia.org/wiki/Nagios#Nagios_Remote_Plugin_Executor>`_.
Integration with KitchenCI
~~~~~~~~~~~~~~~~~~~~~~~~~~
KitchenCI (aka Test Kitchen) can use testinfra via its :code:`shell` verifier.
Add the following to your :code:`.kitchen.yml`, this requires installing `paramiko`
additionally (on your host machine, not in the VM handled by kitchen) ::
verifier:
name: shell
command: pytest --hosts="paramiko://${KITCHEN_USERNAME}@${KITCHEN_HOSTNAME}:${KITCHEN_PORT}?ssh_identity_file=${KITCHEN_SSH_KEY}" --junit-xml "junit-${KITCHEN_INSTANCE}.xml" "test/integration/${KITCHEN_SUITE}"
.. _test docker images:
Test Docker images
~~~~~~~~~~~~~~~~~~
Docker is a handy way to test your infrastructure code. This recipe shows how to
build and run Docker containers with Testinfra by overloading the `host`
fixture.
.. code-block:: python
import pytest
import subprocess
import testinfra
# scope='session' uses the same container for all the tests;
# scope='function' uses a new container per test function.
@pytest.fixture(scope='session')
def host(request):
# build local ./Dockerfile
subprocess.check_call(['docker', 'build', '-t', 'myimage', '.'])
# run a container
docker_id = subprocess.check_output(
['docker', 'run', '-d', 'myimage']).decode().strip()
# return a testinfra connection to the container
yield testinfra.get_host("docker://" + docker_id)
# at the end of the test suite, destroy the container
subprocess.check_call(['docker', 'rm', '-f', docker_id])
def test_myimage(host):
# 'host' now binds to the container
assert host.check_output('myapp -v') == 'Myapp 1.0'
|