Skip to content

Commit

Permalink
Improve TOC and add .NET Analyzers to tests (#54)
Browse files Browse the repository at this point in the history
* Add example indication to Smells TOC

* add analyzers to SqlServer.Rules.Test

* add .NET Analyzers to Smells test project
  • Loading branch information
ErikEJ authored Jan 19, 2025
1 parent 5631dba commit ed4a4e1
Show file tree
Hide file tree
Showing 25 changed files with 1,481 additions and 1,516 deletions.
198 changes: 98 additions & 100 deletions SqlServer.Rules.Test/BaselineSetup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -8,129 +8,127 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SqlServer.Rules.Tests.Utils;

namespace SqlServer.Rules.Test
namespace SqlServer.Rules.Test;

internal sealed class BaselineSetup : RuleTest
{
class BaselineSetup : RuleTest
private const string TestScriptsFolder = "TestScripts";
private const string SetupScriptsFolder = "_Setup";
private const string Output = "Output";
private const string Baseline = "Baseline";
private const string SqlExtension = ".sql";

public string ScriptsFolder { get; private set; }
public string SetupFolder { get; private set; }
public string OutputFilePath { get; private set; }
public string BaselineFilePath { get; private set; }

public BaselineSetup(TestContext testContext, string testName, TSqlModelOptions databaseOptions, SqlServerVersion sqlServerVersion = SqlServerVersion.Sql150)
: base(new List<Tuple<string, string>>(), databaseOptions, sqlServerVersion)
{
private const string TestScriptsFolder = "TestScripts";
private const string SetupScriptsFolder = "_Setup";
private const string Output = "Output";
private const string Baseline = "Baseline";
private const string DacpacBaseline = "DacpacBaseline";
private const string SqlExtension = ".sql";

protected string ScriptsFolder { get; private set; }
protected string SetupFolder { get; private set; }
protected string OutputFilePath { get; private set; }
protected string BaselineFilePath { get; private set; }

public BaselineSetup(TestContext testContext, string testName, TSqlModelOptions databaseOptions, SqlServerVersion sqlServerVersion = SqlServerVersion.Sql150)
: base(new List<Tuple<string, string>>(), databaseOptions, sqlServerVersion)
{
var folder = Path.Combine(GetBaseFolder(), TestScriptsFolder);
ScriptsFolder = Directory.EnumerateDirectories(folder, testName, SearchOption.AllDirectories).FirstOrDefault();
Assert.IsTrue(Directory.Exists(ScriptsFolder), $"Expected the test folder '{ScriptsFolder}' to exist");
var folder = Path.Combine(GetBaseFolder(), TestScriptsFolder);
ScriptsFolder = Directory.EnumerateDirectories(folder, testName, SearchOption.AllDirectories).FirstOrDefault();
Assert.IsTrue(Directory.Exists(ScriptsFolder), $"Expected the test folder '{ScriptsFolder}' to exist");

SetupFolder = Path.Combine(GetBaseFolder(), TestScriptsFolder, SetupScriptsFolder);
SetupFolder = Path.Combine(GetBaseFolder(), TestScriptsFolder, SetupScriptsFolder);

var outputDir = testContext.TestResultsDirectory;
var outputFilename = $"{testName}-{Output}.txt";
OutputFilePath = Path.Combine(outputDir, testName, outputFilename);
var outputDir = testContext.TestResultsDirectory;
var outputFilename = $"{testName}-{Output}.txt";
OutputFilePath = Path.Combine(outputDir, testName, outputFilename);

var baselineFilename = $"{testName}-{Baseline}.txt";
BaselineFilePath = Path.Combine(ScriptsFolder, baselineFilename);
}
var baselineFilename = $"{testName}-{Baseline}.txt";
BaselineFilePath = Path.Combine(ScriptsFolder, baselineFilename);
}

private string GetBaseFolder()
{
var testAssemply = GetType().Assembly;
private string GetBaseFolder()
{
var testAssemply = GetType().Assembly;

return Path.GetDirectoryName(testAssemply.Location);
}
return Path.GetDirectoryName(testAssemply.Location);
}

public override void RunTest(string fullId, Action<CodeAnalysisResult, string> verify)
{
LoadTestScripts(SetupFolder);
LoadTestScripts(ScriptsFolder);
base.RunTest(fullId, verify);
}
public override void RunTest(string fullId, Action<CodeAnalysisResult, string> verify)
{
LoadTestScripts(SetupFolder);
LoadTestScripts(ScriptsFolder);
base.RunTest(fullId, verify);
}

public void RunTest(string fullId)
public void RunTest(string fullId)
{
LoadTestScripts(SetupFolder);
LoadTestScripts(ScriptsFolder);
base.RunTest(fullId, RunVerification);
}

private void LoadTestScripts(string folder)
{
if (!Directory.Exists(folder))
{
LoadTestScripts(SetupFolder);
LoadTestScripts(ScriptsFolder);
base.RunTest(fullId, RunVerification);
return;
}

private void LoadTestScripts(string folder)
var directoryInfo = new DirectoryInfo(folder);

var scriptFilePaths = from file in directoryInfo.GetFiles("*" + SqlExtension)
where SqlExtension.Equals(file.Extension, StringComparison.OrdinalIgnoreCase)
select file.FullName;

foreach (var scriptFile in scriptFilePaths)
{
if (!Directory.Exists(folder))
try
{
return;
var contents = RuleTestUtils.ReadFileToString(scriptFile);
TestScripts.Add(Tuple.Create(contents, Path.GetFileName(scriptFile)));
Console.WriteLine($"Test file '{scriptFile}' loaded successfully");
}

var directoryInfo = new DirectoryInfo(folder);

var scriptFilePaths = from file in directoryInfo.GetFiles("*" + SqlExtension)
where SqlExtension.Equals(file.Extension, StringComparison.OrdinalIgnoreCase)
select file.FullName;

foreach (var scriptFile in scriptFilePaths)
catch (Exception ex)
{
try
{
var contents = RuleTestUtils.ReadFileToString(scriptFile);
TestScripts.Add(Tuple.Create(contents, Path.GetFileName(scriptFile)));
Console.WriteLine($"Test file '{scriptFile}' loaded successfully");
}
catch (Exception ex)
{
Console.WriteLine($"Error reading from file {scriptFile} with message '{ex.Message}'");
Console.WriteLine("Execution will continue...");
}
Console.WriteLine($"Error reading from file {scriptFile} with message '{ex.Message}'");
Console.WriteLine("Execution will continue...");
}
}
}

private void RunVerification(CodeAnalysisResult result, string resultsString)
{
var baseline = RuleTestUtils.ReadFileToString(BaselineFilePath);
RuleTestUtils.SaveStringToFile(resultsString, OutputFilePath);
private void RunVerification(CodeAnalysisResult result, string resultsString)
{
var baseline = RuleTestUtils.ReadFileToString(BaselineFilePath);
RuleTestUtils.SaveStringToFile(resultsString, OutputFilePath);

var loadedTestScriptFiles = ListScriptFilenames();
var loadedTestScriptFiles = ListScriptFilenames();

if (string.Compare(resultsString, baseline, false, System.Globalization.CultureInfo.CurrentCulture) != 0)
{
var failureMessage = new StringBuilder();

failureMessage.AppendLine($"The result is not the same as expected. Please compare actual output to baseline.");
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### Loaded Test Script Files ###");
failureMessage.AppendLine(loadedTestScriptFiles);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### View Baseline ###");
failureMessage.AppendLine(BaselineFilePath);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### View Action Output ###");
failureMessage.AppendLine(OutputFilePath);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### Test Folder ###");
failureMessage.AppendLine(ScriptsFolder);

Assert.Fail(failureMessage.ToString());
}
}

private string ListScriptFilenames()
if (string.Equals(resultsString, baseline, StringComparison.OrdinalIgnoreCase))
{
var loadedTestScriptFiles = new StringBuilder();
var failureMessage = new StringBuilder();

failureMessage.AppendLine($"The result is not the same as expected. Please compare actual output to baseline.");
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### Loaded Test Script Files ###");
failureMessage.AppendLine(loadedTestScriptFiles);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### View Baseline ###");
failureMessage.AppendLine(BaselineFilePath);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### View Action Output ###");
failureMessage.AppendLine(OutputFilePath);
failureMessage.AppendLine(string.Empty);
failureMessage.AppendLine($"### Test Folder ###");
failureMessage.AppendLine(ScriptsFolder);

Assert.Fail(failureMessage.ToString());
}
}

foreach (var scriptInfo in TestScripts)
{
var scriptPath = scriptInfo.Item2;
loadedTestScriptFiles.AppendLine(scriptPath);
}
private string ListScriptFilenames()
{
var loadedTestScriptFiles = new StringBuilder();

return loadedTestScriptFiles.ToString();
foreach (var scriptInfo in TestScripts)
{
var scriptPath = scriptInfo.Item2;
loadedTestScriptFiles.AppendLine(scriptPath);
}

return loadedTestScriptFiles.ToString();
}
}
63 changes: 31 additions & 32 deletions SqlServer.Rules.Test/Design/DesignTestCases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,47 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SqlServer.Rules.Design;

namespace SqlServer.Rules.Tests.Performance
namespace SqlServer.Rules.Tests.Performance;

[TestClass]
[TestCategory("Design")]
public class DesignTestCases : TestCasesBase
{
[TestClass]
[TestCategory("Design")]
public class DesignTestCases : TestCasesBase
[TestMethod]
public void TestAvoidNotForReplication()
{
[TestMethod]
public void TestAvoidNotForReplication()
{
var problems = GetTestCaseProblems(nameof(NotForReplication), NotForReplication.RuleId);
var problems = GetTestCaseProblems(nameof(NotForReplication), NotForReplication.RuleId);

const int expected = 4;
Assert.AreEqual(expected, problems.Count, $"Expected {expected} problem(s) to be found");
const int expected = 4;
Assert.AreEqual(expected, problems.Count, $"Expected {expected} problem(s) to be found");

Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "dbo_table2_trigger_1_not_for_replication.sql")));
Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "fk_table2_table1_1_not_for_replication.sql")));
Assert.IsTrue(problems.Count(problem => Comparer.Equals(problem.SourceName, "table3.sql")) == 2);
Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "dbo_table2_trigger_1_not_for_replication.sql")));
Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "fk_table2_table1_1_not_for_replication.sql")));
Assert.IsTrue(problems.Count(problem => Comparer.Equals(problem.SourceName, "table3.sql")) == 2);

Assert.IsTrue(problems.All(problem => Comparer.Equals(problem.Description, NotForReplication.Message)));
Assert.IsTrue(problems.All(problem => problem.Severity == SqlRuleProblemSeverity.Warning));
}
Assert.IsTrue(problems.All(problem => Comparer.Equals(problem.Description, NotForReplication.Message)));
Assert.IsTrue(problems.All(problem => problem.Severity == SqlRuleProblemSeverity.Warning));
}

[TestMethod]
public void TestMissingJoinPredicateFalsePositive()
{
var problems = GetTestCaseProblems(nameof(MissingJoinPredicateRule), MissingJoinPredicateRule.RuleId);
[TestMethod]
public void TestMissingJoinPredicateFalsePositive()
{
var problems = GetTestCaseProblems(nameof(MissingJoinPredicateRule), MissingJoinPredicateRule.RuleId);

const int expected = 1;
Assert.AreEqual(expected, problems.Count, $"Expected {expected} problem(s) to be found");
const int expected = 1;
Assert.AreEqual(expected, problems.Count, $"Expected {expected} problem(s) to be found");

Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "mtgfunc.sql")));
Assert.IsTrue(problems.Any(problem => Comparer.Equals(problem.SourceName, "mtgfunc.sql")));

Assert.IsTrue(problems.All(problem => Comparer.Equals(problem.Description, MissingJoinPredicateRule.MessageNoJoin)));
Assert.IsTrue(problems.All(problem => problem.Severity == SqlRuleProblemSeverity.Warning));
}
Assert.IsTrue(problems.All(problem => Comparer.Equals(problem.Description, MissingJoinPredicateRule.MessageNoJoin)));
Assert.IsTrue(problems.All(problem => problem.Severity == SqlRuleProblemSeverity.Warning));
}

[TestMethod]
public void TestTableMissingClusteredIndexRule()
{
var problems = GetTestCaseProblems(nameof(TableMissingClusteredIndexRule), TableMissingClusteredIndexRule.RuleId);
[TestMethod]
public void TestTableMissingClusteredIndexRule()
{
var problems = GetTestCaseProblems(nameof(TableMissingClusteredIndexRule), TableMissingClusteredIndexRule.RuleId);

Assert.AreEqual(0, problems.Count, "Expected 0 problems to be found");
}
Assert.AreEqual(0, problems.Count, "Expected 0 problems to be found");
}
}
3 changes: 0 additions & 3 deletions SqlServer.Rules.Test/Directory.Build.props

This file was deleted.

Loading

0 comments on commit ed4a4e1

Please sign in to comment.