Skip to content

TEST: Add tests for triangle.py. - #1088

Open
genedan wants to merge 3 commits into
mainfrom
triangle_tests
Open

TEST: Add tests for triangle.py.#1088
genedan wants to merge 3 commits into
mainfrom
triangle_tests

Conversation

@genedan

@genedan genedan commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary of Changes

Add tests for uncovered lines in triangle.py.

@henrydingliu, could you submit a PR testing for these lines for the disposal rate method? I think you'd be able to create a better test than I can:

if not obj.is_full:
obj = obj[obj.valuation <= obj.valuation_date]
if hasattr(obj, "disposal_w_"):

Related GitHub Issue(s)

Additional Context for Reviewers

I left any lines dealing with dask/cupy uncovered.

  • I passed tests locally for both code (uv run pytest) and documentation changes (uv run jb build docs --builder=custom --custom-builder=doctest)

Note

Low Risk
Test-only changes with no production code modifications; risk is limited to CI/runtime of the expanded test suite.

Overview
Expands test_triangle.py to lock in behavior for several Triangle APIs that lacked direct tests: link_ratio (pattern metadata, zero→NaN via num_to_nan, idempotent when is_pattern), index / set_index (DataFrame-only setter, length/type errors, inplace vs copy), trend and shift invalid-axis errors and shift(0) identity, sort_axis on columns/origin/development (values permute with labels), dev_to_val no-op on valuation triangles, and __init__ array-backend handling when AUTO_SPARSE / ARRAY_BACKEND options apply.

The rest of the diff is cosmetic in existing tests (spacing, is vs ==, boolean asserts, type(...) is str).

Reviewed by Cursor Bugbot for commit fc400c2. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Pyright Type Completeness

View the full pyright --verifytypes output for this commit

Project (full chainladder package, at this PR's head): 15.2% of exported symbols fully typed (206 / 1353)

Known Ambiguous Unknown Total
Project (head) 206 111 1036 1353

Other symbols referenced but not exported by chainladder: 13

Known Ambiguous Unknown Total
Other (head) 3 1 9 13

Symbols without documentation:

  • Functions without docstring: 323
  • Functions without default param: 0
  • Classes without docstring: 10

Patch (exported symbols added or changed by this PR): 23.5% fully typed (4 / 17)

Known Ambiguous Unknown Total
Patch 4 0 13 17
Patch symbol details
Symbol Status Change
chainladder.core.tests.test_triangle.test_dev_to_val_inplace_on_val_tri_returns_self ❌ unknown new
chainladder.core.tests.test_triangle.test_index_setter_length_mismatch_raises ❌ unknown new
chainladder.core.tests.test_triangle.test_index_setter_non_dataframe_raises ❌ unknown new
chainladder.core.tests.test_triangle.test_index_setter_with_dataframe ❌ unknown new
chainladder.core.tests.test_triangle.test_init_calls_set_backend_when_auto_sparse_disabled ✅ known new
chainladder.core.tests.test_triangle.test_init_defaults_array_backend_to_option ✅ known new
chainladder.core.tests.test_triangle.test_link_ratio_converts_zero_ratios_to_nan ✅ known new
chainladder.core.tests.test_triangle.test_link_ratio_on_pattern_returns_self ❌ unknown new
chainladder.core.tests.test_triangle.test_link_ratio_sets_pattern_metadata ❌ unknown new
chainladder.core.tests.test_triangle.test_set_index_inplace ❌ unknown new
chainladder.core.tests.test_triangle.test_set_index_not_inplace ❌ unknown new
chainladder.core.tests.test_triangle.test_shift_invalid_axis_raises ❌ unknown new
chainladder.core.tests.test_triangle.test_shift_zero_periods_returns_self ❌ unknown new
chainladder.core.tests.test_triangle.test_sort_axis_columns_reorders_values ✅ known new
chainladder.core.tests.test_triangle.test_sort_axis_development_reorders_values ❌ unknown new
chainladder.core.tests.test_triangle.test_sort_axis_origin_reorders_values ❌ unknown new
chainladder.core.tests.test_triangle.test_trend_invalid_axis_raises ❌ unknown new

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.66%. Comparing base (558274f) to head (fc400c2).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1088      +/-   ##
==========================================
+ Coverage   91.27%   91.66%   +0.38%     
==========================================
  Files          91       91              
  Lines        5411     5411              
  Branches      692      692              
==========================================
+ Hits         4939     4960      +21     
+ Misses        338      329       -9     
+ Partials      134      122      -12     
Flag Coverage Δ
unittests 91.66% <ø> (+0.38%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

assert tri.key_labels == ["Company"]
np.testing.assert_array_equal(tri.kdims, new_index.values)
# _set_slicers() must have rebuilt .loc against the new key label.
assert tri.loc["A"].kdims.tolist() == [["A"]]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

would a stronger test be tri.loc["A"] == clrd.iloc[:1]?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added, but I'm not sure if this is desirable behavior. The two triangles have different index values, but testing their equality results in True:

clrd.iloc[:1].index
Out[3]: 
            GRNAME      LOB
0  Adriatic Ins Co  othliab
tri.loc["A"].index
Out[4]: 
  Company
0       A
tri.loc["A"] == clrd.iloc[:1]
Out[5]: np.True_

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hmmm nevermind. You can actually do this in Pandas. I guess I'm not a huge fan of this ability but we should be ok.

df = pd.DataFrame({"Sales": [100, 200, 300]}, index=["Apple", "Banana", "Cherry"])
# Relabel specific index values
df_new = df.rename(index={"Apple": "Green Apple", "Cherry": "Berry"})
df.loc['Apple'] == df_new.loc['Green Apple']
Out[2]: 
Sales    True
dtype: bool

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess I'm not a huge fan of this ability but we should be ok.

would it change your mind to consider this ability in this context?

df.loc["A"] = df.loc["B"]
assert df.loc["A"] == df.loc["B"]

Comment thread chainladder/core/tests/test_triangle.py
val_tri = qtr.dev_to_val()
assert val_tri.is_val_tri

result = val_tri.dev_to_val(inplace=True)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

inplace=False?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It should be inplace=True, since the test is deliberately testing the inplace feature.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

but the assert in the next line would still pass if inplace=False?

Comment thread chainladder/core/tests/test_triangle.py
cl.options.reset_option("ARRAY_BACKEND")


def test_init_calls_set_backend_when_auto_sparse_disabled() -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the implementation is kinda messy (maybe a small refactor is in order). i think we can benefit from a more consolidated test, i.e.

#the parameter supplied to the constructor will always override everything else (no idea if this is true, just making up something
assert cl.Triangle(backend = 'numpy').array_backend == 'numpy'

#if parameter is left out, cl.options.AUTO_SPARSE takes precedence
assert ...

Comment thread chainladder/core/tests/test_triangle.py
@henrydingliu henrydingliu mentioned this pull request Jul 10, 2026
1 task
@henrydingliu

Copy link
Copy Markdown
Member

@genedan checking in to see if you've had a chance to look through my comments?

@genedan

genedan commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

Still working on it - just wanted to prioritize the contributing guidelines and 0.10.0 release work, I'll get back to this once those are done.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fc400c2. Configure here.


def test_quantile_vs_median(clrd):
xp = clrd.get_array_module()
clrd.get_array_module()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dead leftover module call

Low Severity

test_quantile_vs_median now calls clrd.get_array_module() and discards the result. The call has no side effects used by the quantile/median assertion, so it is dead code left behind after the unused xp assignment was removed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit fc400c2. Configure here.

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