Skip to content

Commit

Permalink
Add ClassicModel Analyzer/CodeFixes for (Not)AssignableFrom
Browse files Browse the repository at this point in the history
  • Loading branch information
manfred-brands committed Nov 2, 2024
1 parent 8b76745 commit aadf20e
Show file tree
Hide file tree
Showing 13 changed files with 1,166 additions and 1 deletion.
82 changes: 82 additions & 0 deletions documentation/NUnit2053.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# NUnit2053

## Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)

| Topic | Value
| :-- | :--
| Id | NUnit2053
| Severity | Info
| Enabled | True
| Category | Assertion
| Code | [ClassicModelAssertUsageAnalyzer](https://github.com/nunit/nunit.analyzers/blob/master/src/nunit.analyzers/ClassicModelAssertUsage/ClassicModelAssertUsageAnalyzer.cs)

## Description

Consider using the constraint model, `Assert.That(actual, Is.AssignableFrom(expected))`, instead of the classic model,
`ClassicAssert.IsAssignableFrom(expected, actual)`.

## Motivation

The assert `ClassicAssert.IsAssignableFrom` from the classic Assert model makes it easy to confuse the `expected` and the
`actual` argument, so this analyzer marks usages of `ClassicAssert.IsAssignableFrom`.

```csharp
[Test]
public void Test()
{
ClassicAssert.IsAssignableFrom(expected, actual);
}
```

## How to fix violations

The analyzer comes with a code fix that will replace `ClassicAssert.IsAssignableFrom(expected, actual)` with
`Assert.That(actual, Is.AssignableFrom(expected))`. So the code block above will be changed into.

```csharp
[Test]
public void Test()
{
Assert.That(actual, Is.AssignableFrom(expected));
}
```

<!-- 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
# NUnit2053: Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)
dotnet_diagnostic.NUnit2053.severity = chosenSeverity
```

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

### Via #pragma directive

```csharp
#pragma warning disable NUnit2053 // Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)
Code violating the rule here
#pragma warning restore NUnit2053 // Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)
```

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

```csharp
#pragma warning disable NUnit2053 // Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)
```

### Via attribute `[SuppressMessage]`

```csharp
[System.Diagnostics.CodeAnalysis.SuppressMessage("Assertion",
"NUnit2053:Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual)",
Justification = "Reason...")]
```
<!-- end generated config severity -->
82 changes: 82 additions & 0 deletions documentation/NUnit2054.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# NUnit2054

## Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)

| Topic | Value
| :-- | :--
| Id | NUnit2054
| Severity | Info
| Enabled | True
| Category | Assertion
| Code | [ClassicModelAssertUsageAnalyzer](https://github.com/nunit/nunit.analyzers/blob/master/src/nunit.analyzers/ClassicModelAssertUsage/ClassicModelAssertUsageAnalyzer.cs)

## Description

Consider using the constraint model, `Assert.That(actual, Is.Not.AssignableFrom(expected))`, instead of the classic model,
`ClassicAssert.IsNotAssignableFrom(expected, actual)`.

## Motivation

The assert `ClassicAssert.IsNotAssignableFrom` from the classic Assert model makes it easy to confuse the `expected` and the
`actual` argument, so this analyzer marks usages of `ClassicAssert.IsNotAssignableFrom`.

```csharp
[Test]
public void Test()
{
ClassicAssert.IsNotAssignableFrom(expected, actual);
}
```

## How to fix violations

The analyzer comes with a code fix that will replace `ClassicAssert.IsNotAssignableFrom(expected, actual)` with
`Assert.That(actual, Is.Not.AssignableFrom(expected))`. So the code block above will be changed into.

```csharp
[Test]
public void Test()
{
Assert.That(actual, Is.Not.AssignableFrom(expected));
}
```

<!-- 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
# NUnit2054: Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)
dotnet_diagnostic.NUnit2054.severity = chosenSeverity
```

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

### Via #pragma directive

```csharp
#pragma warning disable NUnit2054 // Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)
Code violating the rule here
#pragma warning restore NUnit2054 // Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)
```

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

```csharp
#pragma warning disable NUnit2054 // Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)
```

### Via attribute `[SuppressMessage]`

```csharp
[System.Diagnostics.CodeAnalysis.SuppressMessage("Assertion",
"NUnit2054:Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual)",
Justification = "Reason...")]
```
<!-- end generated config severity -->
2 changes: 2 additions & 0 deletions documentation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ Rules which improve assertions in the test code.
| [NUnit2050](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2050.md) | NUnit 4 no longer supports string.Format specification | :white_check_mark: | :exclamation: | :white_check_mark: |
| [NUnit2051](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2051.md) | Consider using Assert.That(expr, Is.Positive) instead of ClassicAssert.Positive(expr) | :white_check_mark: | :information_source: | :white_check_mark: |
| [NUnit2052](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2052.md) | Consider using Assert.That(expr, Is.Negative) instead of ClassicAssert.Negative(expr) | :white_check_mark: | :information_source: | :white_check_mark: |
| [NUnit2053](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2053.md) | Consider using Assert.That(actual, Is.AssignableFrom(expected)) instead of ClassicAssert.IsAssignableFrom(expected, actual) | :white_check_mark: | :information_source: | :white_check_mark: |
| [NUnit2054](https://github.com/nunit/nunit.analyzers/tree/master/documentation/NUnit2054.md) | Consider using Assert.That(actual, Is.Not.AssignableFrom(expected)) instead of ClassicAssert.IsNotAssignableFrom(expected, actual) | :white_check_mark: | :information_source: | :white_check_mark: |

## Suppressor Rules (NUnit3001 - )

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void VerifySupportedDiagnostics()
var analyzer = new ClassicModelAssertUsageAnalyzer();
var diagnostics = analyzer.SupportedDiagnostics;

Assert.That(diagnostics, Has.Length.EqualTo(26), nameof(DiagnosticAnalyzer.SupportedDiagnostics));
Assert.That(diagnostics, Has.Length.EqualTo(28), nameof(DiagnosticAnalyzer.SupportedDiagnostics));

foreach (var diagnostic in diagnostics)
{
Expand Down
Loading

0 comments on commit aadf20e

Please sign in to comment.