CI: Added C and Python Code Coverage by ganesh-k13 · Pull Request #30911 · numpy/numpy · GitHub
Skip to content

CI: Added C and Python Code Coverage#30911

Open
ganesh-k13 wants to merge 4 commits into
numpy:mainfrom
ganesh-k13:coverage_ci
Open

CI: Added C and Python Code Coverage#30911
ganesh-k13 wants to merge 4 commits into
numpy:mainfrom
ganesh-k13:coverage_ci

Conversation

@ganesh-k13

@ganesh-k13 ganesh-k13 commented Mar 2, 2026

Copy link
Copy Markdown
Member

@ganesh-k13

Copy link
Copy Markdown
Member Author

@ganesh-k13 ganesh-k13 marked this pull request as draft March 2, 2026 04:22
@mattip

mattip commented Mar 2, 2026

Copy link
Copy Markdown
Member

It might be nice to add a spin coverage command that would take an output argument. It would check that the dependencies are in place, and run pytest —coverage. That way people could check it all offline

@mattip

mattip commented Mar 2, 2026

Copy link
Copy Markdown
Member

Do you use the c_coverage directory?

@ganesh-k13

Copy link
Copy Markdown
Member Author

I was thinking same @mattip , would something like scientific-python/spin#315 work?

Do you use the c_coverage directory?

No, we use Ninja's builtin gcov: https://github.com/scientific-python/spin/blob/1713846e86d1c84037976e0f2392abead645c75d/spin/cmds/meson.py#L660-L665

@ganesh-k13

ganesh-k13 commented Mar 3, 2026

Copy link
Copy Markdown
Member Author

It works 🎉, reports from CI run:

It might be worth waiting for scientific-python/spin#316 however, but I'm marking it ready for review as just the command will change.

@ganesh-k13 ganesh-k13 marked this pull request as ready for review March 3, 2026 05:00
@mattip

mattip commented Mar 3, 2026

Copy link
Copy Markdown
Member

Cool. The artifacts can only be viewed via the CI run link, and then opening the "Upload Python coverage report" section, then clicking the link. Likewise the C coverage report. The link you put into the comment above does not work (maybe it is only for you?). Then I get a text table showing each file, here are the first few rows:

-----------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: /home/runner/work/numpy/numpy
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
build/numpy/_core/__multiarray_api.h          36      20    55%   1498-1499,1513-1515,1520-1521,1541,1543-1544,1548,1558,1567,1569,1580,1583
build/numpy/_core/__ufunc_api.h               26      15    57%   266-267,271,273,279-280,284-286,291-292
build/numpy/_core/__umath_generated.c       3515    3140    89%   2631,2634,2637,2655,2658,2661,2679,2682,2685,2703,2706,2709,2727,2730,2733,2751,2754,2757,2775,2778,2781,2799,2802,2805,2823,2826,2829,2847,2850,2853,2871,2874,2877,2895,2898,2901,2919,2922,2925,2943,2946,2949,2967,2970,2973,2991,2994,2997,3015,3018,3021,3437,3440,3443,3461,3464,3467,3485,3488,3491,3509,3512,3515,3734,3737,3740,3758,3761,3764,3782,3785,3788,3806,3809,3812,3830,3833,3836,3854,3857,3860,3878,3881,3884,3902,3905,3908,3926,3929,3932,3950,3953,3956,3974,3977,3980,3998,4001,4004,4022,4025,4028,4046,4049,4052,4089,4092,4095,4113,4116,4119,4137,4140,4143,4161,4164,4167,4185,4188,4191,4209,4212,4215,4233,4236,4239,4257,4260,4263,4281,4284,4287,4305,4308,4311,4329,4332,4335,4353,4356,4359,4377,4380,4383,4401,4404,4407,4444,4447,4450,4468,4471,4474,4492,4495,4498,4516,4519,4522,4540,4543,4546,4564,4567,4570,4588,4591,4594,4612,4615,4618,4636,4639,4642,4660,4663,4666,4684,4687,4690,4708,4711,4714,4732,4735,4738,4756,4759,4762,5516,5519,5522,5540,5543,5546,5564,5567,5570,5588,5591,5594,5612,5615,5618,5636,5639,5642,5660,5663,5666,5684,5687,5690,5708,5711,5714,5732,5735,5738,5756,5759,5762,5780,5783,5786,5804,5807,5810,5828,5831,5834,5871,5874,5877,5895,5898,5901,5919,5922,5925,5943,5946,5949,5967,5970,5973,5991,5994,5997,6015,6018,6021,6039,6042,6045,6063,6066,6069,6087,6090,6093,6111,6114,6117,6135,6138,6141,6159,6162,6165,6183,6186,6189,6244,6247,6250,6268,6271,6274,6292,6295,6298,6316,6319,6322,6340,6343,6346,6364,6367,6370,6388,6391,6394,6412,6415,6418,6436,6439,6442,6460,6463,6466,6484,6487,6490,6508,6511,6514,6532,6535,6538,6556,6559,6562,6580,6583,6586,6604,6607,6610,6628,6631,6634,7072,7075,7078,7096,7099,7102,7120,7123,7126,7144,7147,7150,7168,7171,7174,7192,7195,7198,7216,7219,7222,7240,7243,7246,7264,7267,7270,7288,7291,7294,7312,7315,7318,7336,7339,7342,7360,7363,7366,7384,7387,7390,7408,7411,7414,7432,7435,7438,7456,7459,7462
build/numpy/random/_bounded_integers.cpython-313-x86_64-linux-gnu.so.p/numpy/random/_bounded_integers.pyx.c
                                            9698    7875    81%   671-672,1167-1168,3583-3586,3633-3636,4010,4019-4025,4034-4035,4037-4041,4043-4045,4047,4056-4061,4076-4083,4682-4687,4800-4806,4930-4935,4951,4982-4987,5002-5007,5023-5028,5178-5183,5199,5227-5232,5247-5252,5268-5273,5339-5344,5359-5364,5474-5479,5545-5550,5629-5634,5786-5788,5954-5959,5975,6006-6011,6026-6031,6047-6052,6202-6207,6223,6251-6256,6271-6276,6292-6297,6363-6368,6383-6388,6498-6503,6569-6574,6653-6658,6810-6812,6978-6983,6999,7030-7035,7050-7055,7071-7076,7226-7231,7247,7275-7280,7295-7300,7316-7321,7387-7392,7407-7412,7522-7527,7593-7598,7677-7682,7834-7836,8002-8007,8023,8054-8059,8074-8079,8095-8100,8250-8255,8271,8299-8304,8319-8324,8340-8345,8411-8416,8431-8436,8546-8551,8617-8622,8701-8706,8858-8860,9026-9031,9047,9078-9083,9098-9103,9119-9124,9274-9279,9295,9323-9328,9343-9348,9364-9369,9435-9440,9455-9460,9570-9575,9641-9646,9725-9730,9882-9884,10050-10055,10071,10102-10107,10122-10127,10143-10148,10298-10303,10319,10347-10352,10367-10372,10388-10393,10459-10464,10479-10484,10594-10599,10665-10670,10749-10754,10906-10908,11074-11079,11095,11126-11131,11146-11151,11167-11172,11322-11327,11343,11371-11376,11391-11396,11412-11417,11483-11488,11503-11508,11618-11623,11689-11694,11773-11778,11930-11932,12092-12097,12161-12166,12340-12345,12409-12414,12686-12691,12706-12711,12791-12796,12862-12867,12946-12951,13103-13105,13265-13270,13334-13339,13513-13518,13582-13587,13731-13734,13736-13741,13743-13745,13859-13864,13879-13884,13964-13969,14035-14040,14119-14124,14276-14278,14395-14400,14438-14443,14498-14503,14537-14542,14826-14831,14882-14884,14907-14912,14960-14965,15018-15023,15089-15091,15226-15231,15269-15274,15329-15334,15368-15373,15657-15662,15713-15715,15738-15743,15791-15796,15849-15854,15920-15922,16057-16062,16100-16105,16160-16165,16199-16204,16488-16493,16544-16546,16569-16574,16622-16627,16680-16685,16751-16753,16888-16893,16931-16936,16991-16996,17030-17035,17319-17324,17375-17377,17400-17405,17453-17458,17511-17516,17582-17584,17719-17724,17762-17767,17822-17827,17861-17866,18150-18155,18206-18208,18231-18236,18284-18289,18342-18347,18413-18415,18551-18556,18594-18599,18654-18659,18693-18698,18982-18987,19038-19040,19063-19068,19116-19121,19174-19179,19245-19247,19383-19388,19426-19431,19486-19491,19525-19530,19814-19819,19870-19872,19895-19900,19948-19953,20006-20011,20077-20079,20215-20220,20258-20263,20318-20323,20357-20362,20646-20651,20702-20704,20727-20732,20780-20785,20838-20843,20909-20911,21047-21052,21090-21095,21150-21155,21189-21194,21478-21483,21534-21536,21559-21564,21612-21617,21670-21675,21741-21743,21876-21879,22083-22086,22225-22226,22229,22243-22244,22258,22271-22273,22294-22296,22351,22356,22421-22425,22428,22438-22439,22441,22494-22496,22532-22533,22544-22545,22551,22697-22701,22720,22722-22727,22755-22759,22761-22762,22766-22768,22770-22773,22782-22783,22785,22796,22801,22803,22805-22806,22821-22824,22839-22844,22848,22850-22855,22873-22875,22884,22903,22909,22919-22924,22926-22929,22985,22989,23024,23079,23081,23084,23087,23089,23093-23099,23101-23102,23109-23113,23116-23125,23129,23133,23135,23138-23139,23141-23147,23149,23152,23154,23159,23187,23200-23201,23203-23204,23221-23224,23227,23287,23289,23295,23315,23331,23333,23340,23354-23357,23382-23383,23387-23389,23392-23394,23406,23410-23411,23450-23454,23501-23502,23504-23505,23510-23512,23528-23532,23534,23536,23539,23547-23549,23561-23568,23570,23572,23575,23589-23591,23595-23597,23600-23601,23605-23607,23615-23616,23688-23692,23694-23695,23705-23706,23708,23722,23724,23727-23729,23740,23742,23745-23747,23765,23767,23770,23798,23804,23808,23811-23812,23816,23819,23823,23827-23829,23842,23845,23848-23850,23900-23905,23921,23923-23925,23927-23930,23938-23939,23942,23955-23956,23959-23960,23964-23965,23967-23968,23971-23972,23979-23984,23986-23993,24006,24009-24012,24014-24016,24025-24028,24030-24033,24038-24039,24042-24045,24185-24189,24192-24195,24198-24199,24313-24316,24321-24323,24342-24345,25180-25185,25190,25237,25412-25413,25415,25499-25504,25573-25575,25582-25584,25749-25754,25759,25802-25803,25805-25806,25809-25810,25977-25978,25980-25982,25984,26068-26073,26078,26082-26084,26121-26122,26124-26125,26128-26129,26296-26297,26299-26301,26303,26387-26392,26397,26401-26403,26440-26441,26443-26444,26447-26448,26615-26616,26618-26620,26622,26706-26711,26716,26720-26722,26759-26760,26762-26763,26766-26767,26934-26935,26937-26939,26941,27094-27099,27224-27225,27322-27323,27325,27413-27418,27483-27485,27543-27544,27641-27642,27644,27732-27737,27802-27804,27862-27863,27960-27961,27963,28650-28652,28655,28660-28665,28688-28689,28692,28695-28700,28702-28705,28711-28717,28721,28817,28820-28821,28826,28829,28831,28879-28880,28888-28889,28893-28895,28998-29001,29006-29008,29013,29016-29017,29020,29022,29024-29026,29028-29030,29037-29039,29042-29043
