SonarQube Analysis / sonarqube (pull_request) Successful in 2m59s
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>
519 lines
16 KiB
C#
519 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.Multiple(() =>
|
|
{
|
|
// 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.Multiple(() =>
|
|
{
|
|
// 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.Multiple(() =>
|
|
{
|
|
// 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.Multiple(() =>
|
|
{
|
|
// 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.Multiple(() =>
|
|
{
|
|
// 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.Multiple(() =>
|
|
{
|
|
// 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, Is.Not.Empty);
|
|
}
|
|
|
|
[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.Multiple(() =>
|
|
{
|
|
// Assert
|
|
Assert.That(stats.TotalQueries, Is.EqualTo(100));
|
|
Assert.That(stats.UniqueQueries, Is.EqualTo(1));
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
}
|