Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add unit tests #90

Merged
merged 2 commits into from
Sep 30, 2024
Merged
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
77 changes: 77 additions & 0 deletions .github/workflows/tester.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: "🎳 Tester"

on:
push:
branches:
- master
paths:
- '**.py'
- .github/workflows/tester.yml
- requirements/testing.txt

pull_request:
branches:
- master
paths:
- '**.py'
- .github/workflows/tester.yml
- requirements/testing.txt

env:
PROJECT_FOLDER: "menu_from_project"
PYTHON_VERSION: 3.9

jobs:
tests-unit:
runs-on: ubuntu-latest

steps:
- name: Get source code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
python-version: ${{ env.PYTHON_VERSION }}

- name: Install Python requirements
run: |
python -m pip install -U pip setuptools wheel
python -m pip install -U -r requirements/testing.txt

- name: Run Unit tests
run: pytest -p no:qgis tests/unit/

test-qgis:
runs-on: ubuntu-latest

container:
image: qgis/qgis:release-3_28
env:
CI: true
DISPLAY: ":1"
MUTE_LOGS: true
NO_MODALS: 1
PYTHONPATH: "/usr/share/qgis/python/plugins:/usr/share/qgis/python:."
QT_QPA_PLATFORM: "offscreen"
WITH_PYTHON_PEP: false
options: -v /tmp/.X11-unix:/tmp/.X11-unix

steps:
- name: Get source code
uses: actions/checkout@v4

- name: Print QGIS version
run: qgis --version

- name: Install Python requirements
run: |
python3 -m pip install -U pip setuptools wheel
python3 -m pip install -U -r requirements/testing.txt

- name: Run Unit tests
run: |
Xvfb :1 &
python3 -m pytest tests/qgis/
3 changes: 3 additions & 0 deletions requirements/testing.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Testing dependencies
# --------------------
pytest-cov>=4
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ line_length = 88
[tool:pytest]
addopts =
--junitxml=junit/test-results.xml
--cov-config=.coveragerc
--cov-config=setup.cfg
--cov=menu_from_project
--cov-report=xml
--cov-report=html
Expand Down
Empty file added tests/__init__.py
Empty file.
File renamed without changes.
Empty file added tests/qgis/__init__.py
Empty file.
119 changes: 119 additions & 0 deletions tests/qgis/test_project_read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
Usage from the repo root folder:

.. code-block:: bash

# for whole tests
python -m unittest tests.qgis.test_project_read
# for specific test
python -m unittest tests.qgis.test_project_read.TestProjectMenuConfig.test_get_project_menu_config
"""

# standard library

# PyQGIS
from qgis.testing import unittest
from qgis.core import QgsMapLayerType, QgsWkbTypes

from pathlib import Path

from menu_from_project.logic.project_read import (
MenuProjectConfig,
MenuGroupConfig,
MenuLayerConfig,
get_project_menu_config,
)
from menu_from_project.logic.qgs_manager import QgsDomManager


# ############################################################################
# ########## Classes #############
# ################################


class TestProjectMenuConfig(unittest.TestCase):
def test_get_project_menu_config(self):
"""Read a sample project and check returned informations"""

qgs_dom_manager = QgsDomManager()

project = {
"file": str(Path(__file__).parent / ".." / "projets" / "aeag-tiny.qgz"),
"name": "test_import",
}

result = get_project_menu_config(
project=project, qgs_dom_manager=qgs_dom_manager
)
# Can't define filename because temp file is used
tmp_filename = result.filename

expected = MenuProjectConfig(
project_name="test_import",
filename=tmp_filename,
uri=project["file"],
root_group=MenuGroupConfig(
name="",
filename=tmp_filename,
childs=[
MenuLayerConfig(
name="Sites de mesure qualit\u00e9 (cours d'eau)",
layer_id="L8150cde67501427eade1e787479c2f70",
filename=tmp_filename,
visible=True,
expanded=True,
embedded=False,
is_spatial=True,
layer_type=QgsMapLayerType.VectorLayer,
metadata_abstract="La couche 'Stations de mesure de la qualit\u00e9 des cours d'eau' localise l'ensemble des stations appartenant \u00e0 des r\u00e9seaux de mesure de la qualit\u00e9 des eaux de surface : r\u00e9seaux nationaux (ie. RNB, RCB, R\u00e9seau Hydrobiologique et Piscicole), mais aussi r\u00e9seaux d\u00e9partementaux et locaux.",
metadata_title="Stations de mesure qualit\u00e9 (cours d'eau)",
layer_notes='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">La couche \'Stations de mesure de la qualit\u00e9 des cours d\'eau\' localise l\'ensemble des stations appartenant \u00e0 des r\u00e9seaux de mesure de la qualit\u00e9 des eaux de surface : r\u00e9seaux nationaux (ie. RNB, RCB, R\u00e9seau Hydrobiologique et Piscicole), mais aussi r\u00e9seaux d\u00e9partementaux et locaux.</p>\n<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src="data:image/20425.JPG;base64,/\n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" width="51" height="45" /></p></body></html>',
abstract="La couche 'Stations de mesure de la qualit\u00e9 des cours d'eau' localise l'ensemble des stations appartenant \u00e0 des r\u00e9seaux de mesure de la qualit\u00e9 des eaux de surface : r\u00e9seaux nationaux (ie. RNB, RCB, R\u00e9seau Hydrobiologique et Piscicole), mais aussi r\u00e9seaux d\u00e9partementaux et locaux.",
title="Stations de mesure qualit\u00e9 (cours d'eau)",
geometry_type=QgsWkbTypes.GeometryType.PointGeometry,
),
MenuLayerConfig(
name="Cours d'eau",
layer_id="L35ecffe715c74f15bec52340aa3c9e3f",
filename=tmp_filename,
visible=True,
expanded=False,
embedded=False,
is_spatial=True,
layer_type=QgsMapLayerType.RasterLayer,
metadata_abstract="BD Carthage est la base de donn\u00e9e qui constitue le r\u00e9f\u00e9rentiel hydrographique fran\u00e7ais. C'est cette base qui d\u00e9crit, codifie et normalise les cours d'eau, les bassins versants, lacs et autres entit\u00e9s hydrographiques de surface en France. Les mises \u00e0 jour sont annuelles, centralis\u00e9es par chaque agence de l'eau, et confi\u00e9es \u00e0 l'IGN pour int\u00e9gration. ",
metadata_title="Cours d'eau (BD Carthage)",
layer_notes="",
abstract="",
title="",
geometry_type=None,
),
MenuLayerConfig(
name="Bassin Hydrographique",
layer_id="Lbd28399787e349488c2f7bb0298b370d",
filename=tmp_filename,
visible=True,
expanded=False,
embedded=False,
is_spatial=True,
layer_type=QgsMapLayerType.RasterLayer,
metadata_abstract="BD Carthage est la base de donn\u00e9e qui constitue le r\u00e9f\u00e9rentiel hydrographique fran\u00e7ais. C'est cette base qui d\u00e9crit, codifie et normalise les cours d'eau, les bassins versants, lacs et autres entit\u00e9s hydrographiques de surface en France. Les mises \u00e0 jour sont annuelles, centralis\u00e9es par chaque agence de l'eau, et confi\u00e9es \u00e0 l'IGN pour int\u00e9gration. ",
metadata_title="Bassin hydrographique (BD Carthage)",
layer_notes="",
abstract="",
title="",
geometry_type=None,
),
],
embedded=False,
),
)

self.assertEqual(result, expected)


# ############################################################################
# ####### Stand-alone run ########
# ################################
if __name__ == "__main__":
unittest.main()
Empty file added tests/unit/__init__.py
Empty file.
85 changes: 85 additions & 0 deletions tests/unit/test_plg_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#! python3 # noqa E265

"""
Usage from the repo root folder:

