.. _testing-label: Running and writing tests ========================= Write tests ^^^^^^^^^^^ Every new function that is written in to HyperSpy needs to be tested and documented. Tests are short functions found in hyperspy/tests that call your functions under some known conditions and check the outputs against known values. They should depend on as few other features as possible so that when they break we know exactly what caused it. Ideally, the tests should be written at the same time than the code itself, as they are very convenient to run to check outputs when coding. Writing tests can seem laborious but you'll probably soon find that they're very important as they force you to sanity check all you do. For details on running and writing HyperSpy test see :ref:`dev_tests` HyperSpy uses the `pytest `_ library for testing. The tests reside in the ``hyperspy.tests`` module. First ensure pytest and its plugins are installed by: .. code:: bash # If using a standard hyperspy install pip install hyperspy[test] # Or, from a hyperspy local development directory pip install -e .[test] # Or just installing the dependencies using conda conda install -c conda-forge pytest pytest-mpl To run them: .. code:: bash pytest --mpl --pyargs hyperspy Or, from HyperSpy's project folder simply: .. code:: bash pytest Useful hints on testing: * When comparing integers, it's fine to use ``==``. When comparing floats, be sure to use ``numpy.testing.assert_almost_equal()`` or ``numpy.testing.assert_allclose()``. * ``numpy.testing.assert_equal()`` is convenient to compare numpy arrays. * The ``hyperspy.misc.test_utils.py`` contains a few useful functions for testing. * ``@pytest.mark.parametrize()`` is a very convenient decorator to test several parameters of the same function without having to write to much repetitive code, which is often error-prone. See `pytest documentation for more details `_. * It is good to check that the tests does not use too much of memory after creating new tests. If you need to explicitly delete your objects and free memory, you can do the following to release the memory associated to the ``s`` object, for example: .. code:: python del s gc.collect() * Once, you have pushed your PR to the official HyperSpy repository, it can be useful to check the coverage of your tests using the coveralls.io check of your PR. There should be a link to it at the bottom of your PR on the github PR page. This service can help you to find how well your code is being tested and exactly which part is not currently tested. * `pytest-sugar `_ can be installed to have a nicer look and feel of pytest in the console (encoding issue have been reported in the Windows console). .. _plot-test-label: Plot testing ^^^^^^^^^^^^ Plotting is tested using the ``@pytest.mark.mpl_image_compare`` decorator of the `pytest mpl plugin `_. This decorator uses reference images to compare with the generated output during the tests. The references images are located in the folder defined by the argument ``baseline_dir`` of the ``@pytest.mark.mpl_image_compare`` decorator. To run plotting tests, you simply need to add the option ``--mpl``: :: pytest --mpl If you don't use the ``--mpl``, the code of the tests will be executed but the images will not be compared to the references images. If you need to add or change some plots, follow the workflow below: 1. Write the tests using appropriate decorator such as ``@pytest.mark.mpl_image_compare``. 2. If you need to generate new reference image in the folder ``plot_test_dir``, for example, run: ``pytest --mpl-generate-path=plot_test_dir`` 3. Run again the tests and this time they should pass. 4. Use ``git add`` to put the new file in the git repository. When the plotting tests are failling, it is possible to download the figure comparison images generated by pytest-mpl in the `artifacts tabs `_ of the corresponding build. The plotting tests need matplotlib > 3.0.0, since small changes in the way matplotlib generates the figure can make the tests fail. In travis and appveyor, the matplotlib backend is set to ``agg`` by setting the ``MPLBACKEND`` environment variable to ``agg``. At the first import of ``matplotlib.pyplot``, matplotlib will look at the ``MPLBACKEND`` environment variable and set accordingly the backend. See `pytest-mpl `_ for more details. Exporting pytest results as HTML ^^^^^^^^^^^^ With ``pytest-html`` it is possible to export the results of running pytest for easier viewing. I can be installed by conda: .. code:: bash conda install pytest-html and run by: .. code:: bash pytest --mpl --html=report.html