Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring back more fine-grained code coverage targeting #5175

Closed
jnoordsij opened this issue Feb 6, 2023 · 18 comments
Closed

Bring back more fine-grained code coverage targeting #5175

jnoordsij opened this issue Feb 6, 2023 · 18 comments
Assignees
Labels
feature/code-coverage Issues related to code coverage (but not php-code-coverage) feature/metadata/attributes type/enhancement A new idea that should be implemented
Milestone

Comments

@jnoordsij
Copy link
Contributor

jnoordsij commented Feb 6, 2023

In PHPUnit 10.0, attributes were added to (optionally) replace code comment annotations (great feature btw!). However, these are currently limited only to apply to classes, where previously covers attributes were allowed to be on methods as well.

It would be fruitful for some usecases (as mentioned in various comments below) to allow for more fine-grained coverage measurement; in particular to allow targetting (class) methods by name using attributes.

Note: if this is an intentional change, and there is no plan to actively support this anymore, maybe this should be turned into two other issues:

  • add a deprecation message for covers attributes on methods
  • an issue on the Rector Rules repository to not automatically convert method-based covers annotations into attributes, as it will result into a broken tests suite (Attribute "PHPUnit\Framework\Attributes\CoversClass" cannot target method (allowed targets: class))
@jnoordsij jnoordsij added the type/enhancement A new idea that should be implemented label Feb 6, 2023
@jnoordsij jnoordsij changed the title Allow CoversX attributes to be applied to class methods Allow CoversX attributes to be applied to test class methods Feb 6, 2023
@sebastianbergmann sebastianbergmann removed the type/enhancement A new idea that should be implemented label Feb 6, 2023
@sebastianbergmann
Copy link
Owner

This is intentional and explained in #4502.

@jnoordsij
Copy link
Contributor Author

Thanks for pointing me there! I've raised rectorphp/rector-phpunit#149 to highlight this issue there.

I think a separate deprecation for method-based annotations is probably not be needed, as this will be covered by deprecating all annotations in #4505. However it might be worth adding a somewhat more extended migration guide at that point, with some pointers on how to replace method-based annotations with class-based attributes.

@kylekatarnls
Copy link

This is intentional and explained in #4502.

I see it's intentional and noted "not recommended because too fine-grained"

But I'm searching with no luck where this design choice is explained. I've cases similar to #5558 (comment) where it's relevant to avoid a method to be unintentionally covered.

There I can't find any good reason why it would be bad to be too fine-grained in cover targeting.

Any reading you can recommend @sebastianbergmann to learn why we should not to that and then how we prevent accidental coverage of a method?

@mattvb91
Copy link

mattvb91 commented Jan 26, 2024

This is a crazy change to remove being able to cover methods directly... Defeats the whole purpose of having @covers in the first place...

Any recommendations on how to get targeted coverage results back?

@jrfnl
Copy link
Contributor

jrfnl commented Feb 26, 2024

I'm struggling with the same thing as everyone else in this thread.

Yes, of course, everyone should be using SOLID OO and classes should only have one responsibility and in an ideal world, using CoversClass would work brilliantly.

Except I do not live in such an ideal world. I live in a world of legacy code, where there are plenty of classes which do too much and where I want to know exactly what code (i.e. what method(s)) is covered by dedicated tests (vs incidentally covered) to know whether it is safe to refactor that code (preferably to more SOLID code).

Unfortunately, that will no longer be possible, which makes adding Covers* attributes at all, basically useless, as it no longer prevents unintentional code coverage from being recorded.

@sebastianbergmann Please, please, please reconsider this design choice, as CoversClass is next to useless for real world situations.

@sebastianbergmann
Copy link
Owner

Do you only want targetting methods back or do you also want to be able to use coverage target attributes on test methods in addition to test classes?

@jrfnl
Copy link
Contributor

jrfnl commented Feb 26, 2024

Do you only want targetting methods back or do you also want to be able to use coverage target attributes on test methods in addition to test classes?

@sebastianbergmann For me, the most important part is being able to target methods.

I don't have a problem with splitting up test classes which were targeting multiple different units of code to multiple test classes, each targeting just one unit of code.

Splitting test classes is not a breaking change, just busy-work while I have better things to do, but I can deal with that.
Having to refactor large parts of the code base under test just to be able to see what code is covered by tests, that's a whole other matter due to the breaking changes in the public API that would involve.

@sebastianbergmann sebastianbergmann changed the title Allow CoversX attributes to be applied to test class methods Bring back more fine-grained code coverage targetting Feb 26, 2024
@sebastianbergmann sebastianbergmann self-assigned this Feb 26, 2024
@sebastianbergmann sebastianbergmann added type/enhancement A new idea that should be implemented feature/code-coverage Issues related to code coverage (but not php-code-coverage) feature/metadata/attributes labels Feb 26, 2024
@sebastianbergmann sebastianbergmann added this to the PHPUnit 11.1 milestone Feb 26, 2024
@jrfnl
Copy link
Contributor

jrfnl commented Feb 26, 2024

@sebastianbergmann Looking at the tags and milestoning you've just done, I take it you are considering this. Should the ticket be re-opened ?

@jrfnl
Copy link
Contributor

jrfnl commented Feb 26, 2024

@sebastianbergmann As a side-note: I was wondering how to deal with Covers attributes vs namespaced functions.

The CoversFunction attribute is documented to only support global functions.
I haven't tested it, but hope it supports namespaced functions too ?

@sebastianbergmann
Copy link
Owner

sebastianbergmann commented Feb 26, 2024

I haven't tested it, but hope it supports namespaced functions too?

It should. :) And according to this test it does.

@mattvb91
Copy link

Just a quick thank you to @sebastianbergmann for putting this change back in. Im in the exact same boat as @jrfnl where im working on a legacy codebase and the issue is exactly that its super chaotic in that there is a ton of global superclasses that hold a ton of functionality that I am in the process of splitting up and refactoring to individual classes so the @covers is essential in helping out what has already been tested and can be moved.

@mfn
Copy link

mfn commented Feb 26, 2024

legacy codebase

I hate to "out myself", but I work on what I consider a more modern codebase and I find it still very useful to have.

@sebastianbergmann sebastianbergmann changed the title Bring back more fine-grained code coverage targetting Bring back more fine-grained code coverage targeting Feb 27, 2024
@mfn
Copy link

mfn commented Feb 27, 2024

HOLY 🐮

I gave up on this… this makes me so happy to see this back.

Thank you @sebastianbergmann , this is really really appreciated (also 🙇🏼 to those who argued in favor, thank you too 🙏🏼 )

@kylekatarnls
Copy link

A big thank you @sebastianbergmann for this attribute port of the method annotations :) we're lucky to have you in the PHP community 🥇

@jrfnl
Copy link
Contributor

jrfnl commented Feb 27, 2024

@sebastianbergmann Joining the others in saying: Thank you! I'm very happy to see that this will be brought back.

On a practical note: I presume this will only be introduced in PHPUnit 11.1 ?

For those of us who need to use a range of PHPUnit versions to runs the tests, am I correct in saying those projects should then require "phpunit/phpunit": "^8.0 || ^9.0 || ^11.1", effectively skipping PHPUnit 10 ? As 10.x will not support this attribute - and I presume will not read the @covers annotation if it finds other attributes on the class ?

@sebastianbergmann
Copy link
Owner

I presume this will only be introduced in PHPUnit 11.1?

This will not be backported to PHPUnit 10, correct.

I presume will not read the @covers annotation if it finds other attributes on the class?

PHPUnit 10 and PHPUnit 11 support metadata in annotations and attributes. If an attribute is found on a unit of code, annotations on that unit of code are ignored.

am I correct in saying those project should then require "phpunit/phpunit": "^8.0 || ^9.0 || ^11.1", effectively skipping PHPUnit 10?

Yes.

@jrfnl
Copy link
Contributor

jrfnl commented Feb 27, 2024

@sebastianbergmann Thank you for confirming.

@miken32
Copy link

miken32 commented Apr 22, 2024

@sebastianbergmann you asked:

Do you only want targeting methods back or do you also want to be able to use coverage target attributes on test methods in addition to test classes?

Was there an intentional choice to only allow the CoversMethod attribute to be applied to classes? I have always used the old @covers annotation on each test method. Is there a compelling reason not to have the attribute definition contain this?

#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]

The workaround is fairly simple: having multiple CoversMethod attributes on the class and indicating in comments or elsewhere which method the test method is covering. I'm just wondering why a workaround is needed at all, or if this was an oversight in the attribute definition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/code-coverage Issues related to code coverage (but not php-code-coverage) feature/metadata/attributes type/enhancement A new idea that should be implemented
Projects
None yet
Development

No branches or pull requests

7 participants