SonarQube Analysis / sonarqube (pull_request) Successful in 3m30s
Three public methods on the SqlServer-namespaced Markdown generators no longer touch instance state and now carry the `static` keyword: - `Markdown.SqlServer.QueryBreakdownGenerator.GenerateMermaidDiagram(QueryBreakdown, string?)` - `Markdown.SqlServer.SqlStatementGenerator.GenerateSequenceDiagram(ISqlBreakdown, string?)` - `Markdown.SqlServer.SqlStatementGenerator.GenerateEntityRelationshipDiagram(IEnumerable<string>, string?)` Plus one private bonus the analyzer caught on the same pass: - `LinqExpressionVisitor.ExtractSelectExpression` → static (non-breaking). Internal callers in the Snowflake/LinqToSql/PostgreSql wrapper classes and in the test fixtures are updated to the type-name form (`SqlServer.SqlStatementGenerator.GenerateSequenceDiagram(...)`). The wrappers retain their `_baseGenerator` field for now even though it is no longer used — that S4487 / unused-field cleanup is its own commit. BREAKING CHANGE: External NuGet consumers calling `generatorInstance.GenerateMermaidDiagram(...)`, `generatorInstance.GenerateSequenceDiagram(...)`, or `generatorInstance.GenerateEntityRelationshipDiagram(...)` on the SqlServer-namespaced generators must switch to type-name form, e.g. `Markdown.SqlServer.SqlStatementGenerator.GenerateSequenceDiagram(...)`. Calls through the Snowflake / LinqToSql / PostgreSql wrapper classes are unaffected at the call site. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
152 lines
5.7 KiB
C#
152 lines
5.7 KiB
C#
using Strata.SqlTools.Breakdowns.SqlServer;
|
|
using Strata.SqlTools.Markdown.SqlServer;
|
|
|
|
namespace Strata.SqlTools.Markdown.Tests.SqlServer;
|
|
|
|
[TestFixture]
|
|
[Ignore("These tests are designed to generate markdown files from SQL queries in the Queries directory. They are not meant to be run as part of regular unit testing, but can be executed manually when needed.")]
|
|
[Category("MarkdownGeneration")]
|
|
public class QueryMarkdownGenerationTests
|
|
{
|
|
private QueryBreakdownGenerator _generator = null!;
|
|
private string _queriesSourcePath = null!;
|
|
private string _markdownOutputPath = null!;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
_generator = new QueryBreakdownGenerator();
|
|
|
|
// Get the solution root directory
|
|
var testDirectory = TestContext.CurrentContext.TestDirectory;
|
|
var solutionRoot = Directory.GetParent(testDirectory)?.Parent?.Parent?.Parent?.Parent?.FullName;
|
|
|
|
if (solutionRoot == null)
|
|
throw new InvalidOperationException("Could not determine solution root directory");
|
|
|
|
_queriesSourcePath = Path.Combine(solutionRoot, "Queries");
|
|
_markdownOutputPath = Path.Combine(solutionRoot, "docs", "queries");
|
|
|
|
// Ensure output directory exists
|
|
if (!Directory.Exists(_markdownOutputPath))
|
|
{
|
|
Directory.CreateDirectory(_markdownOutputPath);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void GenerateMarkdownForAllQueries_CreatesMarkdownFiles()
|
|
{
|
|
// Arrange
|
|
Assert.That(Directory.Exists(_queriesSourcePath), Is.True,
|
|
$"Queries directory not found at: {_queriesSourcePath}");
|
|
|
|
var sqlFiles = Directory.GetFiles(_queriesSourcePath, "*.sql");
|
|
Assert.That(sqlFiles, Is.Not.Empty, "No SQL files found in Queries directory");
|
|
|
|
int successCount = 0;
|
|
int skippedCount = 0;
|
|
|
|
// Act & Assert for each file
|
|
foreach (var sqlFile in sqlFiles)
|
|
{
|
|
var fileName = Path.GetFileNameWithoutExtension(sqlFile);
|
|
var sqlContent = File.ReadAllText(sqlFile);
|
|
|
|
try
|
|
{
|
|
// Parse the SQL query
|
|
var queryBreakdown = QueryBreakdown.Parse(sqlContent);
|
|
|
|
// Generate markdown with the filename as title
|
|
var markdown = QueryBreakdownGenerator.GenerateMermaidDiagram(queryBreakdown, fileName);
|
|
|
|
// Verify markdown was generated
|
|
Assert.That(markdown, Is.Not.Null);
|
|
Assert.That(markdown, Does.Contain("```mermaid"));
|
|
Assert.That(markdown, Does.Contain(fileName));
|
|
|
|
// Write to output file
|
|
var outputFile = Path.Combine(_markdownOutputPath, $"{fileName}.md");
|
|
File.WriteAllText(outputFile, markdown);
|
|
|
|
// Verify file was created
|
|
Assert.That(File.Exists(outputFile), Is.True,
|
|
$"Markdown file was not created: {outputFile}");
|
|
|
|
TestContext.Out.WriteLine($"Generated: {fileName}.md");
|
|
successCount++;
|
|
}
|
|
catch (FormatException ex)
|
|
{
|
|
// Skip files that can't be parsed (e.g., partial queries with only WITH clauses)
|
|
TestContext.Out.WriteLine($"Skipped: {fileName}.sql - {ex.Message}");
|
|
skippedCount++;
|
|
}
|
|
}
|
|
|
|
TestContext.Out.WriteLine($"Generated {successCount} markdown files, skipped {skippedCount} files in {_markdownOutputPath}");
|
|
Assert.That(successCount, Is.GreaterThan(0), "At least one markdown file should be generated");
|
|
}
|
|
|
|
[Test]
|
|
public void GenerateMarkdownForAllQueries_IncludesQuerySource()
|
|
{
|
|
// Arrange
|
|
var sqlFiles = Directory.GetFiles(_queriesSourcePath, "*.sql");
|
|
Assert.That(sqlFiles, Is.Not.Empty);
|
|
|
|
int successCount = 0;
|
|
|
|
// Act & Assert
|
|
foreach (var sqlFile in sqlFiles)
|
|
{
|
|
var fileName = Path.GetFileNameWithoutExtension(sqlFile);
|
|
var sqlContent = File.ReadAllText(sqlFile);
|
|
|
|
try
|
|
{
|
|
var queryBreakdown = QueryBreakdown.Parse(sqlContent);
|
|
var markdown = QueryBreakdownGenerator.GenerateMermaidDiagram(queryBreakdown, fileName);
|
|
|
|
// Add source SQL to the markdown
|
|
var fullMarkdown = $"{markdown}\n\n## Source SQL\n\n```sql\n{sqlContent}\n```\n";
|
|
|
|
var outputFile = Path.Combine(_markdownOutputPath, $"{fileName}.md");
|
|
File.WriteAllText(outputFile, fullMarkdown);
|
|
|
|
// Verify the output includes both diagram and source
|
|
var writtenContent = File.ReadAllText(outputFile);
|
|
Assert.That(writtenContent, Does.Contain("```mermaid"));
|
|
Assert.That(writtenContent, Does.Contain("## Source SQL"));
|
|
Assert.That(writtenContent, Does.Contain(sqlContent));
|
|
|
|
successCount++;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
// Skip files that can't be parsed
|
|
TestContext.Out.WriteLine($"Skipped: {fileName}.sql (could not parse)");
|
|
}
|
|
}
|
|
|
|
Assert.That(successCount, Is.GreaterThan(0), "At least one markdown file should be generated");
|
|
}
|
|
|
|
[Test]
|
|
public void AllQueriesDirectory_Exists()
|
|
{
|
|
// Verify the Queries directory exists
|
|
Assert.That(Directory.Exists(_queriesSourcePath), Is.True,
|
|
$"Queries directory should exist at: {_queriesSourcePath}");
|
|
}
|
|
|
|
[Test]
|
|
public void OutputDirectory_IsCreated()
|
|
{
|
|
// Verify the output directory was created
|
|
Assert.That(Directory.Exists(_markdownOutputPath), Is.True,
|
|
$"Output directory should exist at: {_markdownOutputPath}");
|
|
}
|
|
}
|