Fix duplicate test class, close coverage gaps, enforce coverage gate - #88
Conversation
Phase 0: merge the byte-for-byte-duplicate TestFinalEnergyByCarrierOil class definition in test_statistics_functions.py (the second definition silently shadowed the first at import time) and add an ast-based guard test that fails on any duplicate top-level test class name. Phase 2-3: add targeted unit tests to close remaining coverage gaps in class_definitions.py, statistics_functions.py, and workflow.py (87%/98%/ 96% -> 100%), covering error branches in Network_Processor.__init__, _get_network_config, _get_unit_from_common_definitions, calculate_variables_values, format_timestamps's TypeError fallback, and the module __main__ guard. While closing coverage, testing surfaced a real bug in _get_unit_from_common_definitions: the bracket-parsing check ran before the NaN check, so a NaN unit raised an undocumented TypeError instead of the documented KeyError, making the NaN-handling branch unreachable. Fixed by reordering the checks. Phase 4: enforce --cov-fail-under=90 on the pixi `test` task so coverage regressions fail CI instead of drifting silently. Phase 1 (mock consolidation) was assessed and skipped: the concrete duplication this was meant to fix turned out to be an exact duplicate, already resolved by Phase 0, and the other bespoke mock accessors encode genuinely distinct per-function call shapes rather than copy-paste duplication.
Reviewer's GuideRemoves a silently shadowed duplicate test class, adds regression tests to guard against future duplicate test classes, extends tests to cover error/edge branches in Network_Processor, unit conversion, statistics functions, workflow main execution, and timestamp formatting, fixes _get_unit_from_common_definitions NaN-handling to raise the documented KeyError, and tightens CI by enforcing a 90% coverage minimum on the pytest task. File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The
_setup_processorhelper used in bothTestGetNetworkConfigandTestCalculateVariablesValuesAggregation(and similar config/setup patterns in other tests) is nearly identical; consider factoring this into a shared helper or pytest fixture to reduce duplication and keep future changes to the setup logic in one place. - Several new tests assert on exact
printed WARNING/INFO strings fromNetwork_Processormethods; consider centralizing these messages as constants or, better, switching to the logging module so tests can assert on log records instead of brittle stdout string matches.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `_setup_processor` helper used in both `TestGetNetworkConfig` and `TestCalculateVariablesValuesAggregation` (and similar config/setup patterns in other tests) is nearly identical; consider factoring this into a shared helper or pytest fixture to reduce duplication and keep future changes to the setup logic in one place.
- Several new tests assert on exact `print`ed WARNING/INFO strings from `Network_Processor` methods; consider centralizing these messages as constants or, better, switching to the logging module so tests can assert on log records instead of brittle stdout string matches.
## Individual Comments
### Comment 1
<location path="tests/test_network_processor.py" line_range="1627-1636" />
<code_context>
+class TestCalculateVariablesValuesAggregation:
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen aggregation test by asserting on actual merged values, not just column labels.
In `test_merges_multiple_investment_years_when_aggregated`, you currently only assert the presence of columns `"2020"` and `"2030"` and the single-row shape. Please also assert the actual cell values against the per-year outputs from `fake_execute` (e.g. `assert result.loc[("AT1", "MWh_el"), "2020"] == 2020.0` and similarly for 2030) to ensure the aggregation logic and reindexing are correct, not just the column labels.
Suggested implementation:
```python
assert "2020" in result.columns
assert "2030" in result.columns
assert result.shape == (1, 2)
# Assert merged values for each investment year to validate aggregation
assert result.loc[("AT1", "MWh_el"), "2020"] == 2020.0
assert result.loc[("AT1", "MWh_el"), "2030"] == 2030.0
```
If the test currently uses a different MultiIndex key than `("AT1", "MWh_el")`, or different numeric values from `fake_execute`, adjust the tuple and the expected numbers accordingly. Likewise, if the index is a simple Index (not MultiIndex), replace `("AT1", "MWh_el")` with the appropriate single index label used by the test.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| class TestCalculateVariablesValuesAggregation: | ||
| """Test calculate_variables_values() for aggregate_per_year branches.""" | ||
|
|
||
| def _setup_processor(self, tmp_path: Path) -> Network_Processor: | ||
| defs_path = tmp_path / "definitions" | ||
| defs_path.mkdir(exist_ok=True) | ||
| nw_path = tmp_path / "networks" | ||
| nw_path.mkdir(parents=True, exist_ok=True) | ||
| (nw_path / "dummy.nc").touch() | ||
| config_content = f""" |
There was a problem hiding this comment.
suggestion (testing): Strengthen aggregation test by asserting on actual merged values, not just column labels.
In test_merges_multiple_investment_years_when_aggregated, you currently only assert the presence of columns "2020" and "2030" and the single-row shape. Please also assert the actual cell values against the per-year outputs from fake_execute (e.g. assert result.loc[("AT1", "MWh_el"), "2020"] == 2020.0 and similarly for 2030) to ensure the aggregation logic and reindexing are correct, not just the column labels.
Suggested implementation:
assert "2020" in result.columns
assert "2030" in result.columns
assert result.shape == (1, 2)
# Assert merged values for each investment year to validate aggregation
assert result.loc[("AT1", "MWh_el"), "2020"] == 2020.0
assert result.loc[("AT1", "MWh_el"), "2030"] == 2030.0If the test currently uses a different MultiIndex key than ("AT1", "MWh_el"), or different numeric values from fake_execute, adjust the tuple and the expected numbers accordingly. Likewise, if the index is a simple Index (not MultiIndex), replace ("AT1", "MWh_el") with the appropriate single index label used by the test.
Summary
TestFinalEnergyByCarrierOilclass intests/test_statistics_functions.py(the second definition silently shadowed the first at import time — no tests were actually lost since both blocks were identical, but it was dead duplicate code). Added an ast-based regression guard (tests/test_no_duplicate_test_classes.py) that fails on any duplicate top-level test class name intests/._OilStatisticsAccessormocks) turned out to be an exact duplicate, already resolved by Phase 0. The other 8 bespoke per-function mock accessors encode genuinely distinctpypsa.statisticscall shapes, not copy-paste duplication, so consolidating them into one generic fixture wasn't pursued.class_definitions.py(87% → 100%),statistics_functions.py(98% → 100%), andworkflow.py(96% → 100%):Network_Processor.__init__error branches,_get_network_config,_get_unit_from_common_definitions,calculate_variables_valuesmulti-year aggregation,format_timestamps'sTypeErrorfallback, and the module__main__guard._get_unit_from_common_definitions— the bracket-parsing check ran before the NaN check, so a NaN unit raised an undocumentedTypeErrorinstead of the documentedKeyError, making the NaN-handling branch unreachable dead code. Fixed by reordering the checks (pypsa_validation_processing/class_definitions.py).--cov-fail-under=90on thetestpixi task so coverage regressions fail CI instead of drifting silently.Closes #32. The issue comment about cross-validation between Final Energy variables (by carrier / by sector) is out of scope here — tracked as separate follow-up work.
Test plan
pixi run test— 224 passed, 100% coverage,--cov-fail-under=90gate passespixi run workflow_test— all 4 config setups (country/region × timeseries/year) run successfully, plus full test suitepixi run black --checkon touched filestests/test_no_duplicate_test_classes.pypasses, confirming no new name collisionsSummary by Sourcery
Remove duplicate test code, harden unit handling and configuration logic, and strengthen test coverage and CI coverage enforcement.
New Features:
Bug Fixes:
Enhancements:
Build: