Skip to content

[Experiment] Unit test coverage#17466

Draft
ohmayr wants to merge 5 commits into
mainfrom
experiment-with-unit-tests
Draft

[Experiment] Unit test coverage#17466
ohmayr wants to merge 5 commits into
mainfrom
experiment-with-unit-tests

Conversation

@ohmayr

@ohmayr ohmayr commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces template coverage measurement for Jinja templates by adding a custom coverage plugin (jinja_coverage.py), a configuration file (.coveragerc-templates), and new Nox sessions (template_coverage, downstream_golden_tests, and showcase_prerelease_deps). It also adds integration test configurations and a unit test to render goldens for coverage. The review feedback highlights several critical improvements: resolving a potential NameError in noxfile.py by using os.path instead of path, avoiding fragile hardcoded line exclusions in jinja_coverage.py in favor of inline pragmas, and adding robustness checks for missing configuration options and Jinja loader attributes.

Comment on lines +144 to +169
if self.filename.endswith("test_macros.j2"):
excluded.update([59, 150, 319, 320, 321, 493, 561, 619, 620, 621, 658, 1191, 1207, 1217, 1312, 1419, 1540, 1541, 1542, 1576, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1679, 1715, 1716, 1717, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 2024, 2025, 2040])
if self.filename.endswith("_client_macros.j2"):
excluded.update([43, 65, 84, 133, 134, 137, 194, 199, 220, 222])
if self.filename.endswith("client.py.j2"):
excluded.update([71, 680, 681])
if self.filename.endswith("async_client.py.j2"):
excluded.update([52, 321, 442])
if self.filename.endswith("transports/base.py.j2"):
excluded.update([46, 51, 164, 170, 174, 175, 292])
if self.filename.endswith("transports/grpc.py.j2"):
excluded.update([50, 340])
if self.filename.endswith("transports/grpc_asyncio.py.j2"):
excluded.update([54, 345])
if self.filename.endswith("transports/_mixins.py.j2"):
excluded.update([172, 199])
if self.filename.endswith("services/%service/_mixins.py.j2"):
excluded.update([291, 298, 301, 308, 311, 321, 412, 419, 426, 433, 447, 534, 541, 552, 559])
if self.filename.endswith("services/%service/_async_mixins.py.j2"):
excluded.update([291, 298, 301, 308, 311, 321, 412, 419, 426, 433, 447, 534, 541, 552, 559])
if self.filename.endswith("services/%service/_shared_macros.j2"):
excluded.update([27, 106, 133, 159, 172, 177, 313, 314, 316, 317, 319, 320, 323, 324])
if self.filename.endswith("services/%service/pagers.py.j2"):
excluded.update([30])
if self.filename.endswith("services/%service/transports/rest_asyncio.py.j2"):
excluded.update([188])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Hardcoding specific line numbers for exclusion is highly fragile and will break whenever the templates are modified or lines are shifted. Since you already have a mechanism to exclude lines matching pragma: no cover (lines 106 and 139-142), you should use inline comments like {# pragma: no cover #} directly in the Jinja templates instead of maintaining these hardcoded lists of line numbers here.

Comment on lines +905 to +912
goldens_dir = path.join("tests", "integration", "goldens")

# Iterate through all golden directories
for golden in os.listdir(goldens_dir):
golden_path = path.join(goldens_dir, golden)

# If it's a generated package with a noxfile, run its unit tests
if path.isdir(golden_path) and path.exists(path.join(golden_path, "noxfile.py")):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Using path directly (e.g., path.join, path.isdir, path.exists) will raise a NameError if path is not imported from os. Since os is already imported (as seen in os.listdir), you should use os.path consistently.

Suggested change
goldens_dir = path.join("tests", "integration", "goldens")
# Iterate through all golden directories
for golden in os.listdir(goldens_dir):
golden_path = path.join(goldens_dir, golden)
# If it's a generated package with a noxfile, run its unit tests
if path.isdir(golden_path) and path.exists(path.join(golden_path, "noxfile.py")):
goldens_dir = os.path.join("tests", "integration", "goldens")
# Iterate through all golden directories
for golden in os.listdir(goldens_dir):
golden_path = os.path.join(goldens_dir, golden)
# If it's a generated package with a noxfile, run its unit tests
if os.path.isdir(golden_path) and os.path.exists(os.path.join(golden_path, "noxfile.py")):

Comment on lines +24 to +25
def __init__(self, options):
self.template_directory = os.path.abspath(options.get("template_directory"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If template_directory is missing from the options, options.get("template_directory") will return None, causing os.path.abspath to raise a TypeError. Adding a check with a clear error message improves robustness.

    def __init__(self, options):
        template_dir = options.get("template_directory")
        if not template_dir:
            raise ValueError("template_directory option is required for JinjaPlugin")
        self.template_directory = os.path.abspath(template_dir)

Comment on lines +59 to +62
if env and env.loader:
try:
co_filename = frame.f_code.co_filename
for search_path in env.loader.searchpath:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Not all Jinja loaders have a searchpath attribute (e.g., PackageLoader or DictLoader do not). Using getattr to safely retrieve searchpath avoids raising and catching unnecessary AttributeError exceptions.

        if env and env.loader:
            try:
                co_filename = frame.f_code.co_filename
                search_paths = getattr(env.loader, "searchpath", [])
                for search_path in search_paths:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant