index.rst 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. .. _salt-test-suite:
  2. =================
  3. Salt's Test Suite
  4. =================
  5. Salt comes with a powerful integration and unit test suite allowing for
  6. the fully automated run of integration and/or unit tests from a single
  7. interface. It uses the combination of pytest, nox and `Kitchen Salt`_ to
  8. run these tests. Nox is used to manage all of the test python dependencies.
  9. When you run the test runner with nox, you will be installing the same
  10. python dependencies that we use to run our test suite on PRs and branch tests.
  11. `Kitchen Salt`_ is used to spin up our virtual machines based off of golden
  12. images. These virtual machines use the `salt-jenkins`_ sls states to configure
  13. any system dependencies.
  14. To learn the basics of how Salt's test suite works, be sure to check
  15. out the :ref:`Salt's Test Suite: An Introduction <tutorial-salt-testing>`
  16. tutorial.
  17. Nox
  18. ===
  19. Nox is used to manage all of the python dependencies used in the test suite
  20. and spins up the different nox sessions. You can look at the ``noxfile.py``
  21. in the salt repo to view all of the current nox configurations. In that file
  22. you will notice various nox sessions. When creating each of these sessions,
  23. nox will create a virtualenv with the specified interpreter. Once the virtualenv
  24. is created it will also install all of the required python dependencies
  25. required for that session and run the tests.
  26. For example if you want to run all of the tests using the zeromq transport on
  27. python3 you would need to specify the zeromq transport and python3.
  28. .. code-block:: bash
  29. nox -e 'pytest-zeromq-3(coverage=False)'
  30. To run all the tests but on the tcp transport, you would need to specify the tcp session.
  31. .. code-block:: bash
  32. nox -e 'pytest-tcp-3(coverage=False)'
  33. You can view all available sessions by running:
  34. .. code-block:: bash
  35. nox --list-sessions
  36. For the most part you will only need nox to run the test suite, as this tool
  37. will install the exact same python dependencies we use to run on our test runs.
  38. The exception to this is when a system dependency is required, for example ``mysql``.
  39. These system dependencies are installed with sls states managed in the `salt-jenkins`_
  40. repo or you can manually install the dependency yourself.
  41. System Dependencies
  42. ===================
  43. The system dependencies are installed from the `salt-jenkins`_ repo. The
  44. ``golden-images-provision`` state is what is run to determine what dependencies
  45. to install on which platform.
  46. We run this state only when we want to update our current VM images with new
  47. dependencies.
  48. Kitchen Salt
  49. ============
  50. We also use `Kitchen Salt`_ to spin up the VM's used for testing. You can view the
  51. kitchen-salt `getting started`_ for instructions on how to install and set it up.
  52. `Kitchen Salt`_ uses Test Kitchen to spin up the VM or container in the configured
  53. provider. Once the VM is spun up, `Kitchen Salt`_ can install salt and run a particular
  54. set of states. In the case of our branch and PR tests we create "Golden Images" which
  55. run the `salt-jenkins`_ states and install salt system dependencies beforehand. We only
  56. update these "Golden Images" when we need to upgrade or install a system dependency. You can
  57. view the `kitchen-salt jenkins setup`_ docs for instructions on how to set up `Kitchen Salt`_
  58. similar to the jenkins environment we use to run branch and PR tests.
  59. Test Directory Structure
  60. ========================
  61. Salt's test suite is located in the ``tests/`` directory in the root of
  62. Salt's codebase.
  63. With the migration to PyTest, Salt has created a separate directory for tests
  64. that are written taking advantage of the full pottential of PyTest. These are
  65. located under ``tests/pytests``.
  66. As for the old test suite, it is divided into two main groups:
  67. * :ref:`Integration Tests <integration-tests>`
  68. * :ref:`Unit Tests <unit-tests>`
  69. Within each of these groups, the directory structure roughly mirrors the
  70. structure of Salt's own codebase. Notice that there are directories for
  71. ``states``, ``modules``, ``runners``, ``output``, and more in each testing
  72. group.
  73. The files that are housed in the ``modules`` directory of either the unit
  74. or the integration testing factions contain respective integration or unit
  75. test files for Salt execution modules.
  76. The PyTest only tests under ``tests/pytests`` should, more or less, follow the
  77. same grouping as the old test suite.
  78. Integration Tests
  79. -----------------
  80. The Integration section of Salt's test suite start up a number of Salt
  81. daemons to test functionality in a live environment. These daemons
  82. include two Salt Masters, one Syndic, and two Minions. This allows the
  83. Syndic interface to be tested and Master/Minion communication to be
  84. verified. All of the integration tests are executed as live Salt commands
  85. sent through the started daemons.
  86. Integration tests are particularly good at testing modules, states, and
  87. shell commands, among other segments of Salt's ecosystem. By utilizing
  88. the integration test daemons, integration tests are easy to write. They
  89. are also SaltStack's generally preferred method of adding new tests.
  90. The discussion in the :ref:`Integration vs. Unit <integration-vs-unit>`
  91. section of the :ref:`testing tutorial <tutorial-salt-testing>` is
  92. beneficial in learning why you might want to write integration tests
  93. vs. unit tests. Both testing arenas add value to Salt's test suite and
  94. you should consider adding both types of tests if possible and appropriate
  95. when contributing to Salt.
  96. * :ref:`Integration Test Documentation <integration-tests>`
  97. Unit Tests
  98. ----------
  99. Unit tests do not spin up any Salt daemons, but instead find their value
  100. in testing singular implementations of individual functions. Instead of
  101. testing against specific interactions, unit tests should be used to test
  102. a function's logic as well as any ``return`` or ``raises`` statements.
  103. Unit tests also rely heavily on mocking external resources.
  104. The discussion in the :ref:`Integration vs. Unit <integration-vs-unit>`
  105. section of the :ref:`testing tutorial <tutorial-salt-testing>` is useful
  106. in determining when you should consider writing unit tests instead of,
  107. or in addition to, integration tests when contributing to Salt.
  108. * :ref:`Unit Test Documentation <unit-tests>`
  109. .. _running-the-tests:
  110. Running The Tests
  111. =================
  112. There is only one requirement to install, to quickly get started
  113. running salt's test suite: ``nox``.
  114. .. code-block:: bash
  115. pip install nox
  116. Once this requirement is installed, you can use the ``nox`` binary to run
  117. all of the tests included in Salt's test suite:
  118. .. code-block:: bash
  119. nox -e 'pytest-zeromq-3(coverage=False)'
  120. For more information about options you can pass the test runner, see the
  121. ``--help`` option:
  122. .. code-block:: bash
  123. nox -e 'pytest-zeromq-3(coverage=False)' -- --help
  124. .. _running-test-subsections:
  125. Running Test Subsections
  126. ------------------------
  127. Instead of running the entire test suite all at once, which can take a long time,
  128. there are several ways to run only specific groups of tests or individual tests:
  129. * Run :ref:`unit tests only<running-unit-tests-no-daemons>`: ``nox -e 'pytest-zeromq-3(coverage=False)' -- tests/unit/``
  130. * Run unit and integration tests for states: ``nox -e 'pytest-zeromq-3(coverage=False)' -- tests/unit/states/ tests/integration/states/``
  131. * Run integration tests for an individual module: ``nox -e 'pytest-zeromq-3(coverage=False)' -- tests/integration/modules/test_virt.py``
  132. * Run unit tests for an individual module: ``nox -e 'pytest-zeromq-3(coverage=False)' -- tests/unit/modules/test_virt.py``
  133. * Run an individual test by using the class and test name (this example is for the
  134. ``test_default_kvm_profile`` test in the ``tests/integration/module/test_virt.py``):
  135. ``nox -e 'pytest-zeromq-3(coverage=False)' -- tests/integration/modules/test_virt.py::VirtTest::test_default_kvm_profile``
  136. For more specific examples of how to run various test subsections or individual
  137. tests, please see the `pytest`_ documentation on how to run specific tests or
  138. the :ref:`Running Specific Tests <running-specific-tests>`
  139. section of the :ref:`Salt's Test Suite: An Introduction <tutorial-salt-testing>`
  140. tutorial.
  141. .. _running-unit-tests-no-daemons:
  142. Running Unit Tests Without Integration Test Daemons
  143. ---------------------------------------------------
  144. Since the unit tests do not require a master or minion to execute, it is often useful to be able to
  145. run unit tests individually, or as a whole group, without having to start up the integration testing
  146. daemons. Starting up the master, minion, and syndic daemons takes a lot of time before the tests can
  147. even start running and is unnecessary to run unit tests. To run unit tests without invoking the
  148. integration test daemons, simply add the unit directory as an argument:
  149. .. code-block:: bash
  150. nox -e 'pytest-zeromq-3(coverage=False)' -- tests/unit/
  151. All of the other options to run individual tests, entire classes of tests, or
  152. entire test modules still apply.
  153. Running Destructive Integration Tests
  154. -------------------------------------
  155. Salt is used to change the settings and behavior of systems. In order to
  156. effectively test Salt's functionality, some integration tests are written to
  157. make actual changes to the underlying system. These tests are referred to as
  158. "destructive tests". Some examples of destructive tests are changes may be
  159. testing the addition of a user or installing packages. By default,
  160. destructive tests are disabled and will be skipped.
  161. Generally, destructive tests should clean up after themselves by attempting to
  162. restore the system to its original state. For instance, if a new user is created
  163. during a test, the user should be deleted after the related test(s) have
  164. completed. However, no guarantees are made that test clean-up will complete
  165. successfully. Therefore, running destructive tests should be done with caution.
  166. .. note::
  167. Running destructive tests will change the underlying system.
  168. Use caution when running destructive tests.
  169. To run tests marked as destructive, set the ``--run-destructive`` flag:
  170. .. code-block:: bash
  171. nox -e 'pytest-zeromq-3(coverage=False)' -- --run-destructive
  172. Running Cloud Provider Tests
  173. ----------------------------
  174. Salt's testing suite also includes integration tests to assess the successful
  175. creation and deletion of cloud instances using :ref:`Salt-Cloud<salt-cloud>` for
  176. providers supported by Salt-Cloud.
  177. The cloud provider tests are off by default and run on sample configuration files
  178. provided in ``tests/integration/files/conf/cloud.providers.d/``. In order to run
  179. the cloud provider tests, valid credentials, which differ per provider, must be
  180. supplied. Each credential item that must be supplied is indicated by an empty
  181. string value and should be edited by the user before running the tests. For
  182. example, DigitalOcean requires a client key and an api key to operate. Therefore,
  183. the default cloud provider configuration file for DigitalOcean looks like this:
  184. .. code-block:: yaml
  185. digitalocean-config:
  186. driver: digitalocean
  187. client_key: ''
  188. api_key: ''
  189. location: New York 1
  190. As indicated by the empty string values, the ``client_key`` and the ``api_key``
  191. must be provided:
  192. .. code-block:: yaml
  193. digitalocean-config:
  194. driver: digitalocean
  195. client_key: wFGEwgregeqw3435gDger
  196. api_key: GDE43t43REGTrkilg43934t34qT43t4dgegerGEgg
  197. location: New York 1
  198. .. note::
  199. When providing credential information in cloud provider configuration files,
  200. do not include the single quotes.
  201. Once all of the valid credentials for the cloud provider have been supplied, the
  202. cloud provider tests can be run by setting the ``--cloud-provider-tests`` flag:
  203. .. code-block:: bash
  204. nox -e 'pytest-cloud-3(coverage=False)'
  205. Automated Test Runs
  206. ===================
  207. SaltStack maintains a Jenkins server to allow for the execution of tests
  208. across supported platforms. The tests executed from Salt's Jenkins server
  209. create fresh virtual machines for each test run, then execute destructive
  210. tests on the new, clean virtual machine.
  211. SaltStack's Jenkins server continuously runs the entire test suite,
  212. including destructive tests, on an array of various supported operating
  213. systems throughout the day. Each actively supported branch of Salt's
  214. repository runs the tests located in the respective branch's code. Each set
  215. of branch tests also includes a pylint run. These branch tests help ensure
  216. the viability of Salt code at any given point in time as pull requests
  217. are merged into branches throughout the day.
  218. In addition to branch tests, SaltStack's Jenkins server also runs tests
  219. on pull requests. These pull request tests include a smaller set of
  220. virtual machines that run on the branch tests. The pull request tests,
  221. like the branch tests, include a pylint test as well.
  222. When a pull request is submitted to Salt's repository on GitHub, the suite
  223. of pull request tests are started by Jenkins. These tests are used to
  224. gauge the pull request's viability to merge into Salt's codebase. If these
  225. initial tests pass, the pull request can then merged into the Salt branch
  226. by one of Salt's core developers, pending their discretion. If the initial
  227. tests fail, core developers may request changes to the pull request. If the
  228. failure is unrelated to the changes in question, core developers may merge
  229. the pull request despite the initial failure.
  230. As soon as the pull request is merged, the changes will be added to the
  231. next branch test run on Jenkins.
  232. For a full list of currently running test environments, go to
  233. https://jenkinsci.saltstack.com.
  234. Using Salt-Cloud on Jenkins
  235. ---------------------------
  236. For testing Salt on Jenkins, SaltStack uses :ref:`Salt-Cloud<salt-cloud>` to
  237. spin up virtual machines. The script using Salt-Cloud to accomplish this is
  238. open source and can be found here: :blob:`tests/jenkins.py`
  239. Writing Tests
  240. =============
  241. The salt testing infrastructure is divided into two classes of tests,
  242. integration tests and unit tests. These terms may be defined differently in
  243. other contexts, but for Salt they are defined this way:
  244. - Unit Test: Tests which validate isolated code blocks and do not require
  245. external interfaces such as ``salt-call`` or any of the salt daemons.
  246. - Integration Test: Tests which validate externally accessible features.
  247. Salt testing uses unittest2 from the python standard library and MagicMock.
  248. * :ref:`Writing integration tests <integration-tests>`
  249. * :ref:`Writing unit tests <unit-tests>`
  250. Naming Conventions
  251. ------------------
  252. Any function in either integration test files or unit test files that is doing
  253. the actual testing, such as functions containing assertions, must start with
  254. ``test_``:
  255. .. code-block:: python
  256. def test_user_present(self):
  257. ...
  258. When functions in test files are not prepended with ``test_``, the function
  259. acts as a normal, helper function and is not run as a test by the test suite.
  260. Submitting New Tests
  261. --------------------
  262. Which branch of the Salt codebase should new tests be written against? The location
  263. of where new tests should be submitted depends largely on the reason you're writing
  264. the tests.
  265. Tests for New Features
  266. ~~~~~~~~~~~~~~~~~~~~~~
  267. If you are adding new functionality to Salt, please write the tests for this new
  268. feature in the same pull request as the new feature. New features should always be
  269. submitted to the ``|repo_primary_branch|`` branch.
  270. If you have already submitted the new feature, but did not write tests in the original
  271. pull request that has already been merged, please feel free to submit a new pull
  272. request containing tests. If the feature was recently added to Salt's ``|repo_primary_branch|``
  273. branch, then the tests should be added there as well. However, if the feature was
  274. added to ``|repo_primary_branch|`` some time ago and is already present in one or more release
  275. branches, please refer to the `Tests for Entire Files or Functions`_ section below
  276. for more details about where to submit tests for functions or files that do not
  277. already have tests.
  278. Tests to Accompany a Bugfix
  279. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  280. If you are writing tests for code that fixes a bug in Salt, please write the test
  281. in the same pull request as the bugfix. If you're unsure of where to submit your
  282. bugfix and accompanying test, please review the
  283. :ref:`Which Salt Branch? <which-salt-branch>` documentation in Salt's
  284. :ref:`Contributing <contributing>` guide.
  285. Tests for Entire Files or Functions
  286. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  287. Sometimes entire files in Salt are completely untested. If you are writing tests for
  288. a file that doesn't have any tests written for it, write your test against the
  289. earliest supported release branch that contains the file or function you're testing.
  290. Once your tests are submitted in a pull request and is merged into the branch in
  291. question, the tests you wrote will be merged-forward by SaltStack core engineers and
  292. the new tests will propagate to the newer release branches. That way the tests you
  293. wrote will apply to all current and relevant release branches, and not just the ``|repo_primary_branch|``
  294. branch, for example. This methodology will help protect against regressions on older
  295. files in Salt's codebase.
  296. There may be times when the tests you write against an older branch fail in the
  297. merge-forward process because functionality has changed in newer release branches.
  298. In these cases, a Salt core developer may reach out to you for advice on the tests in
  299. question if the path forward is unclear.
  300. .. note::
  301. If tests are written against a file in an older release branch and then merged forward,
  302. there may be new functionality in the file that is present in the new release branch
  303. that is untested.It would be wise to see if new functionality could use additional
  304. testing once the test file has propagated to newer release branches.
  305. Test Helpers
  306. ------------
  307. Several Salt-specific helpers are available. A full list is available by inspecting
  308. functions exported in `tests.support.helpers`.
  309. `@expensiveTest` -- Designates a test which typically requires a relatively costly
  310. external resource, like a cloud virtual machine. This decorator is not normally
  311. used by developers outside of the Salt core team.
  312. `@destructiveTest` -- Marks a test as potentially destructive. It will not be run
  313. by the test runner unless the ``-run-destructive`` test is expressly passed.
  314. `@requires_network` -- Requires a network connection for the test to operate
  315. successfully. If a network connection is not detected, the test will not run.
  316. `@requires_salt_modules` -- Requires all the modules in a list of modules in
  317. order for the test to be executed. Otherwise, the test is skipped.
  318. `@requires_system_grains` -- Loads and passes the grains on the system as an
  319. keyword argument to the test function with the name `grains`.
  320. `@skip_if_binaries_missing(['list', 'of', 'binaries'])` -- If called from inside a test,
  321. the test will be skipped if the binaries are not all present on the system.
  322. `@skip_if_not_root` -- If the test is not executed as root, it will be skipped.
  323. `@with_system_user` -- Creates and optionally destroys a system user within a test case.
  324. See implementation details in `tests.support.helpers` for details.
  325. `@with_system_group` -- Creates and optionally destroys a system group within a test case.
  326. See implementation details in `tests.support.helpers` for details.
  327. `@with_system_user_and_group` -- Creates and optionally destroys a system user and group
  328. within a test case. See implementation details in `tests.support.helpers` for details.
  329. .. _kitchen-salt jenkins setup: https://kitchen.saltstack.com/docs/file/docs/jenkins.md
  330. .. _getting started: https://kitchen.saltstack.com/docs/file/docs/gettingstarted.md
  331. .. _salt-jenkins: https://github.com/saltstack/salt-jenkins
  332. .. _Kitchen Salt: https://kitchen.saltstack.com/
  333. .. _pytest: https://docs.pytest.org/en/latest/usage.html#specifying-tests-selecting-tests