gramps.gen.filters.rules.test.person_rules_test.FilterMatchProxyDbTest() should generate an error on Github, but it doesn't

Hello,
The code below produce error (as it should) when I run it locally on Debian 13:

class FilterMatchProxyDbTest(unittest.TestCase):
    PRIVATE_PERSON_ID = "I0988"
    CHILD_OF_PRIVATE_ID = "I0092"

    @classmethod
    def setUpClass(cls):
        raw_db = import_as_dict(EXAMPLE, User())
        cls.db = raw_db
        cls.proxy_db = PrivateProxyDb(raw_db)

        # Confirm setup assumptions
        private_person = raw_db.get_person_from_gramps_id(cls.PRIVATE_PERSON_ID)
        assert (
            private_person is not None and private_person.private
        ), "Test setup: I0988 must be private in example.gramps"
        assert (
            cls.proxy_db.get_person_from_handle(private_person.handle) is None
        ), "Test setup: PrivateProxyDb must hide private people"

When I run:

LANG=en_US.utf-8 GDK_BACKEND=- GRAMPS_RESOURCES=build/share python3 -m unittest  discover -t . -s ./gramps/gen/filters/rules -p "*test.py"

I get:

ERROR: setUpClass (gramps.gen.filters.rules.test.person_rules_test.FilterMatchProxyDbTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/petr/Gramps/gramps/gen/filters/rules/test/person_rules_test.py", line 1663, in setUpClass
    private_person is not None and private_person.private
AssertionError: Test setup: I0988 must be private in example.gramps

The root cause is this line: raw_db = import_as_dict(EXAMPLE, User()). It had to be changed to:

    cls.db = import_as_dict(
        EXAMPLE,
        User(),
        person_prefix="I%04d",
        media_prefix="O%04d",
        family_prefix="F%04d",
        source_prefix="S%04d",
        citation_prefix="C%04d",
        place_prefix="P%04d",
        event_prefix="E%04d",
        repository_prefix="R%04d",
        note_prefix="N%04d",
    )

similar to line 155 of the same file. But what I can not understand is why the test pass on Github!

Gemini suggested that it might happen because optimization removes assert (somehow). To test I ran (note the -O flag):

LANG=en_US.utf-8 GDK_BACKEND=- GRAMPS_RESOURCES=build/share python3 -O -m unittest  discover -t . -s ./gramps/gen/filters/rules -p "*test.py"

And got two errors instead of one:

ERROR: test_IsChildOfFilterMatch_proxy_excludes_private_seed (gramps.gen.filters.rules.test.person_rules_test.FilterMatchProxyDbTest.test_IsChildOfFilterMatch_proxy_excludes_private_seed)
When the seed filter contains only the private person I0988,
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/petr/Gramps/gramps/gen/filters/rules/test/person_rules_test.py", line 1695, in test_IsChildOfFilterMatch_proxy_excludes_private_seed
    self.db.get_person_from_gramps_id(self.CHILD_OF_PRIVATE_ID).handle,
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'handle'

======================================================================
ERROR: test_IsParentOfFilterMatch_proxy_excludes_private_from_result (gramps.gen.filters.rules.test.person_rules_test.FilterMatchProxyDbTest.test_IsParentOfFilterMatch_proxy_excludes_private_from_result)
When the seed filter contains I0092 (child of private I0988),
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/petr/Gramps/gramps/gen/filters/rules/test/person_rules_test.py", line 1714, in test_IsParentOfFilterMatch_proxy_excludes_private_from_result
    ).handle
      ^^^^^^
AttributeError: 'NoneType' object has no attribute 'handle'

These errors are expected and the change proposed above removes them too. But again, why the test pass on Github?

To be honest there are many other unit tests failing on my machine, so the problem may be in my environment. But this particular case seems very strange - it must not work on maintenance/gramps61. Please have a look.

Looks like one of the remaining tests that behaves differently when the settings are different between local and CI. Your changes to pass in those extra values are correct.

The root cause of the issue is this line, in gramps/plugins/test/reports_test.py module which runs during import of test modules, i.e. before start of unit test execution:

reports = ReportControl()

It executes this code :

 def __init__(self):
      super().__init__()
      self.tearDown()  # removes it if it existed
      out, err = self.call(
          "-C",
          TREE_NAME,
          "--import",
          example,
          # the test results depend on specific grampsIds, so we need to use the same prefixes as the example database
          "--config=preferences.iprefix:I%04d",
          "--config=preferences.oprefix:O%04d",
          "--config=preferences.fprefix:F%04d",
          "--config=preferences.sprefix:S%04d",
          "--config=preferences.cprefix:C%04d",
          "--config=preferences.pprefix:P%04d",
          "--config=preferences.eprefix:E%04d",
          "--config=preferences.rprefix:R%04d",
          "--config=preferences.nprefix:N%04d",
      )

which modifies the singleton configuration object gramps.gen.config.config, so all unit tests run with old values of preferences, i.e. with 'I%04d', not with 'I%05d'.

With reports_test.py removed, three unit test modules fail

PR #2235 “Change the default gramps IDs to %05d” may be of interest to you.

I’ve added setUpModule() and tearDownModule() to reports_test.py and moved module-level initialization code into the former.

Also setUpModule() captures state of gramps.gen.config.config before execution of reports = ReportControl() and the remaining initialization, and tearDownModule() restores it.

Now unit tests which should fail - fail as expected.

Later I’ll try to fix the failing tests and, if successful, will submit PR with all changes.

PR #2478 which resolves the issue has been submitted