Skip to main content

pytest-qgis

PyPI version Downloads CI Code on Github Ruff pre-commit codecov.io

A pytest plugin for testing QGIS python plugins.

Features

This plugin makes it easier to write QGIS plugin tests with the help of some fixtures and hooks:

Fixtures

  • qgis_app returns and eventually exits fully configured QgsApplication. This fixture is called automatically on the start of pytest session.
  • qgis_bot returns a QgisBot, which holds common utility methods for interacting with QGIS.
  • qgis_canvas returns QgsMapCanvas.
  • qgis_parent returns the QWidget used as parent of the qgis_canvas
  • qgis_iface returns stubbed QgisInterface. All the methods that are not implemented return a MagicMock that can be used for testing the calls.
  • qgis_new_project makes sure that all the map layers and configurations are removed. This should be used with tests that add stuff to QgsProject. Fixture returns the QgsProject instance.
  • qgis_processing initializes the processing framework. This can be used when testing code that calls processing.run(...).
  • qgis_version returns QGIS version number as integer.
  • qgis_world_map_geopackage returns Path to the world_map.gpkg that ships with QGIS
  • qgis_countries_layer returns Natural Earth countries layer from world_map.gpkg as QgsVectorLayer

Markers

  • qgis_show_map lets developer inspect the QGIS map visually during the test and also at the teardown of the test. Full signature of the marker is:

    @pytest.mark.qgis_show_map(timeout: int = 30, add_basemap: bool = False, zoom_to_common_extent: bool = True, extent: QgsRectangle = None)
    
    • timeout is the time in seconds until the map is closed. If timeout is zero, the map will be closed in teardown.
    • add_basemap when set to True, adds Natural Earth countries layer as the basemap for the map.
    • zoom_to_common_extent when set to True, centers the map around all layers in the project.
    • extent is alternative to zoom_to_common_extent and lets user specify the extent as QgsRectangle

Check the marker api documentation and examples for the ways markers can be used.

Hooks

  • pytest_load_initial_conftests hook is used to initialize and configure QgsApplication. It is also used to patch qgis.utils.iface with qgis_iface automatically. Since this happens before any conftest file is imported, also the conftest files can import modules that import qgis.utils.iface.

  • pytest_runtest_teardown hook is used to ensure that all layer fixtures of any scope are cleaned properly without causing segmentation faults. The layer fixtures that are cleaned automatically must have some of the following keywords in their name: "layer", "lyr", "raster", "rast", "tif".

Utility tools

  • wait and wait_until functions in pytest_qgis.utils can be used to wait certain time or until a condition is met. wait runs a real event loop for the given milliseconds. If you use pytest-qt, its qtbot.wait, qtbot.waitUntil and qtbot.waitSignal offer similar functionality.

  • clean_qgis_layer decorator found in pytest_qgis.utils can be used with QgsMapLayer fixtures to ensure that they are cleaned properly if they are used but not added to the QgsProject. This is only needed with layers with other than memory provider.

    This decorator works only with fixtures that return QgsMapLayer instances. There is no support for fixtures that use yield.

    This decorator is an alternative way of cleaning the layers, since pytest_runtest_teardown hook cleans layer fixtures automatically by the keyword.

    # conftest.py or start of a test file
    import pytest
    from pytest_qgis.utils import clean_qgis_layer
    from qgis.core import QgsVectorLayer
    
    
    @pytest.fixture()
    @clean_qgis_layer
    def geojson() -> QgsVectorLayer:
        return QgsVectorLayer("layer_file.geojson", "some layer")
    
    
    # This will be cleaned automatically since it contains the keyword "layer" in its name
    @pytest.fixture()
    def geojson_layer() -> QgsVectorLayer:
        return QgsVectorLayer("layer_file2.geojson", "some layer")
    

Command line options

  • --qgis_disable_gui can be used to disable graphical user interface in tests. This speeds up the tests that use Qt widgets of the plugin.
  • --qgis_disable_init can be used to prevent QGIS (QgsApplication) from initializing. Mainly used in internal testing.
  • --qgis_disable_exit can be used to prevent QGIS (QgsApplication) from exiting in teardown. This might be useful if C++ errors occur.

