Skip to content

pytest: Run g.html2man testsuite test with pytest - #678

Closed
echoix wants to merge 1 commit into
mainfrom
claude/pytest-migration-candidates-g5nxes
Closed

echoix wants to merge 1 commit into
mainfrom
claude/pytest-migration-candidates-g5nxes

Conversation

@echoix

@echoix echoix commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Description

Adds utils/g.html2man/testsuite/test_ghtml2man.py to the set of grass.gunittest-based testsuite/ tests that already run directly under pytest (.github/workflows/pytest_args_gunittest.txt), and excludes it from the grass.gunittest runner (.gunittest.cfg) to avoid running it twice, following the pattern from OSGeo#5584 and OSGeo#6523.

The test only parses the already-installed HTML manual pages (self.gisbase/docs/html/*.html) and doesn't need an active GRASS session or the North Carolina sample dataset. It does read the GISBASE environment variable, which the pytest.yml and macos.yml "gunittest-based tests" steps didn't export before this change (osgeo4w.yml already exports it via env.bat), so this PR exports it there too.

Motivation and context

I was asked to look at how grass.gunittest testsuite tests became runnable under pytest in CI, then find and try other candidate testsuite files that could run under pytest the same way without needing a rewrite (i.e. without needing an active session or the NC sample dataset). I researched this with an AI assistant (Claude), including verifying every candidate against an actual from-source build rather than relying on static reading alone.

I looked at roughly 20 files that looked promising from static analysis (no assertModule/runModule/run_command-style calls visible in the test file itself). Most turned out not to work when actually run:

  • python/grass/pygrass/vector/testsuite/test_table.py: looked self-contained (own temp sqlite3 db), but its tearDown calls Table.drop(), which internally calls db_table_in_vector() → g.list, which needs an active GRASS session. Fails with ERROR: No active GRASS session: GISRC environment variable not set.
  • python/grass/pygrass/modules/testsuite/test_import_isolation.py: passes on its own, but fails when run in the same pytest process as the other allowlisted files, because they import grass.lib.* (ctypes bindings) first and this test's whole point is asserting nothing has imported those yet.
  • The four *_doctests.py files built on doctest.DocTestSuite(...) inside a module-level load_tests(loader, tests, ignore) function (test_gunitest_doctests.py, test_pygrass_modules_interface_doctests.py, test_pygrass_shell_doctests.py, test_pygrass_messages_doctests.py): pytest's _pytest/unittest.py collector only discovers actual unittest.TestCase subclasses defined in a module; it never calls the load_tests protocol hook that only unittest.TestLoader.loadTestsFromModule()/discover() invoke. So these files collect 0 items under pytest regardless of what they test, confirmed with pytest --collect-only vs python -m unittest. I had hoped to split the session-dependent doctests (e.g. grass.pygrass.modules.interface.module, grass.gunittest.gmodules) out into new files so the remaining pure-logic doctests (e.g. grass.pygrass.shell.conversion, grass.gunittest.checkers) could be added to the allowlist, but this collection limitation means splitting wouldn't help; it would need restructuring away from load_tests entirely, which felt out of scope here.

Only test_ghtml2man.py survived, so that's the only test added in this PR.

How has this been tested?

Built GRASS locally from source (CMake, Ubuntu 24.04 packages matching .github/workflows/apt.txt minus PDAL, WITH_GUI=OFF, WITH_DOCS=ON to get the real per-tool docs/html/*.html files this test reads) and ran, matching the CI step's env and args:

pytest @.github/workflows/pytest_args_gunittest.txt

Result: 95 passed, 2 xfailed (previously 94 passed, 2 xfailed), with test_ghtml2man.py passing against the 550 real installed doc pages.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist

  • PR title provides summary of the changes and starts with one of the pre-defined prefixes
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have added tests to cover my changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_0169cUQFskpDPA7wVJ7paGVG


Generated by Claude Code

test_ghtml2man.py is a grass.gunittest.case.TestCase test that only
parses the already-installed HTML manual pages, so it does not need
an active GRASS session or the North Carolina sample dataset like
most other testsuite files. Add it to the pytest allowlist and
exclude it from the grass.gunittest runner, following the pattern
used for the other tests already running under pytest.

It reads the GISBASE environment variable, which the pytest.yml and
macos.yml gunittest steps did not export before this change
(osgeo4w.yml already exports it via env.bat), so export it there too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0169cUQFskpDPA7wVJ7paGVG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant