Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bafc6a1
t.rast.mapcalc: migrate additional shell test to pytest
sakirr05 Jan 25, 2026
f8212dc
t.rast.mapcalc: migrate remaining shell tests to pytest
sakirr05 Jan 27, 2026
bf53070
tests(t.rast.mapcalc): replace pytest with grass.gunittest in tempora…
sakirr05 Jan 28, 2026
09ed4f3
tests(t.rast.mapcalc): explicitly remove temporal datasets in tearDow…
sakirr05 Jan 28, 2026
bda705a
t.rast.mapcalc: fix pytest failures and temporal cleanup
sakirr05 Jan 28, 2026
054669c
tests(t.rast.mapcalc): convert tests to pytest and place in correct d…
sakirr05 Jan 29, 2026
ef84825
tests(t.rast.mapcalc): run fixtures in existing GRASS session
sakirr05 Jan 29, 2026
b02d4e1
tests(t.rast.mapcalc): migrate additional shell test to pytest
sakirr05 Jan 29, 2026
00efc55
t.rast.mapcalc: fixtures create own GRASS session
sakirr05 Jan 29, 2026
e2f9cc1
tests(t.rast.mapcalc): remove create_project and use standard pytest …
sakirr05 Jan 31, 2026
239be0c
tests(t.rast.mapcalc): create GRASS project before gs.setup.init
sakirr05 Jan 31, 2026
a83590a
tests(t.rast.mapcalc): use Tools API in pytest fixtures
sakirr05 Jan 31, 2026
5296679
tests(t.rast.mapcalc): use Tools API consistently in tests
sakirr05 Jan 31, 2026
9b4594b
tests(t.rast.mapcalc): simplify t.info reference to dict
sakirr05 Feb 2, 2026
faa5294
Merge branch 'main' into migrate-additional-t-rast-mapcalc-test
echoix Feb 28, 2026
b8028c8
Merge branch 'main' into migrate-additional-t-rast-mapcalc-test
echoix Apr 27, 2026
b9075df
improvements
petrasovaa Apr 29, 2026
b6f8c78
reduce number of maps
petrasovaa Apr 29, 2026
3bdcf7a
Merge branch 'main' into migrate-additional-t-rast-mapcalc-test
sakirr05 May 7, 2026
8db2e75
Merge branch 'OSGeo:main' into migrate-additional-t-rast-mapcalc-test
sakirr05 May 9, 2026
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
58 changes: 0 additions & 58 deletions temporal/t.rast.mapcalc/test.t.rast.mapcalc.operators.sh

This file was deleted.

56 changes: 0 additions & 56 deletions temporal/t.rast.mapcalc/test.t.rast.mapcalc.sh

This file was deleted.

71 changes: 71 additions & 0 deletions temporal/t.rast.mapcalc/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Fixtures for t.rast.mapcalc tests.

(C) 2025 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
"""

import os

import pytest

import grass.script as gs
from grass.tools import Tools


@pytest.fixture(scope="session")
def mapcalc_session(tmp_path_factory):
"""GRASS session with prec_1..prec_3 rasters and precip_abs1/2 STRDS.

Session-scoped: setup (region, rasters, STRDS, TGIS init) runs once for
the whole test run. Tests use overwrite=True for their outputs and
test_failure_on_missing_map restores its rename in a finally block, so
sharing across modules is safe.
"""
tmp_path = tmp_path_factory.mktemp("t_rast_mapcalc")
project = tmp_path / "test"
gs.create_project(project)
with gs.setup.init(project, env=os.environ.copy()) as session:
tools = Tools(session=session, overwrite=True)
tools.g_gisenv(set="TGIS_USE_CURRENT_MAPSET=1")
tools.g_region(s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10)
for name, val in [("prec_1", 550), ("prec_2", 450), ("prec_3", 320)]:
tools.r_mapcalc(expression=f"{name} = rand(0, {val})", seed=1)
for name in ("precip_abs1", "precip_abs2"):
tools.t_create(
type="strds",
temporaltype="absolute",
output=name,
title="A test",
description="A test",
)
tools.t_register(
flags="i",
type="raster",
input="precip_abs1",
maps="prec_1,prec_2,prec_3",
start="2001-01-01",
increment="3 months",
)
tools.t_register(
type="raster",
input="precip_abs2",
maps="prec_1,prec_2,prec_3",
)
yield session


@pytest.fixture
def assert_tinfo():
"""Return a helper that checks t.info -g output against expected key/value pairs."""

def _assert(tools, strds_name, expected):
actual = tools.t_info(type="strds", input=strds_name, flags="g").keyval
for key, value in expected.items():
assert key in actual, f"missing key {key!r} in t.info output"
assert actual[key] == value, (
f"{key}: expected {value!r}, got {actual[key]!r}"
)

return _assert
134 changes: 134 additions & 0 deletions temporal/t.rast.mapcalc/tests/test_t_rast_mapcalc_basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"""Test t.rast.mapcalc basic functionality.

