Writing tests for new code is a critical part of keeping napari maintainable as
it grows. Tests are written in files whose names
begin with test_*
and which are contained in one of the _tests
directories.
There are a few things to keep in mind when writing a test where a Qt
event
loop or a napari.Viewer
is required. The important thing is that any widgets
you create during testing are cleaned up at the end of each test:
-
If you simply need a
QApplication
to be running for your test, you can use theqapp
fixture from pytest-qt. Note however, that you are required to perform any and all cleanup of widgets at the end of the test.note: fixtures in pytest can be a little mysterious, since it's not always clear where they are coming from. In this case, using a pytest-qt fixture looks like this:
# just by putting `qapp` in the list of arguments # pytest-qt will start up an event loop for you def test_something(qapp): ...
-
Often however, you will be creating some widgets during testing, and these need to be cleaned up at the end of the test. The
qtbot
fixture frompytest-qt
provides a convenientqtbot.addWidget
method that will ensure that the widget gets closed at the end of the test. It also creates an event loop and provides a whole bunch of other convenient methods for interacting with your GUI tests (clicking, waiting signals, etc...). See the docs linked above for details.# the qtbot fixture starts an event loop and provides # a number of convenience methods def test_something_else(qtbot): widget = QWidget() qtbot.addWidget(widget) # tell qtbot to clean this widget later ...
-
When writing a test that requires a
napari.Viewer
object, there is a convenient fixture available calledviewer_factory
that will take care of creating a viewer and cleaning up at the end of the test. When using this function, it is not necessary to use aqtbot
orqapp
fixture, nor should you do any additional cleanup (such as callingviewer.close()
) at the end of the test. Duplicate cleanup may cause an error. Use the factory as follows:# the viewer_factory fixture is defined in napari/conftest.py def test_something_with_a_viewer(viewer_factory): # viewer factory takes any keyword arguments that napari.Viewer() takes view, viewer = viewer_factory() # note, `view` here is just a pointer to viewer.window.qt_viewer # do stuff with the viewer, no qtbot or viewer.close() methods needed. ...