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
|
.. _testing:
================
Trove Unit Tests
================
Mock Object Library
-------------------
Trove unit tests make a frequent use of the Python Mock library.
This library lets the caller replace (*"mock"*) parts of the system under test with
mock objects and make assertions about how they have been used. [1]_
The Problem of Dangling Mocks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Often one needs to mock global functions in shared system modules.
The caller must restore the original state of the module
after it is no longer required.
Dangling mock objects in global modules (mocked members of imported
modules that never get restored) have been causing various transient
failures in the unit test suite.
The main issues posed by dangling mock objects include::
- Such object references propagate across the entire test suite. Any
caller may be hit by a non-functional - or worse - crippled module member
because some other (potentially totally unrelated) test case failed to
restore it.
- Dangling mock references shared across different test modules may
lead to unexpected results/behavior in multi-threaded environments. One
example could be a test case failing because a mock got called multiple
times from unrelated modules.
Such issues are likely to exhibit transient random behavior depending
on the runtime environment, making them difficult to debug.
There are several possible strategies available for dealing with dangling
mock objects (see the section on recommended patterns).
Further information is available in [1]_, [2]_, [3]_.
Dangling Mock Detector
~~~~~~~~~~~~~~~~~~~~~~
All Trove unit tests should extend 'trove_testtools.TestCase'.
It is a subclass of 'testtools.TestCase' which automatically checks for
dangling mock objects at each test class teardown.
It marks the tests as failed and reports the leaked reference if it
finds any.
Writing Unit Tests
------------------
Trove has some legacy unit test code for all the components which is not
recommended to follow. Use the suggested approaches below.
Writing Unit Tests for Trove API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For trove-api unit test, we use real database (sqlite).
Set up trove database in ``setUpClass`` method.
.. code-block:: python
from trove.tests.unittests.util import util
@classmethod
def setUpClass(cls):
util.init_db()
and clean up the database in the method ``tearDownClass``:
.. code-block:: python
from trove.tests.unittests.util import util
@classmethod
def tearDownClass(cls):
util.cleanup_db()
Insert some data in ``setUpClass`` in order to run the tests.
Trove sends notifications for various operations which communicates with
the message queue service. In unit test, this is also mocked and usually
called in the ``setUp`` method.
.. code-block:: python
from trove.tests.unittests import trove_testtools
def setUp(self):
trove_testtools.patch_notifier(self)
Look at an example in ``trove/tests/unittests/instance/test_service.py``
Run Unit Test
-------------
Run all the unit tests in one command:
.. code-block:: console
tox -e py39
Run all the tests of a specific test class:
.. code-block:: console
tox -e py39 -- trove.tests.unittests.instance.test_service.TestInstanceController
Run a single test case:
.. code-block:: console
tox -e py39 -- trove.tests.unittests.instance.test_service.TestInstanceController.test_create_multiple_versions
References
----------
.. [1] Mock Guide: https://docs.python.org/3/library/unittest.mock.html
.. [2] Python Mock Gotchas: http://alexmarandon.com/articles/python_mock_gotchas/
.. [3] Mocking Mistakes: http://engineroom.trackmaven.com/blog/mocking-mistakes/
|