Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .docker/run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
#
# Run test in docker QGIS image
#

set -e

cd /src

VENV=/src/.docker-venv-$QGIS_VERSION

python3 -m venv $VENV --system-site-package

echo "Installing requirements..."
$VENV/bin/pip install -q --no-cache -r REQUIREMENTS_TESTING.txt

cd tests && $VENV/bin/python -m pytest -v


37 changes: 16 additions & 21 deletions .github/workflows/test_plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,26 @@ jobs:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
docker_tags: [release-3_28, latest]

qgis_version: [
"3.34",
"3.40",
]
steps:

- name: Checkout
uses: actions/checkout@v2

- name: Docker pull and create qgis-testing-environment
run: |
docker pull "$DOCKER_IMAGE":${{ matrix.docker_tags }}
docker run -d --name qgis-testing-environment -v "$GITHUB_WORKSPACE":/tests_directory -e DISPLAY=:99 "$DOCKER_IMAGE":${{ matrix.docker_tags }}

- name: Docker set up QGIS
run: |
docker exec qgis-testing-environment sh -c "qgis_setup.sh $PLUGIN_NAME"
docker exec qgis-testing-environment sh -c "rm -f /root/.local/share/QGIS/QGIS3/profiles/default/python/plugins/$PLUGIN_NAME"
docker exec qgis-testing-environment sh -c "ln -s /tests_directory/$PLUGIN_NAME /root/.local/share/QGIS/QGIS3/profiles/default/python/plugins/$PLUGIN_NAME"
docker exec qgis-testing-environment sh -c "pip3 install -r /tests_directory/REQUIREMENTS_TESTING.txt"
docker exec qgis-testing-environment sh -c "apt-get update"
docker exec qgis-testing-environment sh -c "apt-get install -y python3-pyqt5.qtwebkit"

- name: Docker run plugin tests
run: |
docker exec qgis-testing-environment sh -c "qgis_testrunner.sh $TESTS_RUN_FUNCTION"
uses: actions/checkout@v5

- name: Running tests
run: >-
docker run --quiet --rm --name qgis-DataPlotly-tests
--network host
--user $(id -u):$(id -g)
--mount type=bind,source=$GITHUB_WORKSPACE,target=/src
--workdir /src
--env QGIS_VERSION=${{ matrix.qgis_version }}
$DOCKER_IMAGE:${{ matrix.qgis_version }} .docker/run-tests.sh

Check-code-quality:
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion REQUIREMENTS_TESTING.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# For tests execution:
pytest
deepdiff
mock
flake8
pep257
plotly
pylint
pandas
pandas
File renamed without changes.
100 changes: 100 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import logging
import os
import sys

from pathlib import Path

import pytest

from qgis.core import Qgis, QgsApplication
from qgis.PyQt import Qt
from qgis.testing import start_app

# with warnings.catch_warnings():
# warnings.filterwarnings("ignore", category=DeprecationWarning)
# from osgeo import gdal


def pytest_report_header(config):
from osgeo import gdal

message = (
f"QGIS : {Qgis.QGIS_VERSION_INT}\n"
f"Python GDAL : {gdal.VersionInfo('VERSION_NUM')}\n"
f"Python : {sys.version}\n"
f"QT : {Qt.QT_VERSION_STR}"
)
return message


#
# Fixtures
#


@pytest.fixture(scope="session")
def rootdir(request: pytest.FixtureRequest) -> Path:
return Path(request.config.rootdir.strpath)


@pytest.fixture(scope="session")
def data(rootdir: Path) -> Path:
return rootdir.joinpath("data")


#
# Session
#


# Path the 'qgis.utils.iface' property
# Which is not initialized when QGIS app
# is initialized from testing module
def _patch_iface():
import qgis.utils

from qgis.testing.mocked import get_iface

qgis.utils.iface = get_iface()


def pytest_sessionstart(session):
"""Start qgis application"""
os.environ["QT_QPA_PLATFORM"] = "offscreen"

sys.path.append("/usr/share/qgis/python")

# NOTE: we need to prevent cleanup in this case
# because failing tests leads to a segfault.
start_app(cleanup=False)
install_logger_hook(verbose=True)

# XXX The mock does not work here

# Patch 'iface' in qgis.utils
#_patch_iface()


