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):
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)
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)
- 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>
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>
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>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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 Releaseanddotnet test -c Release --no-build(1180 tests passing throughout):505ada5Assert.That(x.Count, Is.EqualTo(n))→Has.Count.EqualTo(n)/Is.Empty;Assert.That(s.Contains(x))→Does.Contain;.StartsWith("$"|"@"|":")→ char overload67512d2Assert.That(...)inAssert.Multiple(() => { ... })so all failures in a group are reported77eb5d8new[] { ... }tostatic readonlyfields inExpressionFactoryFilterTests470cb00JsonSerializerOptionsas astatic readonlyfield inRules.Tests/UnitTest1.csNotes
dotnet format analyzers --diagnostics …. Commit 1 also includes a regex sweep for theCount == 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.Assert.Throws/Assert.Fail/Assert.Catch/Assert.Pass/Assert.DoesNotThrowended up inside anAssert.Multipleblock (those must short-circuit).src/Strata.SqlTools.SqlBreakdown/Utilities/SqlUtils.csandsrc/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 failedsonarqube.ymlruns the SonarScanner upload on this PR/api/issues/search?componentKeys=sql-utilities&resolved=false&facets=rulesafter the scan completes; the six rule IDs above should each drop to 0 (or near-0 if the fixer left a corner case)- 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>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>