build/numpy/random/_common.cpython-313-x86_64-linux-gnu.so.p/numpy/random/_common.pyx.c
                                            9544    6095    63%   
  • Is there a way to get the link into the CI summary, like the ci/circleci: build artifact?
  • Is there a way to get a nicer rendering of the report?
  • Is there a way to compare the report to main, or to a stored version of the main CI run, and only show the delta? Would that be too slow?

@ganesh-k13

Copy link
Copy Markdown
Member Author

Is there a way to get the link into the CI summary, like the ci/circleci: build artifact?

This is a good point, let me see if we can get it readable directly from the PR page somehow through a published link.

Is there a way to get a nicer rendering of the report?

There are multiple formats today and even directory upload works, so maybe we can somehow get HTML to work. Let me try it out

Is there a way to compare the report to main, or to a stored version of the main CI run, and only show the delta? Would that be too slow?

There are other packages like diff-cover that can run as a parallel job. There should be some elegant way of doing it that's not too slow. I think this would be of most use for maintainers to check before merging a PR, will look into this as well.

Thanks for the comments!

@mattip

mattip commented Mar 3, 2026

Copy link
Copy Markdown
Member

Thanks. This is all a bit experimental, so i expect some of the answers will be “nope, can’t do that”

@agriyakhetarpal

