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

Added new rule MiKo_3122 that reports tests having more than 2 parameters #1024

Merged
merged 1 commit into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MiKo.Analyzer.Shared/Extensions/SyntaxTokenExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ internal static SyntaxToken WithLeadingEmptyLines(this SyntaxToken value, int li
var indicesToRemove = new Stack<int>();

var count = trivia.Count;

for (var index = 0; index < count; index++)
{
var t = trivia[index];
Expand Down
1 change: 1 addition & 0 deletions MiKo.Analyzer.Shared/MiKo.Analyzer.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3119_TestMethodsDoNotReturnCompletedTaskAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3120_UseValueInsteadOfItIsConditionMatcherAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3121_ObjectUnderTestIsNoInterfaceAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3201_InvertIfWhenFollowedByFewCodeLinesAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3202_InvertNegativeIfWhenReturningOnAllPathsAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Rules\Maintainability\MiKo_3203_InvertNegativeIfInsideBlockWhenFollowedBySingleCodeLinesAnalyzer.cs" />
Expand Down
27 changes: 27 additions & 0 deletions MiKo.Analyzer.Shared/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions MiKo.Analyzer.Shared/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4382,6 +4382,15 @@ Otherwise, when attempting to jump into the code, developers just end up at the
<data name="MiKo_3121_Title" xml:space="preserve">
<value>Tests should test concrete implementations and no interfaces</value>
</data>
<data name="MiKo_3122_Description" xml:space="preserve">
<value>Test methods using more than 2 parameters most likely are combined tests. Such test are hard to read. Hence, to ease reading, these tests should be split into separate ones.</value>
</data>
<data name="MiKo_3122_MessageFormat" xml:space="preserve">
<value>Split into multiple tests so that you do not need more than 2 parameters</value>
</data>
<data name="MiKo_3122_Title" xml:space="preserve">
<value>Test methods should not use more than 2 parameters</value>
</data>
<data name="MiKo_3201_CodeFixTitle" xml:space="preserve">
<value>Invert if to simplify</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace MiKoSolutions.Analyzers.Rules.Maintainability
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzer : MaintainabilityAnalyzer
{
public const string Id = "MiKo_3122";

public MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzer() : base(Id)
{
}

protected override bool IsUnitTestAnalyzer => true;

protected override bool ShallAnalyze(IMethodSymbol symbol) => symbol.IsTestMethod();

protected override IEnumerable<Diagnostic> Analyze(IMethodSymbol symbol, Compilation compilation)
{
if (symbol.Parameters.Length > 2)
{
var syntax = symbol.GetSyntax<MethodDeclarationSyntax>();

yield return Issue(syntax.ParameterList);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ protected override SyntaxNode GetUpdatedSyntax(Document document, SyntaxNode syn
{
case IdentifierNameSyntax identifier:
nodes.Add(identifier);

break;

case BaseExpressionSyntax _:
nodes.Add(expression.Parent);

break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using Microsoft.CodeAnalysis.Diagnostics;

using NUnit.Framework;

using TestHelper;

//// ncrunch: rdi off
namespace MiKoSolutions.Analyzers.Rules.Maintainability
{
[TestFixture]
public sealed class MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzerTests : CodeFixVerifier
{
[Test]
public void No_issue_is_reported_for_non_test_method_with_3_parameters() => No_issue_is_reported_for(@"
using System;

namespace Bla
{
public class TestMe
{
public void DoSomething(int a, int b, int c) { }
}
}
");

[Test]
public void No_issue_is_reported_for_test_method_with_0_parameters() => No_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[Test]
public void SomeTest() { }
}
}
");

[Test]
public void No_issue_is_reported_for_test_method_with_1_parameter() => No_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[Test]
public void SomeTest([Values(42)] int a) { }
}
}
");

[Test]
public void No_issue_is_reported_for_test_method_with_2_parameters() => No_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[Test]
public void SomeTest([Values(1)] int a, [Values(2)] int b) { }
}
}
");

[Test]
public void An_issue_is_reported_for_test_method_with_3_parameters() => An_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[Test]
public void SomeTest([Values(1)] int a, [Values(2)] int b, [Values(3)] int c) { }
}
}
");

[Test]
public void No_issue_is_reported_for_test_case_method_with_1_parameter() => No_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[TestCase(42)]
public void SomeTest(int a) { }
}
}
");

[Test]
public void No_issue_is_reported_for_test_case_method_with_2_parameters() => No_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[TestCase(1, 2)]
public void SomeTest(int a, int b) { }
}
}
");

[Test]
public void An_issue_is_reported_for_test_case_method_with_3_parameters() => An_issue_is_reported_for(@"
using System;

using NUnit.Framework;

namespace Bla
{
[TestFixture]
public class TestMe
{
[TestCase(1, 2, 3)]
public void SomeTest(int a, int b, int c) { }
}
}
");

protected override string GetDiagnosticId() => MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzer.Id;

protected override DiagnosticAnalyzer GetObjectUnderTest() => new MiKo_3122_TestMethodsDoNotHaveMultipleParametersAnalyzer();
}
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Screenshots on how to use such analyzers can be found [here](https://learn.micro
[![Build history](https://buildstats.info/appveyor/chart/RalfKoban/miko-analyzers)](https://ci.appveyor.com/project/RalfKoban/miko-analyzers/history)

## Available Rules
The following tables lists all the 459 rules that are currently provided by the analyzer.
The following tables lists all the 460 rules that are currently provided by the analyzer.

### Metrics
|ID|Title|Enabled by default|CodeFix available|
Expand Down Expand Up @@ -395,6 +395,7 @@ The following tables lists all the 459 rules that are currently provided by the
|MiKo_3119|Test methods should not simply return completed task|&#x2713;|&#x2713;|
|MiKo_3120|Moq mocks should use values instead of 'It.Is&lt;&gt;(...)' condition matcher to verify exact values|&#x2713;|&#x2713;|
|MiKo_3121|Tests should test concrete implementations and no interfaces|&#x2713;|\-|
|MiKo_3122|Test methods should not use more than 2 parameters|&#x2713;|\-|
|MiKo_3201|If statements can be inverted in short methods|&#x2713;|&#x2713;|
|MiKo_3202|Use positive conditions when returning in all paths|&#x2713;|&#x2713;|
|MiKo_3203|If-continue statements can be inverted when followed by single line|&#x2713;|&#x2713;|
Expand Down