(C) 2025 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
"""

import pytest

import grass.exceptions
from grass.tools import Tools


def test_basic_addition(mapcalc_session, assert_tinfo):
"""Test basic addition of two STRDS with -n flag (register null maps)."""
tools = Tools(session=mapcalc_session, overwrite=True)
tools.t_rast_mapcalc(
flags="n",
inputs="precip_abs1,precip_abs2",
output="precip_abs3",
expression="precip_abs1 + precip_abs2",
basename="new_prec",
method="equal",
nprocs=3,
)
assert_tinfo(
tools,
"precip_abs3",
{
"number_of_maps": 3,
"temporal_type": "absolute",
"name": "precip_abs3",
},
)


def test_division_with_three_inputs(mapcalc_session, assert_tinfo):
"""Test division expression across three input STRDS.

First creates precip_abs3 = precip_abs1 + precip_abs2, then runs the
test expression (precip_abs1 + precip_abs2) / precip_abs2 over all
three STRDS with the -s (sampling) flag.
"""
tools = Tools(session=mapcalc_session, overwrite=True)
tools.t_rast_mapcalc(
flags="n",
inputs="precip_abs1,precip_abs2",
output="precip_abs3",
expression="precip_abs1 + precip_abs2",
basename="new_prec",
method="equal",
nprocs=3,
)
tools.t_rast_mapcalc(
flags="s",
inputs="precip_abs1,precip_abs2,precip_abs3",
output="precip_abs4",
expression="(precip_abs1 + precip_abs2) / precip_abs2",
basename="new_prec",
method="equal",
nprocs=3,
)
assert_tinfo(
tools,
"precip_abs4",
{
"number_of_maps": 3,
"temporal_type": "absolute",
"name": "precip_abs4",
},
)


def test_null_multiplication(mapcalc_session, assert_tinfo):
"""Test multiplication with null() function using -s flag."""
tools = Tools(session=mapcalc_session, overwrite=True)
tools.t_rast_mapcalc(
flags="s",
inputs="precip_abs1,precip_abs2",
output="precip_abs4",
expression="(precip_abs1 + precip_abs2) * null()",
basename="new_prec",
method="equal",
nprocs=3,
)
assert_tinfo(
tools,
"precip_abs4",
{"name": "precip_abs4", "number_of_maps": 0},
)


def test_null_multiplication_with_null_flag(mapcalc_session, assert_tinfo):
"""Test multiplication with null() function using -sn flags."""
tools = Tools(session=mapcalc_session, overwrite=True)
tools.t_rast_mapcalc(
flags="sn",
inputs="precip_abs1,precip_abs2",
output="precip_abs4",
expression="(precip_abs1 + precip_abs2) * null()",
basename="new_prec",
method="equal",
nprocs=3,
)
assert_tinfo(
tools,
"precip_abs4",
{"name": "precip_abs4", "number_of_maps": 3},
)


def test_failure_on_missing_map(mapcalc_session):
"""Test that the module fails when a registered raster is missing.

Hides prec_1 by renaming it so that the STRDS still references the name
but the raster does not resolve. The rename is restored in a finally
block so subsequent tests in the shared session see prec_1.
"""
tools = Tools(session=mapcalc_session, overwrite=True)
tools.g_rename(raster="prec_1,prec_1_hidden")
try:
with pytest.raises(grass.exceptions.CalledModuleError):
tools.t_rast_mapcalc(
flags="sn",
inputs="precip_abs1,precip_abs2",
output="precip_abs4",
expression="(precip_abs1 + precip_abs2) * null()",
basename="new_prec",
method="equal",
nprocs=3,
)
finally:
tools.g_rename(raster="prec_1_hidden,prec_1")
Loading
Loading