Skip to content

grass.script, man: Add tests for utils and parser_standard_options - #751

Open
echoix wants to merge 3 commits into
mainfrom
utils-tests-pynguin-gaps
Open

echoix wants to merge 3 commits into
mainfrom
utils-tests-pynguin-gaps

Conversation

@echoix

@echoix echoix commented Oct 27, 2026

Copy link
Copy Markdown
Owner

Description

Add pytest tests for grass.script.utils helpers (legalize_vector_name, append_*, basename, try_remove/try_rmdir, parse_key_val, get_lib_path, set_path, and others) and for man/parser_standard_options.py, which had no tests. Fix a parenthesis counting bug in parse_options found while writing them (separate commit).

Motivation and context

Pynguin was run on grass.script.utils and man/parser_standard_options.py to find untested code. Its generated tests were not usable as-is, so the tests are written by hand, with AI assistance, with expected values checked against the code. Pynguin only indicated the gaps.

parse_options did diff -= count_par_diff(line), so a multiline G_ call made it skip every line until break;. The generated documentation is unchanged, because the C source only has such calls as the last statement of a case.

How has this been tested?

  • pytest python/grass/script/tests/utils_test.py man/tests: all pass. Coverage of grass.script.utils under pytest goes from 32% to 88%.
  • Mutations of utils.py and parser_standard_options.py were applied to check that the tests fail when the code changes.
  • Output of parse_options on lib/gis/parser_standard_options.c is identical before and after the fix (89 options).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

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 updated the documentation accordingly.
  • I have added tests to cover my changes.

Generated by Claude Code

Cover legalize_vector_name, append_random, append_uuid, append_node_pid,
basename, try_remove, try_rmdir, diff_files, split, naturally_sorted,
get_num_suffix, parse_key_val, get_lib_path and set_path.

Gaps were found by running Pynguin on grass.script.utils. The tests are
written by hand, with AI assistance, and the expected values were
checked against the behavior of the functions. Several mutations of
utils.py were used to confirm that the tests fail when the code changes.
Test the extraction of standard options from lib/gis/parser_standard_options.c
(dynamic answers, multiline strings, multiline function calls, escaped
quotes), the heading lookup, the Markdown generation for a single option
and the CSV, HTML and Markdown output of the option table. The whole real
C source file is parsed to check that every standard option is found.

Pynguin was run on the module to see what a generator can do. It only
produced empty inputs for the nested list and dict parameters, so the
tests are written by hand, with AI assistance, with expected values
checked against the C source. Mutations of the module were used to
confirm that the tests fail when the code changes.
A multiline G_ call in a case of lib/gis/parser_standard_options.c, such
as G_asprintf(, set the open parenthesis count and the following lines
subtracted their net count, so the closing line increased the count
instead of bringing it to zero. All lines after the call were then
skipped until the end of the case.

The standard options currently in the C source have such calls only as
the last statement of a case, so the generated documentation is
unchanged. Add the continuation lines' net count instead, and add a test
with an assignment after a multiline call.

The problem was found by checking whether the new tests detect changes
of this line, with AI assistance.
def test_naturally_sorted_key():
"""Check that the key function selects the text used for sorting"""
items = [("b", "file10"), ("a", "file9")]
assert gutils.naturally_sorted(items, key=lambda item: item[1]) == [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ruff] reported by reviewdog 🐶

Suggested change
assert gutils.naturally_sorted(items, key=lambda item: item[1]) == [
assert gutils.naturally_sorted(items, key=operator.itemgetter(1)) == [

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

2 participants