chore(sonar): clean up test-file INFO code smells (NUnit2045/2046/2011, CA1866/1861/1869) #14

Merged
bermudalamb merged 5 commits from fix/sonarqube-test-cases-code-smells into main 2026-05-27 13:02:43 -05:00
Owner

Summary

Drives the open SonarQube issue count for tests/** from 485 → 0 (or near-0) by clearing every INFO-severity code smell the analyzer reports in the test projects. Production code is untouched on this branch.

Four tiered commits, each verified with dotnet build -c Release and dotnet test -c Release --no-build (1180 tests passing throughout):

Commit Rule(s) What changed
505ada5 NUnit2046, NUnit2011, CA1866 Assert.That(x.Count, Is.EqualTo(n))Has.Count.EqualTo(n) / Is.Empty; Assert.That(s.Contains(x))Does.Contain; .StartsWith("$"|"@"|":") → char overload
67512d2 NUnit2045 Wrap consecutive independent Assert.That(...) in Assert.Multiple(() => { ... }) so all failures in a group are reported
77eb5d8 CA1861 Hoist inline new[] { ... } to static readonly fields in ExpressionFactoryFilterTests
470cb00 CA1869 Cache JsonSerializerOptions as a static readonly field in Rules.Tests/UnitTest1.cs

Notes

  • Commits 1 and 2 were driven by dotnet format analyzers --diagnostics …. Commit 1 also includes a regex sweep for the Count == n (n>0) cases the Roslyn fixer doesn't handle, plus three CA1866 sites the fixer reports no code fix for and were edited by hand.
  • Commit 2 audit: confirmed no Assert.Throws / Assert.Fail / Assert.Catch / Assert.Pass / Assert.DoesNotThrow ended up inside an Assert.Multiple block (those must short-circuit).
  • The CA1861 sweep also flagged three production-code sites in src/Strata.SqlTools.SqlBreakdown/Utilities/SqlUtils.cs and src/Strata.SqlTools.SqlServer/Statements/StatementParser.cs — explicitly out of scope here; will land separately.

Test plan

  • dotnet build Strata.SqlTools.QueryBreakdown.sln -c Release — 0 errors after each commit (pre-existing warnings unchanged)
  • dotnet test ... -c Release --no-build — 1180 passed, 0 failed
  • Gitea Actions sonarqube.yml runs the SonarScanner upload on this PR
  • Re-query /api/issues/search?componentKeys=sql-utilities&resolved=false&facets=rules after the scan completes; the six rule IDs above should each drop to 0 (or near-0 if the fixer left a corner case)
## Summary Drives the open SonarQube issue count for `tests/**` from **485 → 0** (or near-0) by clearing every INFO-severity code smell the analyzer reports in the test projects. Production code is untouched on this branch. Four tiered commits, each verified with `dotnet build -c Release` and `dotnet test -c Release --no-build` (1180 tests passing throughout): | Commit | Rule(s) | What changed | |---|---|---| | `505ada5` | NUnit2046, NUnit2011, CA1866 | `Assert.That(x.Count, Is.EqualTo(n))` → `Has.Count.EqualTo(n)` / `Is.Empty`; `Assert.That(s.Contains(x))` → `Does.Contain`; `.StartsWith("$"\|"@"\|":")` → char overload | | `67512d2` | NUnit2045 | Wrap consecutive independent `Assert.That(...)` in `Assert.Multiple(() => { ... })` so all failures in a group are reported | | `77eb5d8` | CA1861 | Hoist inline `new[] { ... }` to `static readonly` fields in `ExpressionFactoryFilterTests` | | `470cb00` | CA1869 | Cache `JsonSerializerOptions` as a `static readonly` field in `Rules.Tests/UnitTest1.cs` | ## Notes - Commits 1 and 2 were driven by `dotnet format analyzers --diagnostics …`. Commit 1 also includes a regex sweep for the `Count == n` (n>0) cases the Roslyn fixer doesn't handle, plus three CA1866 sites the fixer reports no code fix for and were edited by hand. - Commit 2 audit: confirmed no `Assert.Throws` / `Assert.Fail` / `Assert.Catch` / `Assert.Pass` / `Assert.DoesNotThrow` ended up inside an `Assert.Multiple` block (those must short-circuit). - The CA1861 sweep also flagged three production-code sites in `src/Strata.SqlTools.SqlBreakdown/Utilities/SqlUtils.cs` and `src/Strata.SqlTools.SqlServer/Statements/StatementParser.cs` — explicitly out of scope here; will land separately. ## Test plan - [x] `dotnet build Strata.SqlTools.QueryBreakdown.sln -c Release` — 0 errors after each commit (pre-existing warnings unchanged) - [x] `dotnet test ... -c Release --no-build` — 1180 passed, 0 failed - [ ] Gitea Actions `sonarqube.yml` runs the SonarScanner upload on this PR - [ ] Re-query `/api/issues/search?componentKeys=sql-utilities&resolved=false&facets=rules` after the scan completes; the six rule IDs above should each drop to 0 (or near-0 if the fixer left a corner case)
bermudalamb added 4 commits 2026-05-27 12:03:15 -05:00
- NUnit2046: `Assert.That(x.Count, Is.EqualTo(n))` → `Assert.That(x, Has.Count.EqualTo(n))` (or `Is.Empty` when n==0)
- NUnit2011: `Assert.That(s.Contains(x))` → `Assert.That(s, Does.Contain(x))` for richer failure messages
- CA1866: `.StartsWith("$"|"@"|":")` → `.StartsWith('$'|'@'|':')` char overload

Driven by `dotnet format analyzers --diagnostics NUnit2046 NUnit2011 CA1866`
for the cases the Roslyn fixer handles, plus a regex sweep for the remaining
`Count == n` (n>0) cases which the fixer doesn't address. CA1866 had no
associated code fix and was edited by hand (3 sites in 2 files). All tests
green (1180 passing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Driven by `dotnet format analyzers --diagnostics NUnit2045`. The fixer
groups consecutive independent `Assert.That(...)` calls into
`Assert.Multiple(() => { ... })`, so a failing assertion no longer
short-circuits the block — every failure inside the group is reported,
which gives much better diagnostics on multi-property tests.

Audit confirmed no Assert.Throws / Assert.Fail / Assert.Catch / Assert.Pass
/ Assert.DoesNotThrow got pulled inside a Multiple block (those need to
short-circuit). All 1180 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two inline `new[] { ... }` literals inside TestCaseSource yield-returns
get hoisted to `static readonly string[]` fields with descriptive names
(`monthListValues`, `calendarRange`) matching the surrounding test-case
identifiers. Avoids reconstructing the same array on each call.

Only the test-file CA1861 sites are touched; the three production-code
sites flagged for the same rule are out of scope for this branch and
will land separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore(sonar): cache JsonSerializerOptions in test fixture (CA1869)
SonarQube Analysis / sonarqube (pull_request) Successful in 5m12s
470cb009b9
Promote the `new JsonSerializerOptions { Converters = { ... } }` instance
that `OneTimeSetup` was constructing on each fixture run to a
`private static readonly JsonSerializerOptions _jsonOptions` field, so
the converter list isn't rebuilt per fixture. Strictly cosmetic here
(OneTimeSetup runs once) but it's the change the analyzer wants and the
field is the more idiomatic JsonSerializer pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bermudalamb added 1 commit 2026-05-27 12:14:17 -05:00
Re-runs `dotnet format analyzers --diagnostics NUnit2046 NUnit2045` after
the Tier 2 Assert.Multiple wrap, which exposed:

- `Has.Length.EqualTo(n)` rewrites for `string[]`/array `.Length` checks
  (the first pass only knew about `.Count`).
- `Is.Not.Empty` rewrites for `Count, Is.GreaterThan(0)`.
- A handful of new NUnit2045 groups that became wrappable once the
  initial Multiple blocks settled the surrounding indentation.

Tests still 1180/1180 passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bermudalamb merged commit 72072cec8e into main 2026-05-27 13:02:43 -05:00
bermudalamb deleted branch fix/sonarqube-test-cases-code-smells 2026-05-27 13:02:43 -05:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Lambda-Associates/sql-utilities#14