Files
sql-utilities/tests/Strata.SqlTools.LinqToSql.Tests/QueryCollectionAnalyzerTests.cs
T
Thom LambandClaude Opus 4.7 505ada5017 chore(sonar): adopt Has.Count, Is.Empty, Does.Contain, char overloads in tests (NUnit2046, NUnit2011, CA1866)
- 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>
2026-05-27 11:58:00 -05:00

498 lines
16 KiB
C#

using NUnit.Framework;
using Strata.SqlTools.Analyzers.LinqToSql;
using Strata.SqlTools.Builders.LinqToSql;
namespace Strata.SqlTools.LinqToSql.Tests;
[TestFixture]
public class QueryCollectionAnalyzerTests
{
#region Basic Analysis Tests
[Test]
public void Analyze_WithEmptyCollection_ReturnsZeroStatistics()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>();
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TotalQueries, Is.EqualTo(0));
Assert.That(stats.UniqueQueries, Is.EqualTo(0));
Assert.That(stats.DuplicateQueries, Is.Empty);
}
[Test]
public void Analyze_WithSingleQuery_ReturnsCorrectStatistics()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Id", "Name")
.FromTable("Users")
.Where("IsActive = true")
.Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TotalQueries, Is.EqualTo(1));
Assert.That(stats.UniqueQueries, Is.EqualTo(1));
Assert.That(stats.DuplicateQueries, Is.Empty);
}
[Test]
public void Analyze_WithIdenticalQueries_IdentifiesDuplicates()
{
// Arrange
var query1 = LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Id", "Name")
.FromTable("Users")
.Build();
var query2 = LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Id", "Name")
.FromTable("Users")
.Build();
var query3 = LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Id", "Name")
.FromTable("Users")
.Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown> { query1, query2, query3 };
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TotalQueries, Is.EqualTo(3));
Assert.That(stats.UniqueQueries, Is.EqualTo(1));
Assert.That(stats.DuplicateQueries, Has.Count.EqualTo(2));
}
#endregion
#region Deduplication Rate Tests
[Test]
public void DeduplicationRate_WithAllUnique_ReturnsOne()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.DeduplicationRate, Is.EqualTo(1.0));
}
[Test]
public void DeduplicationRate_WithSomeDuplicates_ReturnsCorrectRatio()
{
// Arrange
var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
query,
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), // Duplicate
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.DeduplicationRate, Is.EqualTo(2.0 / 3.0).Within(0.01));
}
#endregion
#region Query Characteristics Tests
[Test]
public void Analyze_CountsQueriesWithoutWhere()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Where("Amount > 100").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.QueriesWithoutWhere, Is.EqualTo(2));
}
[Test]
public void Analyze_CountsQueriesWithoutOrderBy()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").OrderByAscending("Name").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.QueriesWithoutOrderBy, Is.EqualTo(2));
}
[Test]
public void Analyze_CountsQueriesWithSelectAll()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Orders").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.QueriesWithSelectAll, Is.EqualTo(2));
}
#endregion
#region Table Usage Analysis Tests
[Test]
public void Analyze_AnalyzesTableUsageFrequency()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TableUsageFrequency["Users"], Is.EqualTo(3));
Assert.That(stats.TableUsageFrequency["Orders"], Is.EqualTo(1));
}
[Test]
public void Analyze_IgnoresNullTableNames()
{
// Arrange
var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown> { query };
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TableUsageFrequency.ContainsKey("Users"), Is.True);
}
#endregion
#region Column Usage Analysis Tests
[Test]
public void Analyze_AnalyzesColumnSelectionFrequency()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name", "Email").FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.ColumnSelectionFrequency.ContainsKey("Id"), Is.True);
Assert.That(stats.ColumnSelectionFrequency["Id"], Is.EqualTo(3));
Assert.That(stats.ColumnSelectionFrequency["Name"], Is.EqualTo(2));
Assert.That(stats.ColumnSelectionFrequency["Email"], Is.EqualTo(1));
}
[Test]
public void Analyze_IgnoresSelectAll_InColumnUsage()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.ColumnSelectionFrequency.ContainsKey("*"), Is.False);
Assert.That(stats.ColumnSelectionFrequency["Id"], Is.EqualTo(1));
}
#endregion
#region Complexity Analysis Tests
[Test]
public void Analyze_CalculatesAverageComplexity()
{
// Arrange
var simpleQuery = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build();
var complexQuery = LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Department", "COUNT(*)")
.FromTable("Employees")
.Where("Salary > 50000 AND Department IN ('IT', 'HR')")
.GroupBy("Department")
.Having("COUNT(*) > 5")
.OrderByDescending("COUNT(*)")
.Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown> { simpleQuery, complexQuery };
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.AverageComplexity, Is.GreaterThan(0));
Assert.That(stats.AverageComplexity, Is.LessThanOrEqualTo(10));
}
[Test]
public void Analyze_CountsComplexQueries()
{
// Arrange
var simpleQuery = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build();
var complexQuery = LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Dept", "COUNT(*)")
.FromTable("Emp")
.Where("Salary > 50000 AND Department IN ('IT', 'HR')")
.GroupBy("Dept")
.Having("COUNT(*) > 5")
.Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown> { simpleQuery, complexQuery };
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.ComplexQueriesCount, Is.GreaterThan(0));
}
#endregion
#region FindDuplicates Tests
[Test]
public void FindDuplicates_WithNoDuplicates_ReturnsEmptyList()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var duplicates = analyzer.FindDuplicates();
// Assert
Assert.That(duplicates, Is.Empty);
}
[Test]
public void FindDuplicates_WithDuplicates_ReturnsDuplicateQueries()
{
// Arrange
var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build();
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
query,
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var duplicates = analyzer.FindDuplicates();
// Assert
Assert.That(duplicates, Has.Count.EqualTo(2));
}
#endregion
#region FindSimilarQueries Tests
[Test]
public void FindSimilarQueries_WithSimilarQueries_ReturnsSimilarPairs()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name", "Email").FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var similar = analyzer.FindSimilarQueries(0.5); // Lower threshold for testing
// Assert
Assert.That(similar.Count, Is.GreaterThan(0));
}
[Test]
public void FindSimilarQueries_SimilarityScoresBounded()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var similar = analyzer.FindSimilarQueries(0.5);
// Assert
foreach (var pair in similar)
{
Assert.That(pair.Similarity, Is.GreaterThanOrEqualTo(0.5));
Assert.That(pair.Similarity, Is.LessThan(1.0));
}
}
#endregion
#region Report Generation Tests
[Test]
public void GetReport_IncludesBasicStatistics()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var report = analyzer.GetReport();
// Assert
Assert.That(report, Contains.Substring("Query Collection Analysis Report"));
Assert.That(report, Contains.Substring("Total Queries: 1"));
Assert.That(report, Contains.Substring("Unique Queries: 1"));
}
[Test]
public void GetReport_IncludesTableUsage()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>
{
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(),
LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build()
};
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var report = analyzer.GetReport();
// Assert
Assert.That(report, Contains.Substring("Most Frequently Used Tables"));
}
#endregion
#region Null Handling Tests
[Test]
public void Constructor_WithNullQueries_ThrowsArgumentNullException()
{
// Act & Assert
Assert.Throws<ArgumentNullException>(() => new QueryCollectionAnalyzer(null!));
}
#endregion
#region Edge Cases
[Test]
public void Analyze_WithLargeCollection_PerformsAnalysis()
{
// Arrange
var queries = new List<Strata.SqlTools.Breakdowns.LinqToSql.LinqQueryBreakdown>();
for (int i = 0; i < 100; i++)
{
queries.Add(LinqQueryBreakdownBuilder
.Create()
.SelectColumns("Id", "Name")
.FromTable("Users")
.Build());
}
var analyzer = QueryCollectionAnalyzer.Analyze(queries);
// Act
var stats = analyzer.Analyze();
// Assert
Assert.That(stats.TotalQueries, Is.EqualTo(100));
Assert.That(stats.UniqueQueries, Is.EqualTo(1));
}
#endregion
}