.. code-block:: bash
# for whole tests
python -m unittest tests.unit.test_plg_metadata
# for specific test
python -m unittest tests.unit.test_plg_metadata.TestPluginMetadata.test_version_semver
"""

# standard library
import unittest
from pathlib import Path

# 3rd party
from packaging.version import parse

# project
from menu_from_project import __about__

# ############################################################################
# ########## Classes #############
# ################################


class TestPluginMetadata(unittest.TestCase):
"""Test about module"""

def test_metadata_types(self):
"""Test types."""
# plugin metadata.txt file
self.assertIsInstance(__about__.PLG_METADATA_FILE, Path)
self.assertTrue(__about__.PLG_METADATA_FILE.is_file())

# plugin dir
self.assertIsInstance(__about__.DIR_PLUGIN_ROOT, Path)
self.assertTrue(__about__.DIR_PLUGIN_ROOT.is_dir())

# metadata as dict
self.assertIsInstance(__about__.__plugin_md__, dict)

# general
self.assertIsInstance(__about__.__author__, str)
self.assertIsInstance(__about__.__copyright__, str)
self.assertIsInstance(__about__.__email__, str)
self.assertIsInstance(__about__.__keywords__, list)
self.assertIsInstance(__about__.__license__, str)
self.assertIsInstance(__about__.__summary__, str)
self.assertIsInstance(__about__.__title__, str)
self.assertIsInstance(__about__.__title_clean__, str)
self.assertIsInstance(__about__.__version__, str)
self.assertIsInstance(__about__.__version_info__, tuple)

# misc
self.assertLessEqual(len(__about__.__title_clean__), len(__about__.__title__))

# QGIS versions
self.assertIsInstance(
__about__.__plugin_md__.get("general").get("qgisminimumversion"), str
)

self.assertIsInstance(
__about__.__plugin_md__.get("general").get("qgismaximumversion"), str
)

min_version_parsed = parse(
__about__.__plugin_md__.get("general").get("qgisminimumversion")
)
max_version_parsed = parse(
__about__.__plugin_md__.get("general").get("qgismaximumversion")
)
self.assertLessEqual(min_version_parsed, max_version_parsed)

def test_version_semver(self):
"""Test if version comply with semantic versioning."""
self.assertTrue(parse(__about__.__version__))


# ############################################################################
# ####### Stand-alone run ########
# ################################
if __name__ == "__main__":
unittest.main()