diff --git a/src/DemaConsulting.NuGet.CacheTool/Validation.cs b/src/DemaConsulting.NuGet.CacheTool/Validation.cs
index d0968de..598fee1 100644
--- a/src/DemaConsulting.NuGet.CacheTool/Validation.cs
+++ b/src/DemaConsulting.NuGet.CacheTool/Validation.cs
@@ -101,65 +101,22 @@ private static void PrintValidationHeader(Context context)
/// The test results collection.
private static void RunVersionTest(Context context, DemaConsulting.TestResults.TestResults testResults)
{
- var startTime = DateTime.UtcNow;
- var test = CreateTestResult("NuGetCache_VersionDisplay");
-
- try
- {
- using var tempDir = new TemporaryDirectory();
- var logFile = PathHelpers.SafePathCombine(tempDir.DirectoryPath, "version-test.log");
-
- // Build command line arguments
- var args = new List
- {
- "--silent",
- "--log", logFile,
- "--version"
- };
-
- // Run the program
- int exitCode;
- using (var testContext = Context.Create([.. args]))
- {
- Program.Run(testContext);
- exitCode = testContext.ExitCode;
- }
-
- // Check if execution succeeded
- if (exitCode == 0)
+ RunValidationTest(
+ context,
+ testResults,
+ "NuGetCache_VersionDisplay",
+ "Version Display Test",
+ ["--version"],
+ logContent =>
{
- // Read log content
- var logContent = File.ReadAllText(logFile);
-
// Verify version string is in log (version contains dots like 0.0.0)
- if (!string.IsNullOrWhiteSpace(logContent) &&
- logContent.Split('.').Length >= 3)
- {
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Passed;
- context.WriteLine($"✓ Version Display Test - PASSED");
- }
- else
+ if (!string.IsNullOrWhiteSpace(logContent) && logContent.Split('.').Length >= 3)
{
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
- test.ErrorMessage = "Version string not found in log";
- context.WriteError($"✗ Version Display Test - FAILED: Version string not found in log");
+ return null;
}
- }
- else
- {
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
- test.ErrorMessage = $"Program exited with code {exitCode}";
- context.WriteError($"✗ Version Display Test - FAILED: Exit code {exitCode}");
- }
- }
- // Generic catch is justified here as this is a test framework - any exception should be
- // recorded as a test failure to ensure robust test execution and reporting.
- catch (Exception ex)
- {
- HandleTestException(test, context, "Version Display Test", ex);
- }
- FinalizeTestResult(test, startTime, testResults);
+ return "Version string not found in log";
+ });
}
///
@@ -169,64 +126,22 @@ private static void RunVersionTest(Context context, DemaConsulting.TestResults.T
/// The test results collection.
private static void RunHelpTest(Context context, DemaConsulting.TestResults.TestResults testResults)
{
- var startTime = DateTime.UtcNow;
- var test = CreateTestResult("NuGetCache_HelpDisplay");
-
- try
- {
- using var tempDir = new TemporaryDirectory();
- var logFile = PathHelpers.SafePathCombine(tempDir.DirectoryPath, "help-test.log");
-
- // Build command line arguments
- var args = new List
+ RunValidationTest(
+ context,
+ testResults,
+ "NuGetCache_HelpDisplay",
+ "Help Display Test",
+ ["--help"],
+ logContent =>
{
- "--silent",
- "--log", logFile,
- "--help"
- };
-
- // Run the program
- int exitCode;
- using (var testContext = Context.Create([.. args]))
- {
- Program.Run(testContext);
- exitCode = testContext.ExitCode;
- }
-
- // Check if execution succeeded
- if (exitCode == 0)
- {
- // Read log content
- var logContent = File.ReadAllText(logFile);
-
// Verify help text is in log
if (logContent.Contains("Usage:") && logContent.Contains("Options:"))
{
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Passed;
- context.WriteLine($"✓ Help Display Test - PASSED");
- }
- else
- {
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
- test.ErrorMessage = "Help text not found in log";
- context.WriteError($"✗ Help Display Test - FAILED: Help text not found in log");
+ return null;
}
- }
- else
- {
- test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
- test.ErrorMessage = $"Program exited with code {exitCode}";
- context.WriteError($"✗ Help Display Test - FAILED: Exit code {exitCode}");
- }
- }
- // Generic catch is justified here as this is a test framework - any exception should be
- // recorded as a test failure to ensure robust test execution and reporting.
- catch (Exception ex)
- {
- HandleTestException(test, context, "Help Display Test", ex);
- }
- FinalizeTestResult(test, startTime, testResults);
+ return "Help text not found in log";
+ });
}
///
@@ -235,22 +150,56 @@ private static void RunHelpTest(Context context, DemaConsulting.TestResults.Test
/// The context for output.
/// The test results collection.
private static void RunCachePackageTest(Context context, DemaConsulting.TestResults.TestResults testResults)
+ {
+ RunValidationTest(
+ context,
+ testResults,
+ "NuGetCache_CachePackage",
+ "Cache Package Test",
+ ["DemaConsulting.NuGet.Caching:0.1.0"],
+ logContent =>
+ {
+ // Verify that a non-empty path was written to the log
+ if (!string.IsNullOrWhiteSpace(logContent))
+ {
+ return null;
+ }
+
+ return "Package path not found in log";
+ });
+ }
+
+ ///
+ /// Runs a validation test with common test execution logic.
+ ///
+ /// The context for output.
+ /// The test results collection.
+ /// The name of the test.
+ /// The display name for console output.
+ /// Additional command-line arguments for the test.
+ ///
+ /// Function to validate test results. Receives log content and returns null on
+ /// success or an error message on failure.
+ ///
+ private static void RunValidationTest(
+ Context context,
+ DemaConsulting.TestResults.TestResults testResults,
+ string testName,
+ string displayName,
+ string[] additionalArgs,
+ Func validator)
{
var startTime = DateTime.UtcNow;
- var test = CreateTestResult("NuGetCache_CachePackage");
+ var test = CreateTestResult(testName);
try
{
using var tempDir = new TemporaryDirectory();
- var logFile = PathHelpers.SafePathCombine(tempDir.DirectoryPath, "cache-package-test.log");
+ var logFile = PathHelpers.SafePathCombine(tempDir.DirectoryPath, $"{testName}.log");
- // Build command line arguments to cache a known package
- var args = new List
- {
- "--silent",
- "--log", logFile,
- "DemaConsulting.NuGet.Caching:0.1.0"
- };
+ // Build command line arguments: always use --silent and --log for consistent capture
+ var args = new List { "--silent", "--log", logFile };
+ args.AddRange(additionalArgs);
// Run the program
int exitCode;
@@ -263,34 +212,34 @@ private static void RunCachePackageTest(Context context, DemaConsulting.TestResu
// Check if execution succeeded
if (exitCode == 0)
{
- // Read log content to verify a path was written
+ // Read log content and invoke the validator
var logContent = File.ReadAllText(logFile);
+ var errorMessage = validator(logContent);
- // Verify that a non-empty path was written to the log
- if (!string.IsNullOrWhiteSpace(logContent))
+ if (errorMessage == null)
{
test.Outcome = DemaConsulting.TestResults.TestOutcome.Passed;
- context.WriteLine($"✓ Cache Package Test - PASSED");
+ context.WriteLine($"✓ {displayName} - PASSED");
}
else
{
test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
- test.ErrorMessage = "Package path not found in log";
- context.WriteError($"✗ Cache Package Test - FAILED: Package path not found in log");
+ test.ErrorMessage = errorMessage;
+ context.WriteError($"✗ {displayName} - FAILED: {errorMessage}");
}
}
else
{
test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed;
test.ErrorMessage = $"Program exited with code {exitCode}";
- context.WriteError($"✗ Cache Package Test - FAILED: Exit code {exitCode}");
+ context.WriteError($"✗ {displayName} - FAILED: Exit code {exitCode}");
}
}
// Generic catch is justified here as this is a test framework - any exception should be
// recorded as a test failure to ensure robust test execution and reporting.
catch (Exception ex)
{
- HandleTestException(test, context, "Cache Package Test", ex);
+ HandleTestException(test, context, displayName, ex);
}
FinalizeTestResult(test, startTime, testResults);
diff --git a/test/DemaConsulting.NuGet.CacheTool.Tests/ContextTests.cs b/test/DemaConsulting.NuGet.CacheTool.Tests/ContextTests.cs
index f112e95..0bcecb5 100644
--- a/test/DemaConsulting.NuGet.CacheTool.Tests/ContextTests.cs
+++ b/test/DemaConsulting.NuGet.CacheTool.Tests/ContextTests.cs
@@ -270,4 +270,80 @@ public void Context_WriteLine_Silent_DoesNotWriteToConsole()
Console.SetOut(originalOut);
}
}
+
+ ///
+ /// Test WriteError sets exit code to 1.
+ ///
+ [TestMethod]
+ public void Context_WriteError_SetsErrorExitCode()
+ {
+ // Arrange
+ var originalOut = Console.Out;
+ try
+ {
+ using var outWriter = new StringWriter();
+ Console.SetOut(outWriter);
+ using var context = Context.Create([]);
+
+ // Act
+ Assert.AreEqual(0, context.ExitCode);
+ context.WriteError("Test error");
+
+ // Assert
+ Assert.AreEqual(1, context.ExitCode);
+ }
+ finally
+ {
+ Console.SetOut(originalOut);
+ }
+ }
+
+ ///
+ /// Test WriteError writes message to console when not silent.
+ ///
+ [TestMethod]
+ public void Context_WriteError_NotSilent_WritesToConsole()
+ {
+ // Arrange
+ var originalOut = Console.Out;
+ try
+ {
+ using var outWriter = new StringWriter();
+ Console.SetOut(outWriter);
+ using var context = Context.Create([]);
+
+ // Act
+ context.WriteError("Test error message");
+
+ // Assert
+ var output = outWriter.ToString();
+ Assert.Contains("Test error message", output);
+ }
+ finally
+ {
+ Console.SetOut(originalOut);
+ }
+ }
+
+ ///
+ /// Test creating a context with --log flag but no value throws ArgumentException.
+ ///
+ [TestMethod]
+ public void Context_Create_LogFlag_WithoutValue_ThrowsArgumentException()
+ {
+ // Act & Assert
+ var exception = Assert.Throws(() => Context.Create(["--log"]));
+ Assert.Contains("--log", exception.Message);
+ }
+
+ ///
+ /// Test creating a context with --results flag but no value throws ArgumentException.
+ ///
+ [TestMethod]
+ public void Context_Create_ResultsFlag_WithoutValue_ThrowsArgumentException()
+ {
+ // Act & Assert
+ var exception = Assert.Throws(() => Context.Create(["--results"]));
+ Assert.Contains("--results", exception.Message);
+ }
}
diff --git a/test/DemaConsulting.NuGet.CacheTool.Tests/IntegrationTests.cs b/test/DemaConsulting.NuGet.CacheTool.Tests/IntegrationTests.cs
index 4a9299a..3ea0437 100644
--- a/test/DemaConsulting.NuGet.CacheTool.Tests/IntegrationTests.cs
+++ b/test/DemaConsulting.NuGet.CacheTool.Tests/IntegrationTests.cs
@@ -139,6 +139,45 @@ public void IntegrationTest_ValidateWithResults_GeneratesTrxFile()
}
}
+ ///
+ /// Test that validate with results flag generates JUnit XML file.
+ ///
+ [TestMethod]
+ public void IntegrationTest_ValidateWithResults_GeneratesJUnitFile()
+ {
+ // Arrange
+ var resultsFile = Path.GetTempFileName();
+ resultsFile = Path.ChangeExtension(resultsFile, ".xml");
+
+ try
+ {
+ // Act
+ var exitCode = Runner.Run(
+ out var _,
+ "dotnet",
+ _dllPath,
+ "--validate",
+ "--results",
+ resultsFile);
+
+ // Assert
+ Assert.AreEqual(0, exitCode);
+ Assert.IsTrue(File.Exists(resultsFile), "JUnit results file was not created");
+
+ var content = File.ReadAllText(resultsFile);
+ Assert.Contains("
/// Test that silent flag suppresses output.
///
diff --git a/test/DemaConsulting.NuGet.CacheTool.Tests/ProgramTests.cs b/test/DemaConsulting.NuGet.CacheTool.Tests/ProgramTests.cs
index 9115ec6..6aec070 100644
--- a/test/DemaConsulting.NuGet.CacheTool.Tests/ProgramTests.cs
+++ b/test/DemaConsulting.NuGet.CacheTool.Tests/ProgramTests.cs
@@ -161,4 +161,30 @@ public void Program_Version_ReturnsNonEmptyString()
// Assert
Assert.IsFalse(string.IsNullOrWhiteSpace(version));
}
+
+ ///
+ /// Test that Run with validate flag and unsupported results format sets error exit code.
+ ///
+ [TestMethod]
+ public void Program_Run_WithValidateAndUnsupportedResultsFormat_SetsErrorExitCode()
+ {
+ // Arrange
+ var originalOut = Console.Out;
+ try
+ {
+ using var outWriter = new StringWriter();
+ Console.SetOut(outWriter);
+ using var context = Context.Create(["--validate", "--silent", "--results", "output.json"]);
+
+ // Act
+ Program.Run(context);
+
+ // Assert - unsupported format should cause an error
+ Assert.AreEqual(1, context.ExitCode);
+ }
+ finally
+ {
+ Console.SetOut(originalOut);
+ }
+ }
}