Skip to content

Commit

Permalink
Merge pull request #537 from manfred-brands/issue-344
Browse files Browse the repository at this point in the history
Within usage analyzer + tests + codefix
  • Loading branch information
manfred-brands authored May 2, 2023
2 parents 205e92f + 6dd8ddd commit 6c49665
Show file tree
Hide file tree
Showing 12 changed files with 712 additions and 1 deletion.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ dotnet_style_collection_initializer = true:none
dotnet_style_coalesce_expression = true:warning
dotnet_style_null_propagation = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning

# Expression-bodied members
csharp_style_expression_bodied_accessors = when_on_single_line:warning
Expand Down Expand Up @@ -131,6 +132,12 @@ dotnet_naming_rule.parameters_and_locals.severity = warning
dotnet_naming_rule.parameters_and_locals.symbols = parameters_and_locals
dotnet_naming_rule.parameters_and_locals.style = camel_case

##################################################################################
# IDE Code Style Analyzers

# IDE0041: Use 'is null' check
dotnet_diagnostic.IDE0041.severity = warning

# IDE0046: Convert to conditional expression
# Complex Conditional expressions are not easier to read
dotnet_diagnostic.IDE0046.severity = none
Expand Down Expand Up @@ -237,3 +244,11 @@ dotnet_diagnostic.CA1310.severity = error
# Default severity for analyzer diagnostics with category 'MicrosoftCodeAnalysisReleaseTracking'
dotnet_analyzer_diagnostic.category-MicrosoftCodeAnalysisReleaseTracking.severity = none

##################################################################################
# CSharpIsNull Analyzers

# CSIsNull001: Use `is null` for null checks
dotnet_diagnostic.CSIsNull001.severity = warning

# CSIsNull002: Use `is object` for non-null checks
dotnet_diagnostic.CSIsNull002.severity = warning
96 changes: 96 additions & 0 deletions documentation/NUnit2047.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# NUnit2047

## Incompatible types for Within constraint

| Topic | Value
| :-- | :--
| Id | NUnit2047
| Severity | Warning
| Enabled | True
| Category | Assertion
| Code | [WithinUsageAnalyzer](https://github.com/nunit/nunit.analyzers/blob/master/src/nunit.analyzers/WithinUsage/WithinUsageAnalyzer.cs)

## Description

The `Within` modifier should only be used for numeric or Date/Time arguments or tuples containing only these element types. Using it on other types will not have any effect.

## Motivation

To bring developers' attention to a scenario in which their code is actually having no effect and may reveal that their test is not doing what they expect.

## How to fix violations

### Example Violation

```csharp
[Test]
public void RecordsEqualsMismatch()
{
var a = new Data(1, 1.0);
var b = new Data(1, 1.1);

Assert.That(a, Is.EqualTo(b).Within(0.2), $"{a} != {b}");
}

private sealed record Data(int number, double Value);
```

### Explanation

Using `Within` here doesn't make any sense, because NUnit cannot apply comparison with tolerance to the types we're comparing.

### Fix

Remove the errant call to `Within`:

```csharp
[Test]
public void RecordsEqualsMismatch()
{
var a = new Data(1, 1.0);
var b = new Data(1, 1.1);

Assert.That(a, Is.EqualTo(b), $"{a} != {b}");
}

private sealed record Data(int number, double Value);
```

<!-- start generated config severity -->
## Configure severity

### Via ruleset file

Configure the severity per project, for more info see [MSDN](https://learn.microsoft.com/en-us/visualstudio/code-quality/using-rule-sets-to-group-code-analysis-rules?view=vs-2022).

### Via .editorconfig file

```ini
# NUnit2047: Incompatible types for Within constraint
dotnet_diagnostic.NUnit2047.severity = chosenSeverity
```

where `chosenSeverity` can be one of `none`, `silent`, `suggestion`, `warning`, or `error`.

### Via #pragma directive

```csharp
#pragma warning disable NUnit2047 // Incompatible types for Within constraint
Code violating the rule here
#pragma warning restore NUnit2047 // Incompatible types for Within constraint
```

Or put this at the top of the file to disable all instances.

```csharp
#pragma warning disable NUnit2047 // Incompatible types for Within constraint
```

### Via attribute `[SuppressMessage]`

```csharp
[System.Diagnostics.CodeAnalysis.SuppressMessage("Assertion",
"NUnit2047:Incompatible types for Within constraint",
Justification = "Reason...")]
```
<!-- end generated config severity -->
1 change: 1 addition & 0 deletions documentation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Rules which improve assertions in the test code.
| [NUnit2044](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2044.md) | Non-delegate actual parameter | :white_check_mark: | :exclamation: | :white_check_mark: |
| [NUnit2045](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2045.md) | Use Assert.Multiple | :white_check_mark: | :information_source: | :white_check_mark: |
| [NUnit2046](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2046.md) | Use CollectionConstraint for better assertion messages in case of failure | :white_check_mark: | :information_source: | :white_check_mark: |
| [NUnit2047](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2047.md) | Incompatible types for Within constraint | :white_check_mark: | :warning: | :white_check_mark: |

### Suppressor Rules (NUnit3001 - )

Expand Down
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.435" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="7.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeStyle" Version="3.11.0" PrivateAssets="all" />
<PackageReference Include="CSharpIsNullAnalyzer" Version="0.1.300" PrivateAssets="all" />
</ItemGroup>

<PropertyGroup>
Expand Down
1 change: 1 addition & 0 deletions src/nunit.analyzers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "documentation", "documentat
..\documentation\NUnit2044.md = ..\documentation\NUnit2044.md
..\documentation\NUnit2045.md = ..\documentation\NUnit2045.md
..\documentation\NUnit2046.md = ..\documentation\NUnit2046.md
..\documentation\NUnit2047.md = ..\documentation\NUnit2047.md
..\documentation\NUnit3001.md = ..\documentation\NUnit3001.md
..\documentation\NUnit3002.md = ..\documentation\NUnit3002.md
..\README.md = ..\README.md
Expand Down
Loading

0 comments on commit 6c49665

Please sign in to comment.