Skip to content

Make the MsTest source generator emit an override modifier when the base class has a TestContext property#1440

Merged
SimonCropp merged 3 commits intoVerifyTests:mainfrom
m-ringler:main
Apr 21, 2025
Merged

Make the MsTest source generator emit an override modifier when the base class has a TestContext property#1440
SimonCropp merged 3 commits intoVerifyTests:mainfrom
m-ringler:main

Conversation

@m-ringler
Copy link
Contributor

@m-ringler m-ringler commented Apr 16, 2025

When a base class of the TestClass already has a TestContext property this PR makes the source generator emit an override keyword on the TestContext property that it generates.

  • When the base class property is virtual, the resulting code will compile.
  • When the base class property is non-virtual, this will lead to a CS0506 compiler error (instead of CS0108). I think that is the more helpful behavior, as we now show the developer how to solve the problem.

The behavior is unchanged when a TestContext property is declared in the TestClass itself.

Fixes #1437

@m-ringler m-ringler marked this pull request as ready for review April 16, 2025 10:19
@m-ringler
Copy link
Contributor Author

@dotnet-policy-service agree company="Zeiss"

@SimonCropp
Copy link
Member

@MattKotsenas got time to do a review?

@MattKotsenas
Copy link
Contributor

This looks fine to me, however supporting this scenario brings up caveats that are worth thinking through.

Consider code like this:

public class BaseClass
{
    protected TestContext _testContext = null!;
    public virtual TestContext TestContext { get { return _testContext; } set { _testContext = value; } }
}

[TestClass]
[UsesVerify]
public partial class TestClass : BaseClass
{
}

BaseClass might expect that _testContext is set by inheritors, however our partial method won't know to do that. So, if BaseClass only ever uses the property, things are fine. But if it uses the field, things will be broken.

This gets more confusing if you add a third class to the mix:

[TestClass]
public class TestClass2 : TestClass
{
    public override TestContext TestContext { get; set; }
}

without the additional TestContext property this inheritence hierarchy works fine. Prior to this change, adding the override results in CS0506. After this change, it compiles but fails at runtime with System.Exception: TestContext is null. Ensure test class has a [UsesVerify]attribute (or inherits fromVerifyBase).

It's probably on balance an OK change to take, as I doubt many people are doing tricky things with the TestContext, but it's perhaps worth calling out in the docs?

@m-ringler
Copy link
Contributor Author

m-ringler commented Apr 17, 2025

We could mitigate the 1st scenario by also calling the base setter in the generated setter.

We could mitigate the 2nd scenario by sealing the overridden TestContext property.

What do you think?

@SimonCropp
Copy link
Member

@MattKotsenas thoughts?

@MattKotsenas
Copy link
Contributor

I didn't realize you could mark a single method as sealed!

Both seem like good additions to prevent accidental misuse.

@m-ringler , are you willing to try adding both to this PR?

@m-ringler
Copy link
Contributor Author

Yes, I will.

@m-ringler
Copy link
Contributor Author

@MattKotsenas, @SimonCropp
I've made the two changes we discussed.
I've also updated the VerifyGenerator method to check that there are no diagnostics when expectedDiagnostics is null or empty.

Copy link
Contributor

@MattKotsenas MattKotsenas left a comment

Choose a reason for hiding this comment

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

LGTM. Left 1 item for code style, but no other concerns from my end. Thanks for this!

static IEnumerable<IPropertySymbol> BaseTestContextProperties(
INamedTypeSymbol typeSymbol)
=>
from baseClass in BaseClassesOf(typeSymbol)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think this is the only place in the codebase to use the query-style syntax. It's up to @SimonCropp but I'd assume you want method-style for consistency.

Copy link
Member

Choose a reason for hiding this comment

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

i do prefer method-style. but i can fix that after merge

@SimonCropp
Copy link
Member

@m-ringler thanks for this. i will deploy it now

@SimonCropp SimonCropp added this to the 29.3.0 milestone Apr 21, 2025
@SimonCropp SimonCropp merged commit 8fdc279 into VerifyTests:main Apr 21, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

MSTest source generator causes conflicts with TestContext property defined in test base class

3 participants