File: examples.rst

package info (click to toggle)
pytest-testinfra 10.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 676 kB
  • sloc: python: 4,951; makefile: 152; sh: 2
file content (181 lines) | stat: -rw-r--r-- 5,200 bytes parent folder | download
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'