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>
285 lines
8.5 KiB
C#
285 lines
8.5 KiB
C#
using Strata.SqlTools.Breakdowns.Snowflake;
|
|
|
|
namespace Strata.SqlTools.Snowflake.Tests.Snowflake;
|
|
|
|
[TestFixture]
|
|
public class QueryBreakdownCollectionTests
|
|
{
|
|
private QueryBreakdownCollection _collection = null!;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_collection = new QueryBreakdownCollection();
|
|
}
|
|
|
|
[Test]
|
|
public void Constructor_Empty_CreatesEmptyCollection()
|
|
{
|
|
// Act & Assert
|
|
Assert.That(_collection, Is.Empty);
|
|
Assert.That(_collection.QueryBreakdowns, Is.Empty);
|
|
}
|
|
|
|
[Test]
|
|
public void Constructor_WithQueries_InitializesCollection()
|
|
{
|
|
// Arrange
|
|
var queries = new List<QueryBreakdown>
|
|
{
|
|
new QueryBreakdown("ID, Name", "Users"),
|
|
new QueryBreakdown("OrderID, Amount", "Orders")
|
|
};
|
|
|
|
// Act
|
|
var collection = new QueryBreakdownCollection(queries);
|
|
|
|
// Assert
|
|
Assert.That(collection, Has.Count.EqualTo(2));
|
|
Assert.That(collection.QueryBreakdowns, Has.Count.EqualTo(2));
|
|
}
|
|
|
|
[Test]
|
|
public void Add_SingleQuery_AddsToCollection()
|
|
{
|
|
// Arrange
|
|
var query = new QueryBreakdown("ID, Name", "Users");
|
|
|
|
// Act
|
|
_collection.Add(query);
|
|
|
|
// Assert
|
|
Assert.That(_collection, Has.Count.EqualTo(1));
|
|
Assert.That(_collection.QueryBreakdowns[0], Is.EqualTo(query));
|
|
}
|
|
|
|
[Test]
|
|
public void Add_NullQuery_ThrowsArgumentNullException()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() => _collection.Add(null!));
|
|
}
|
|
|
|
[Test]
|
|
public void GetSnowflakeBatch_MultipleQueries_SeparatedBySemicolons()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
|
|
_collection.Add(new QueryBreakdown("OrderID, Amount", "Orders"));
|
|
|
|
// Act
|
|
var sql = _collection.GetSnowflakeBatch();
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain(";"));
|
|
Assert.That(sql, Does.Contain("SELECT"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetSnowflakeBatch_WithSessionSetup_IncludesAlterSession()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
|
|
|
|
// Act
|
|
var sql = _collection.GetSnowflakeBatch(includeSessionSetup: true);
|
|
|
|
// Assert
|
|
Assert.That(sql, Does.Contain("ALTER SESSION"));
|
|
Assert.That(sql, Does.Contain("Session Setup"));
|
|
}
|
|
|
|
[Test]
|
|
public void WhereUseStageReference_WithStageReference_ReturnsMatching()
|
|
{
|
|
// Arrange
|
|
var queryWithStage = new QueryBreakdown("$1, $2", "@mystage/data.csv");
|
|
var queryWithoutStage = new QueryBreakdown("ID, Name", "Users");
|
|
|
|
_collection.Add(queryWithStage);
|
|
_collection.Add(queryWithoutStage);
|
|
|
|
// Act
|
|
var results = _collection.WhereUseStageReference().ToList();
|
|
|
|
// Assert
|
|
Assert.That(results, Has.Count.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void WhereUseStageReference_WithParameterSyntax_ExcludesParameters()
|
|
{
|
|
// Arrange
|
|
var queryWithParameter = new QueryBreakdown("ID, Name", "Users", "ID = @UserId");
|
|
var queryWithStage = new QueryBreakdown("$1, $2", "@mystage/data.csv");
|
|
|
|
_collection.Add(queryWithParameter);
|
|
_collection.Add(queryWithStage);
|
|
|
|
// Act
|
|
var results = _collection.WhereUseStageReference().ToList();
|
|
|
|
// Assert
|
|
// Only the stage reference query should be returned, not the parameter query
|
|
Assert.That(results, Has.Count.EqualTo(1));
|
|
Assert.That(results[0], Is.EqualTo(queryWithStage));
|
|
}
|
|
|
|
[Test]
|
|
public void WhereUseSemiStructuredData_WithJsonFunctions_ReturnsMatching()
|
|
{
|
|
// Arrange
|
|
var queryWithJson = new QueryBreakdown("JSON_EXTRACT(data, '$.id')", "raw_data");
|
|
var queryWithoutJson = new QueryBreakdown("ID, Name", "Users");
|
|
|
|
_collection.Add(queryWithJson);
|
|
_collection.Add(queryWithoutJson);
|
|
|
|
// Act
|
|
var results = _collection.WhereUseSemiStructuredData().ToList();
|
|
|
|
// Assert
|
|
Assert.That(results, Has.Count.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void GetTotalSelectedColumns_MultipleQueries_SumsColumns()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name, Email", "Users"));
|
|
_collection.Add(new QueryBreakdown("OrderID, Amount", "Orders"));
|
|
|
|
// Act
|
|
var columnCount = _collection.GetTotalSelectedColumns();
|
|
|
|
// Assert
|
|
Assert.That(columnCount, Is.EqualTo(5));
|
|
}
|
|
|
|
[Test]
|
|
public void GetUniqueTableReferences_MultipleQueries_ReturnsUniqueTables()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
|
|
_collection.Add(new QueryBreakdown("OrderID, UserID", "Orders"));
|
|
_collection.Add(new QueryBreakdown("ID", "Users"));
|
|
|
|
// Act
|
|
var tables = _collection.GetUniqueTableReferences().ToList();
|
|
|
|
// Assert
|
|
Assert.That(tables, Has.Count.EqualTo(2));
|
|
Assert.That(tables, Does.Contain("Users"));
|
|
Assert.That(tables, Does.Contain("Orders"));
|
|
}
|
|
|
|
[Test]
|
|
public void GetQuerySummaries_WithQueries_ReturnsSummaryWithSnowflakeFeatures()
|
|
{
|
|
// Arrange
|
|
var jsonQuery = new QueryBreakdown("JSON_EXTRACT(data, '$.id')", "raw_data");
|
|
var stageQuery = new QueryBreakdown("$1, $2", "@mystage/data.csv");
|
|
|
|
_collection.Add(jsonQuery);
|
|
_collection.Add(stageQuery);
|
|
|
|
// Act
|
|
var summaries = _collection.GetQuerySummaries().ToList();
|
|
|
|
// Assert
|
|
Assert.That(summaries, Has.Count.EqualTo(2));
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(summaries[0].UsesSemiStructuredData, Is.True);
|
|
Assert.That(summaries[1].UsesStageReference, Is.True);
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void SynchronizeParameters_ParametersInSomeQueries_SynchronizesAcrossQueries()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("ID, Name", "Users", "ID = :UserId");
|
|
var query2 = new QueryBreakdown("OrderID", "Orders", "UserID = :UserId");
|
|
query1.Parameters["UserId"] = 123;
|
|
query2.Parameters["UserId"] = 456;
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
|
|
// Act
|
|
_collection.SynchronizeParameters();
|
|
|
|
// Assert
|
|
Assert.That(query1.Parameters["UserId"], Is.EqualTo(query2.Parameters["UserId"]));
|
|
}
|
|
|
|
[Test]
|
|
public void AddParameterToAll_AddsParameterToAllQueries()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
|
|
_collection.Add(new QueryBreakdown("OrderID", "Orders"));
|
|
|
|
// Act
|
|
_collection.AddParameterToAll("CompanyId", 99);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
// Assert
|
|
Assert.That(_collection.QueryBreakdowns[0].Parameters["CompanyId"], Is.EqualTo(99));
|
|
Assert.That(_collection.QueryBreakdowns[1].Parameters["CompanyId"], Is.EqualTo(99));
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void GetParameterUsageReport_WithParameters_ReturnsUsageReport()
|
|
{
|
|
// Arrange
|
|
var query1 = new QueryBreakdown("ID, Name", "Users", "ID = :UserId");
|
|
var query2 = new QueryBreakdown("OrderID", "Orders", "UserID = :UserId AND Status = :Status");
|
|
query1.Parameters["UserId"] = 123;
|
|
query2.Parameters["UserId"] = 123;
|
|
query2.Parameters["Status"] = "Active";
|
|
_collection.Add(query1);
|
|
_collection.Add(query2);
|
|
|
|
// Act
|
|
var report = _collection.GetParameterUsageReport().ToList();
|
|
|
|
// Assert
|
|
Assert.That(report, Is.Not.Empty);
|
|
var userIdReport = report.FirstOrDefault(r => r.ParameterName == "UserId");
|
|
Assert.That(userIdReport, Is.Not.Null);
|
|
Assert.That(userIdReport?.UsedInQueryCount, Is.EqualTo(2));
|
|
}
|
|
|
|
[Test]
|
|
public void GetParametersAsString_WithParameters_FormatsSnowflakeStyle()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users", "ID = :UserId"));
|
|
_collection.QueryBreakdowns[0].Parameters["UserId"] = 123;
|
|
|
|
// Act
|
|
var paramString = _collection.GetParametersAsString(includeDataTypes: true);
|
|
|
|
// Assert
|
|
Assert.That(paramString, Does.Contain(":UserId"));
|
|
Assert.That(paramString, Does.Contain("NUMBER"));
|
|
}
|
|
|
|
[Test]
|
|
public void Clear_WithQueries_RemovesAllQueries()
|
|
{
|
|
// Arrange
|
|
_collection.Add(new QueryBreakdown("ID, Name", "Users"));
|
|
_collection.Add(new QueryBreakdown("OrderID", "Orders"));
|
|
|
|
// Act
|
|
_collection.Clear();
|
|
|
|
// Assert
|
|
Assert.That(_collection, Is.Empty);
|
|
}
|
|
}
|