Skip to content

TST: expand test coverage with edge cases and identity checks (#58) - #140

Draft
MukundaKatta wants to merge 1 commit into
numpy:mainfrom
MukundaKatta:test/expand-coverage
Draft

MukundaKatta wants to merge 1 commit into
numpy:mainfrom
MukundaKatta:test/expand-coverage

Conversation

@MukundaKatta

Copy link
Copy Markdown

Summary

Refs #58. Expands test coverage with edge cases and identity checks. No library code touched.

Coverage delta

numpy_financial/_financial.py: 97% (6 missing) → 99% (2 missing). The 2 remaining lines are unreachable defensive branches.

What's added

83 new test cases in 8 classes covering:

  • Edge cases: zero-rate paths for fv/pmt/pv/nper, infinite cashflows, scalar/0-d/array shapes, negative rates
  • Error paths: npv invalid shape, mirr size mismatch (both raise + nan-return), irr no-real-solution, rate iterations-exceeded array path
  • Vectorized vs scalar parity for fv, pmt, pv
  • Analytical round-trips: pmt = ppmt + ipmt, npv(irr(x), x) = 0, fv/pv inverse relations
  • _convert_when alias coverage (9 aliases + ndarray pass-through + KeyError)
  • _irr_default_selection mixed-sign / same-sign / all-negative branches + custom selection_logic injection

Files changed

  • numpy_financial/tests/test_coverage_expansion.py (new, 550 lines, 83 tests)

Test plan

  • All 193 tests pass (110 existing + 83 new)
  • ruff format and ruff check clean on the new file

Adds numpy_financial/tests/test_coverage_expansion.py with 83 new
tests focused on:

* zero-rate edge cases for fv, pmt, pv, nper
* error paths (npv shape errors, mirr size mismatch, irr no real
  solution, rate iterations exceeded on arrays)
* vectorized vs scalar parity for fv, pmt, pv
* analytical round-trip identities (pmt = ppmt + ipmt,
  npv(irr(x), x) = 0, fv/pv inversion)
* _convert_when alias dispatch and ndarray pass-through
* _irr_default_selection branches and custom selection_logic

Coverage of numpy_financial/_financial.py rises from 97% to 99%.
Refs numpygh-58.
@milliondreamsblog

Copy link
Copy Markdown

One policy question raised by test_irr_default_selection_mixed_signs_picks_positive: for mixed-sign candidates, pos is positive and neg is negative, so pos >= neg always holds. The test comment describes that comparison as a condition, but the current behaviour is simply to prefer a non-negative root before choosing the smallest magnitude.

A cash-flow example makes the distinction visible:

import numpy_financial as npf
npf.irr([-100, 207, -106.4])
# 0.11999999999999855

Both -5% and 12% make NPV zero here. The returned 12% is valid, but it is not the root closest to zero.

Is that preference intended? If so, could the test comment and the selection-policy documentation state it directly? The implementation comment also mentions comparing cash flows, although _irr_default_selection receives candidate rates.

I checked this against 1.1.0 and the financial module at this PR's head, aeff04c. They agree. This is a policy/documentation question, rather than a request to force coverage of the unreachable branch.

This branch has not been deployed

No deployments
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.

2 participants