#
# Logger hook
#


def install_logger_hook(verbose: bool = False) -> None:
"""Install message log hook"""
from qgis.core import Qgis

# Add a hook to qgis message log
def writelogmessage(message, tag, level):
arg = f"{tag}: {message}"
if level == Qgis.MessageLevel.Warning:
logging.warning(arg)
elif level == Qgis.MessageLevel.Critical:
logging.error(arg)
elif verbose:
# Qgis is somehow very noisy
# log only if verbose is set
logging.info(arg)

messageLog = QgsApplication.messageLog()
messageLog.messageReceived.connect(writelogmessage)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
from DataPlotly.gui.plot_settings_widget import DataPlotlyPanelWidget
from DataPlotly.layouts.plot_layout_item import PlotLayoutItem
from DataPlotly.layouts.plot_layout_item import PlotLayoutItemMetadata
from DataPlotly.test.utilities import get_qgis_app

from .utilities import get_qgis_app

QGIS_APP, CANVAS, IFACE, PARENT = get_qgis_app()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
from qgis.PyQt.QtXml import QDomDocument

from DataPlotly.core.core_utils import restore, restore_safe_str_xml, safe_str_xml
from DataPlotly.test.utilities import get_qgis_app
from DataPlotly.gui.dock import (DataPlotlyDock, DataPlotlyDockManager)
from DataPlotly.gui.add_new_dock_dlg import DataPlotlyNewDockIdValidator

from .utilities import get_qgis_app

QGIS_APP, CANVAS, IFACE, PARENT = get_qgis_app()


Expand Down
File renamed without changes.
12 changes: 9 additions & 3 deletions DataPlotly/test/test_init.py → tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import logging
import configparser

from importlib import resources

LOGGER = logging.getLogger('QGIS')


Expand Down Expand Up @@ -41,9 +43,13 @@ def test_read_init(self):
'email',
'author']

file_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), os.pardir,
'metadata.txt'))
#file_path = os.path.abspath(os.path.join(
# os.path.dirname(__file__), os.pardir,
# 'metadata.txt'))

file_path = resources.files("DataPlotly").joinpath("metadata.txt")
assert file_path.exists()

LOGGER.info(file_path)
metadata = []
parser = configparser.ConfigParser()
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os
import json

import processing
from qgis import processing

from qgis.core import QgsApplication, QgsVectorLayer
from qgis.testing import unittest
Expand Down
File renamed without changes.
41 changes: 22 additions & 19 deletions DataPlotly/test/utilities.py → tests/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ def get_qgis_app(cleanup=True):

# Note: QGIS_PREFIX_PATH is evaluated in QgsApplication -
# no need to mess with it here.
QGISAPP = QgsApplication(argvb, myGuiFlag)
#QGISAPP = QgsApplication(argvb, myGuiFlag)

QGISAPP.initQgis()
s = QGISAPP.showSettings()
LOGGER.debug(s)
#QGISAPP.initQgis()
#s = QGISAPP.showSettings()
#LOGGER.debug(s)

def debug_log_message(message, tag, level):
"""
Expand All @@ -69,23 +69,26 @@ def debug_log_message(message, tag, level):
"""
print(f'{tag}({level}): {message}')

QgsApplication.instance().messageLog().messageReceived.connect(
debug_log_message)

if cleanup:
@atexit.register
def exitQgis(): # pylint: disable=unused-variable
"""
Gracefully closes the QgsApplication instance
"""
try:
QGISAPP.exitQgis() # pylint: disable=used-before-assignment
QGISAPP = None # pylint: disable=redefined-outer-name
except NameError:
pass
QGISAPP = QgsApplication.instance()

#QgsApplication.instance().messageLog().messageReceived.connect(
# debug_log_message)

# XXX Don't cleanup twice
#if cleanup:
# @atexit.register
# def exitQgis(): # pylint: disable=unused-variable
# """
# Gracefully closes the QgsApplication instance
# """
# try:
# QGISAPP.exitQgis() # pylint: disable=used-before-assignment
# QGISAPP = None # pylint: disable=redefined-outer-name
# except NameError:
# pass

if PARENT is None:
# noinspection PyPep8Naming
# # noinspection PyPep8Naming
PARENT = QWidget()

if CANVAS is None:
Expand Down
Loading