diff --git a/.reviewmark.yaml b/.reviewmark.yaml
index 6835c54..4aff849 100644
--- a/.reviewmark.yaml
+++ b/.reviewmark.yaml
@@ -20,15 +20,17 @@ reviews:
- id: TestResults-Model
title: Review of TestResults Model
paths:
+ - "docs/reqstream/model.yaml"
+ - "docs/design/model.md"
- "src/DemaConsulting.TestResults/*.cs"
+ - "test/DemaConsulting.TestResults.Tests/*.cs"
- "!**/obj/**"
- - "docs/design/model.md"
- - "docs/reqstream/model.yaml"
- id: TestResults-Serialization
title: Review of TestResults Serialization
paths:
+ - "docs/reqstream/serialization.yaml"
+ - "docs/design/serialization.md"
- "src/DemaConsulting.TestResults/IO/**/*.cs"
+ - "test/DemaConsulting.TestResults.Tests/IO/**/*.cs"
- "!**/obj/**"
- - "docs/design/serialization.md"
- - "docs/reqstream/serialization.yaml"
diff --git a/docs/design/model.md b/docs/design/model.md
index 293f3a2..ac1e892 100644
--- a/docs/design/model.md
+++ b/docs/design/model.md
@@ -7,9 +7,10 @@ It is deliberately free of serialization concerns — it knows nothing about TRX
XML — so that it can serve as a neutral interchange format between different serializers
and consumers.
-The model consists of three types:
+The model consists of four types:
- `TestOutcome` — an enumeration of all possible test execution outcomes
+- `TestOutcomeExtensions` — extension methods that classify a `TestOutcome` into logical categories
- `TestResult` — a single test case result, including timing, output, and error information
- `TestResults` — a collection of `TestResult` objects representing a complete test run
diff --git a/docs/reqstream/model.yaml b/docs/reqstream/model.yaml
index 5dbea55..bc5cd10 100644
--- a/docs/reqstream/model.yaml
+++ b/docs/reqstream/model.yaml
@@ -63,7 +63,7 @@ sections:
pass or fail result. This status is important for test frameworks that support
inconclusive results and helps distinguish ambiguous test executions from failures.
tests:
- - TestOutcome_IsExecuted_InconclusiveOutcome_ReturnsTrue
+ - TestOutcome_IsExecuted_AllOutcomes_ReturnsExpectedResult
- TrxExampleTests_Deserialize_Example1Trx_ReturnsAllTestResults
- id: TestResults-Mdl-AbortedOutcome
@@ -82,7 +82,7 @@ sections:
started. This status is important for test frameworks that support asynchronous or
deferred test execution and helps track test execution state.
tests:
- - TestOutcome_IsExecuted_InconclusiveOutcome_ReturnsTrue
+ - TestOutcome_IsExecuted_AllOutcomes_ReturnsExpectedResult
- TestOutcome_IsPassed_PassedOutcome_ReturnsTrue
- TrxExampleTests_Deserialize_Example1Trx_ReturnsAllTestResults
diff --git a/src/DemaConsulting.TestResults/TestOutcome.cs b/src/DemaConsulting.TestResults/TestOutcome.cs
index 7bd8b64..e041fc9 100644
--- a/src/DemaConsulting.TestResults/TestOutcome.cs
+++ b/src/DemaConsulting.TestResults/TestOutcome.cs
@@ -21,7 +21,7 @@
namespace DemaConsulting.TestResults;
///
-/// TestOutcome enum
+/// Defines the possible outcomes for a test case execution.
///
public enum TestOutcome
{
diff --git a/src/DemaConsulting.TestResults/TestResult.cs b/src/DemaConsulting.TestResults/TestResult.cs
index 9b48932..a2de702 100644
--- a/src/DemaConsulting.TestResults/TestResult.cs
+++ b/src/DemaConsulting.TestResults/TestResult.cs
@@ -21,7 +21,7 @@
namespace DemaConsulting.TestResults;
///
-/// TestResult class
+/// Represents the result of a single test case execution.
///
public sealed class TestResult
{
diff --git a/src/DemaConsulting.TestResults/TestResults.cs b/src/DemaConsulting.TestResults/TestResults.cs
index bec33be..5323c0b 100644
--- a/src/DemaConsulting.TestResults/TestResults.cs
+++ b/src/DemaConsulting.TestResults/TestResults.cs
@@ -21,7 +21,7 @@
namespace DemaConsulting.TestResults;
///
-/// TestResults class
+/// Represents a collection of test results for a complete test run.
///
public sealed class TestResults
{
diff --git a/test/DemaConsulting.TestResults.Tests/TestOutcomeTests.cs b/test/DemaConsulting.TestResults.Tests/TestOutcomeTests.cs
index 4286a2e..ea63099 100644
--- a/test/DemaConsulting.TestResults.Tests/TestOutcomeTests.cs
+++ b/test/DemaConsulting.TestResults.Tests/TestOutcomeTests.cs
@@ -76,7 +76,7 @@ public void TestOutcome_IsFailed_FailedOutcome_ReturnsTrue()
/// Test the IsExecuted method for all outcomes
///
[TestMethod]
- public void TestOutcome_IsExecuted_InconclusiveOutcome_ReturnsTrue()
+ public void TestOutcome_IsExecuted_AllOutcomes_ReturnsExpectedResult()
{
Assert.IsTrue(TestOutcome.Error.IsExecuted());
Assert.IsTrue(TestOutcome.Failed.IsExecuted());
diff --git a/test/DemaConsulting.TestResults.Tests/TestResultTests.cs b/test/DemaConsulting.TestResults.Tests/TestResultTests.cs
new file mode 100644
index 0000000..b9aa4e7
--- /dev/null
+++ b/test/DemaConsulting.TestResults.Tests/TestResultTests.cs
@@ -0,0 +1,245 @@
+// Copyright(c) 2025 DEMA Consulting
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace DemaConsulting.TestResults.Tests;
+
+///
+/// Tests for the default property values of
+///
+[TestClass]
+public class TestResultTests
+{
+ ///
+ /// Tests that defaults to a non-empty GUID
+ ///
+ [TestMethod]
+ public void TestResult_TestId_Default_IsNotEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - TestId should be auto-generated and not the empty GUID
+ Assert.AreNotEqual(Guid.Empty, result.TestId);
+ }
+
+ ///
+ /// Tests that two separate instances have different values,
+ /// proving that each instance generates its own unique identifier
+ ///
+ [TestMethod]
+ public void TestResult_TestId_TwoInstances_AreUnique()
+ {
+ // Arrange - create two independent TestResult instances
+
+ // Act
+ var result1 = new TestResult();
+ var result2 = new TestResult();
+
+ // Assert - each instance should have a distinct TestId
+ Assert.AreNotEqual(result1.TestId, result2.TestId);
+ }
+
+ ///
+ /// Tests that defaults to a non-empty GUID
+ ///
+ [TestMethod]
+ public void TestResult_ExecutionId_Default_IsNotEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - ExecutionId should be auto-generated and not the empty GUID
+ Assert.AreNotEqual(Guid.Empty, result.ExecutionId);
+ }
+
+ ///
+ /// Tests that two separate instances have different
+ /// values, proving that each instance generates its own unique identifier
+ ///
+ [TestMethod]
+ public void TestResult_ExecutionId_TwoInstances_AreUnique()
+ {
+ // Arrange - create two independent TestResult instances
+
+ // Act
+ var result1 = new TestResult();
+ var result2 = new TestResult();
+
+ // Assert - each instance should have a distinct ExecutionId
+ Assert.AreNotEqual(result1.ExecutionId, result2.ExecutionId);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_Name_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - Name should default to string.Empty
+ Assert.AreEqual(string.Empty, result.Name);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_CodeBase_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - CodeBase should default to string.Empty
+ Assert.AreEqual(string.Empty, result.CodeBase);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_ClassName_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - ClassName should default to string.Empty
+ Assert.AreEqual(string.Empty, result.ClassName);
+ }
+
+ ///
+ /// Tests that defaults to the current machine name
+ ///
+ [TestMethod]
+ public void TestResult_ComputerName_Default_IsEnvironmentMachineName()
+ {
+ // Arrange - record the expected machine name before construction
+ var expectedComputerName = Environment.MachineName;
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - ComputerName should match the environment's machine name
+ Assert.AreEqual(expectedComputerName, result.ComputerName);
+ }
+
+ ///
+ /// Tests that defaults to
+ ///
+ [TestMethod]
+ public void TestResult_Duration_Default_IsZero()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - Duration should default to TimeSpan.Zero
+ Assert.AreEqual(TimeSpan.Zero, result.Duration);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_SystemOutput_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - SystemOutput should default to string.Empty
+ Assert.AreEqual(string.Empty, result.SystemOutput);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_SystemError_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - SystemError should default to string.Empty
+ Assert.AreEqual(string.Empty, result.SystemError);
+ }
+
+ ///
+ /// Tests that defaults to
+ ///
+ [TestMethod]
+ public void TestResult_Outcome_Default_IsNotExecuted()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - Outcome should default to TestOutcome.NotExecuted
+ Assert.AreEqual(TestOutcome.NotExecuted, result.Outcome);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_ErrorMessage_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - ErrorMessage should default to string.Empty
+ Assert.AreEqual(string.Empty, result.ErrorMessage);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResult_ErrorStackTrace_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResult with default property values
+
+ // Act
+ var result = new TestResult();
+
+ // Assert - ErrorStackTrace should default to string.Empty
+ Assert.AreEqual(string.Empty, result.ErrorStackTrace);
+ }
+}
diff --git a/test/DemaConsulting.TestResults.Tests/TestResultsTests.cs b/test/DemaConsulting.TestResults.Tests/TestResultsTests.cs
new file mode 100644
index 0000000..312c029
--- /dev/null
+++ b/test/DemaConsulting.TestResults.Tests/TestResultsTests.cs
@@ -0,0 +1,122 @@
+// Copyright(c) 2025 DEMA Consulting
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace DemaConsulting.TestResults.Tests;
+
+///
+/// Tests for the default property values of
+///
+[TestClass]
+public class TestResultsTests
+{
+ ///
+ /// Tests that defaults to a non-empty GUID
+ ///
+ [TestMethod]
+ public void TestResults_Id_Default_IsNotEmpty()
+ {
+ // Arrange - create a new TestResults with default property values
+
+ // Act
+ var results = new TestResults();
+
+ // Assert - Id should be auto-generated and not the empty GUID
+ Assert.AreNotEqual(Guid.Empty, results.Id);
+ }
+
+ ///
+ /// Tests that two separate instances have different values,
+ /// proving that each instance generates its own unique identifier
+ ///
+ [TestMethod]
+ public void TestResults_Id_TwoInstances_AreUnique()
+ {
+ // Arrange - create two independent TestResults instances
+
+ // Act
+ var results1 = new TestResults();
+ var results2 = new TestResults();
+
+ // Assert - each instance should have a distinct Id
+ Assert.AreNotEqual(results1.Id, results2.Id);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResults_Name_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResults with default property values
+
+ // Act
+ var results = new TestResults();
+
+ // Assert - Name should default to string.Empty
+ Assert.AreEqual(string.Empty, results.Name);
+ }
+
+ ///
+ /// Tests that defaults to an empty string
+ ///
+ [TestMethod]
+ public void TestResults_UserName_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResults with default property values
+
+ // Act
+ var results = new TestResults();
+
+ // Assert - UserName should default to string.Empty
+ Assert.AreEqual(string.Empty, results.UserName);
+ }
+
+ ///
+ /// Tests that defaults to a non-null empty list
+ ///
+ [TestMethod]
+ public void TestResults_Results_Default_IsNotNull()
+ {
+ // Arrange - create a new TestResults with default property values
+
+ // Act
+ var results = new TestResults();
+
+ // Assert - Results list should be initialized (not null)
+ Assert.IsNotNull(results.Results);
+ }
+
+ ///
+ /// Tests that defaults to an empty list
+ ///
+ [TestMethod]
+ public void TestResults_Results_Default_IsEmpty()
+ {
+ // Arrange - create a new TestResults with default property values
+
+ // Act
+ var results = new TestResults();
+
+ // Assert - Results list should contain no elements
+ Assert.HasCount(0, results.Results);
+ }
+}