ini-options

  • qgis_gui_enabled whether the QUI will be visible or not. Defaults to True. Command line option --qgis_disable_gui will override this.
  • qgis_canvas_width width of the QGIS canvas in pixels. Defaults to 600.
  • qgis_canvas_height height of the QGIS canvas in pixels. Defaults to 600.
  • qgis_server support qgis server only plugin testing. This prevent initializing qgis interface and allow instantiating QgsServer() safely.
  • qgis_disable_exit whether to disable QGIS (QgsApplication) from exiting in teardown. This might be useful if C++ errors occur.

Custom QGIS settings

When running tests, a directory named .qgis-settings will be created containings all QGIS default profile as well as QGIS settings. Most of the time you can ignore this directory, but it may be useful for inspecting created default settings.

You may define custom settings to be loaded at startup: in your root tests directory, create a file qgis_settings.ini containing all your default QGIS3 settings: this file will be used as the default settings for the QGIS tests session.

Event loop and threads

Queued and cross-thread signal deliveries require the receiving thread to process its event queue. pytest-qgis handles this automatically:

  • QgsApplication is initialized for every test process, including every pytest-xdist worker.
  • Queued events and deferred deletions (deleteLater) are flushed after each test.
  • wait in pytest_qgis.utils runs a real event loop for the given milliseconds.

Signals between objects living in a QThread require the thread to run an event loop. QThread's default run() implementation provides one.

Note: Decorate slots with @pyqtSlot() (or connect only after moveToThread), otherwise PyQt may run the slot in the thread where the connection was made.

pytest-xdist

Tests can be run in parallel with pytest-xdist (pytest -n auto) without configuration: each worker gets its own QgsApplication and settings directory (.qgis-settings/<worker_id>).

QgisBot

Class to hold common utility methods for interacting with QGIS. Check test_qgis_bot.py for usage examples. Here are some of the methods:

  • create_feature_with_attribute_dialog method can be used to create a feature with default values using QgsAttributeDialog. This ensures that all the default values are honored and for example boolean fields are either true or false, not null.
  • open_project method clears the current project and opens the given .qgs or .qgz file. The map canvas shows the visible layers of the project in the layer tree order with the extent and CRS saved in the project. The project stays open after the test, so use the qgis_new_project fixture in tests that need an empty project.
  • get_qgs_attribute_dialog_widgets_by_name function can be used to get dictionary of the QgsAttributeDialog widgets. Check the test test_qgis_ui.py::test_attribute_dialog_change for a usage example.

Requirements

This pytest plugin requires QGIS >= 3.34 to work though versions up until pytest-qgis<=2.1.0 should work with QGIS >= 3.16.

Installation

Install with pip:

pip install pytest-qgis

Development

See DEVELOPMENT.md.

Contributing

Contributions are very welcome. Get started by reading OSGeo Suomi CONTRIBUTING guidelines.

License

Distributed under the terms of the GNU GPL v2.0 license, or (at your option) any later version. "pytest-qgis" is free and open source software.

Metadata

Release files for pytest-qgis 5.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-qgis 5.0.1
File Size Uploaded
pytest_qgis-5.0.1.tar.gz 33.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-qgis 5.0.1
File Interpreter ABI Platform
pytest_qgis-5.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 66.6 kB

Release files / pytest_qgis-5.0.1.tar.gz

Download URL pytest_qgis-5.0.1.tar.gz
Size 33.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b09b78f6b2fe26833e38f379b84ccd07ed5e449017e38050c1b4a56a308422f8
BLAKE2b-256 checksum
How to use checksums
b836028a8a03e6cbd60ed2c62b42cf93408fcb3a44e22fa2735ad04e79803412
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pytest_qgis-5.0.1-py3-none-any.whl

Download URL pytest_qgis-5.0.1-py3-none-any.whl
Size 33.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
920ff734d6c12b56ad47ca3c7a4a974498d3c92d09b7b4442c624e5b8c55b4d6
BLAKE2b-256 checksum
How to use checksums
e10226dbd410864257b513863fb66fd295f3119bdbe075e6b06dd162f38e8e64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

5.0.1 This release

2 release files

5.0.0

2 release files

4.1.1

2 release files

4.1.0

2 release files

4.0.1

2 release files

4.0.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.3.5

2 release files

1.3.4

2 release files

1.3.3

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page