agriyakhetarpal commented Mar 3, 2026

Copy link
Copy Markdown
Contributor
  • Is there a way to get the link into the CI summary, like the ci/circleci: build artifact?

This is a good point, let me see if we can get it readable directly from the PR page somehow through a published link.


Is there a way to get a nicer rendering of the report?

There are multiple formats today and even directory upload works, so maybe we can somehow get HTML to work. Let me try it out

Get clickable link in homepage of PR

Get a more readable format like HTML/PDF

I've written and published a GitHub Action designed for exactly this use case just a couple of days ago (it works with actions/upload-artifact@v7 and later – the linked issue is where I stumbled upon this PR from!): https://github.com/agriyakhetarpal/github-actions-artifacts-redirector-action. It should work well for HTML/PDF reports, or even text files.

@ganesh-k13

ganesh-k13 commented Mar 10, 2026

Copy link
Copy Markdown
Member Author

Diff cover seems to work (for Python): https://github.com/numpy/numpy/actions/runs/22886825193/artifacts/5842973779. Added a tmp commit to test: 060f220. In case of missing lines, we get more details like this:

# Diff Coverage
## Diff: origin/main...HEAD, staged and unstaged changes

- numpy/lib/_version.py (0.0%): Missing lines 95-96

## Summary

- **Total**: 2 lines
- **Missing**: 2 lines
- **Coverage**: 0%



## numpy/lib/_version.py

Lines 91-100


   91             vercmp = 1
   92         else:
   93             vercmp = -1
   94
!  95         if vercmp == 1:
!  96             print("hello")
   97
   98         return vercmp
   99
  100     def _compare_pre_release(self, other):

---

@mattip

mattip commented Mar 10, 2026

Copy link
Copy Markdown
Member

I am not a big fan of including an action that needs write privileges. That is why suggest that we get a nice console based story before thinking about adding it to CI

@ganesh-k13

Copy link
Copy Markdown
Member Author

@mattip what does console-based mean in this context?

@mattip

mattip commented Mar 10, 2026

Copy link
Copy Markdown
Member

Getting a local run of spin coverage to show something meaningful.

Maybe helpful to take a step back. What exactly would be a user story for the coverage information in practice? Has there been discussion recently asking for coverage? I can see some usages: do tests cover all the code paths in my recent commits? Do I have dead code? But neither of those require the use of CI. How can we get a good tool for the use cases people might care about?

@ganesh-k13

Copy link
Copy Markdown
Member Author

Ahh got it. I always wanted to know if I have ~100% of my newly added code for each PR in C or Python.

An additional usecase as you mentioned might be to find dead code, but that can be done easily by: spin test --coverage && firefox build/coverage/index.html

In case of the first requirement, it would be good to show coverage in the PR for maintainers to ask the OPs specific tests to add for someone new

@agriyakhetarpal

Copy link
Copy Markdown
Contributor

I am not a big fan of including an action that needs write privileges.

@mattip the write privilege should only be required for statuses, not for code/issues/etc. FWIW https://github.com/scientific-python/circleci-artifacts-redirector-action also needs the same write status privileges. It's a bit of a GitHub Actions limitation (or you could call it a design choice), but the action won't work until the workflow file is committed to the main branch, so I'd suggest not adding it in this PR for now and doing so in a later PR.

@mattip

mattip commented Mar 10, 2026

Copy link
Copy Markdown
Member

FWIW https://github.com/scientific-python/circleci-artifacts-redirector-action also needs the same write status privileges.

Just because we have one problematic action doesn't mean we like it.

I always wanted to know if I have ~100% of my newly added code for each PR in C or Python.
it would be good to show coverage in the PR for maintainers

Hmm. Maybe some other reviewers could add more opinions, but when we had it, I rarely looked at the coverage report.

@ganesh-k13

Copy link
Copy Markdown
Member Author

Maybe some other reviewers could add more opinions

Let me start a thread in the mailing list.

@seberg

seberg commented Mar 10, 2026

Copy link
Copy Markdown
Member

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants