-
Notifications
You must be signed in to change notification settings - Fork 33
Adjust NUnit1029 to account for TestCaseSource support for params and optional arguments #958
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
base: master
Are you sure you want to change the base?
Conversation
|
@manfred-brands @mikkelbu I've made this as a draft already as it's most of the way there, however I have very little experience with the analyzers and am encountering an issue. There's a failing test, |
|
Ok I think I'm making a bit more headway here. I think I've moved past my issue and I'll continue chipping away at this. |
Just when I was going to have a look, now I can just sit and wait. |
a2f6b2d to
4955308
Compare
No testcasesource warnings for optional or params are present
4955308 to
eb23a58
Compare
|
I think this is ready for review. I ended up avoiding generic method scenarios since it looks like the existing code also option to avoid explicit type inference + validation for those cases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adjusts the NUnit1029 analyzer to properly handle TestCaseSource usage with params arrays and optional parameters. The analyzer now correctly accounts for methods that can accept a variable number of arguments through params or optional parameters, preventing false positive warnings.
Key Changes:
- Modified parameter count validation to include params parameters in the analysis
- Restructured the validation logic to allow methods with optional or params parameters to accept TestCaseSource data
- Added comprehensive test coverage for params arrays, optional parameters, and generic methods
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| TestCaseSourceUsesStringAnalyzer.cs | Updated parameter counting logic to include params parameters and restructured validation to handle optional/params scenarios |
| TestCaseSourceUsesStringAnalyzerTests.cs | Added four new test cases covering params arrays, generic methods, and optional parameters |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | ||
| } | ||
|
|
||
| [TestCaseSource(↓nameof(TestData))] | ||
| public void ShortName(int a = 1, int b = 2) | ||
| { | ||
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); |
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable 'x' does not exist in this scope. The parameters are named 'a' and 'b', not 'x'.
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | |
| } | |
| [TestCaseSource(↓nameof(TestData))] | |
| public void ShortName(int a = 1, int b = 2) | |
| { | |
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | |
| Assert.That(a, Is.GreaterThanOrEqualTo(0)); | |
| Assert.That(b, Is.GreaterThanOrEqualTo(0)); | |
| } | |
| [TestCaseSource(↓nameof(TestData))] | |
| public void ShortName(int a = 1, int b = 2) | |
| { | |
| Assert.That(a, Is.GreaterThanOrEqualTo(0)); | |
| Assert.That(b, Is.GreaterThanOrEqualTo(0)); |
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | ||
| } | ||
|
|
||
| [TestCaseSource(↓nameof(TestData))] | ||
| public void ShortName(int a = 1, int b = 2) | ||
| { | ||
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); |
Copilot
AI
Nov 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable 'x' does not exist in this scope. The parameters are named 'a' and 'b', not 'x'.
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | |
| } | |
| [TestCaseSource(↓nameof(TestData))] | |
| public void ShortName(int a = 1, int b = 2) | |
| { | |
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | |
| Assert.Pass(); | |
| } | |
| [TestCaseSource(↓nameof(TestData))] | |
| public void ShortName(int a = 1, int b = 2) | |
| { | |
| Assert.Pass(); |
manfred-brands
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some small remarks on the use of RoslynAssert.
Your example test code didn't get to the analyzer as there were compile errors.
I pushed the necessary fixes up, but the underlying test code doesn't work when run in NUnit 4.4.0.
I'm trying it now on master and see if it is related to the bug you raised
| [TestCaseSource(↓nameof(TestData))] | ||
| public void ShortName(int a, int b = 2) | ||
| { | ||
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised this compiles during testing as there is no x variable.
| [TestCaseSource(↓nameof(TestData))] | ||
| public void ShortName(int a = 1, int b = 2) | ||
| { | ||
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate function with same name and parameters. should also not compile.
| } | ||
| }", additionalUsings: "using System.Collections.Generic;"); | ||
|
|
||
| RoslynAssert.NoAnalyzerDiagnostics(analyzer, testCode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might explain it.
I thought we always used RoslynAssert.Valid to ensure the code is correct.
| [TestFixture] | ||
| public class NoWarningWhenNumberOfParametersOfTestWillFitIntoOptionalParams | ||
| { | ||
| [TestCaseSource(↓nameof(TestData))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the code is valid, there should be no ↓ character which otherwise indicates the expect error location.
| [TestFixture] | ||
| public class NoWarningWhenNumberOfParametersOfTestWillFitIntoParamsArrayForGenericMethod | ||
| { | ||
| [TestCaseSource(↓nameof(TestData))] | ||
| public void ShortName<T>(params T[] x) | ||
| { | ||
| Assert.That(x.Length, Is.GreaterThanOrEqualTo(0)); | ||
| } | ||
|
|
||
| static IEnumerable<int> TestData() | ||
| { | ||
| for (int i = 1; i <= 3; i++) | ||
| { | ||
| yield return i; | ||
| } | ||
| } | ||
| }", additionalUsings: "using System.Collections.Generic;"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NUnit itself fails to run this test with Unable to determine type arguments for method.
I always extract the code from the string to see if NUnit will actually run it.
| [TestCaseSource(↓nameof(TestData))] | ||
| public static void TestLotsOfNonRequiredParams(params int[] z) | ||
| { | ||
| Assert.That(z, Is.Not.Default); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default does not exist in NUnit 3.14. The analyzer test run against both 3.14 and 4.4
Also Default for an array is the same as Null, but a params array should never be null.
|
Thanks @manfred-brands ! Appreciate your fixes here. I mentioned that I am new on the analyzer side.
I hadn't realized this was the case but I can see now why we would want to. I suppose my using |
No. Only the tests that have Please revert your last commit! |
23522b6 to
3028d64
Compare
|
Done. Sorry about that, thanks for the clarification |
|
@manfred-brands Thanks for the review here. |
| { | ||
| // more than one required parameter is always a mismatch | ||
| // zero parameters of any kind is also a mismatch | ||
| context.ReportDiagnostic(Diagnostic.Create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a new test case that validates this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @manfred-brands
Do you mean this comment?
// more than one required parameter is always a mismatch
// zero parameters of any kind is also a mismatch
That comment was added by me to clarify the existing logic for myself prior to and after refactoring the logic a bit. I had thought they're already covered through existing tests here:
Lines 658 to 659 in 3028d64
[TestCaseSource(↓nameof(TestData), new object[] { 3 })] public void ShortName() Lines 686 to 687 in 3028d64
[TestCaseSource(↓nameof(TestData))] public void ShortName(int x, int y)
Unless, would you prefer additional cases with 0 and two required args which also include optional args in the signature like this?
[TestCaseSource(↓nameof(TestData))]
public void ShortName(int x, int y, int z = 2)
Fixes #957