1
0

index.rst 20 KB

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