diff --git a/src/DemaConsulting.BuildMark/Configuration/BuildMarkConfigReader.cs b/src/DemaConsulting.BuildMark/Configuration/BuildMarkConfigReader.cs index a9dec7a3..893452db 100644 --- a/src/DemaConsulting.BuildMark/Configuration/BuildMarkConfigReader.cs +++ b/src/DemaConsulting.BuildMark/Configuration/BuildMarkConfigReader.cs @@ -478,14 +478,9 @@ private static void ParseSections( return; } - foreach (var item in sequence.Children) - { - var section = ParseSectionItem(filePath, item, issues); - if (!string.IsNullOrEmpty(section.Id) && !string.IsNullOrEmpty(section.Title)) - { - sections.Add(section); - } - } + sections.AddRange(sequence.Children + .Select(item => ParseSectionItem(filePath, item, issues)) + .Where(section => !string.IsNullOrEmpty(section.Id) && !string.IsNullOrEmpty(section.Title))); } /// diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnector.cs b/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnector.cs index 5c37975d..06caaece 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnector.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnector.cs @@ -266,13 +266,11 @@ private static (VersionTag toVersion, string toHash) DetermineTargetVersion( } // Find the latest tag that points to the current commit - foreach (var tagVersion in lookupData.TagVersions) + var matchingTagVersion = lookupData.TagVersions.FirstOrDefault(tv => + lookupData.TagToCommitHash.TryGetValue(tv.Tag, out var tagHash) && tagHash == toHash); + if (matchingTagVersion is not null) { - if (lookupData.TagToCommitHash.TryGetValue(tagVersion.Tag, out var tagHash) && - tagHash == toHash) - { - return (tagVersion, toHash); - } + return (matchingTagVersion, toHash); } throw new InvalidOperationException( diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubGraphQLClient.cs b/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubGraphQLClient.cs index 6447a642..8d5925a8 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubGraphQLClient.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubGraphQLClient.cs @@ -110,7 +110,7 @@ public async Task> GetCommitsAsync( { try { - List allCommitShas = new(); + List allCommitShas = []; string? afterCursor = null; bool hasNextPage; @@ -192,7 +192,7 @@ public async Task> GetReleasesAsync( { try { - List allReleaseNodes = new(); + List allReleaseNodes = []; string? afterCursor = null; bool hasNextPage; @@ -265,7 +265,7 @@ public async Task> FindIssueIdsLinkedToPullRequestAsync( { try { - List allIssueNumbers = new(); + List allIssueNumbers = []; string? afterCursor = null; bool hasNextPage; @@ -340,7 +340,7 @@ public async Task> GetAllTagsAsync( { try { - List allTagNodes = new(); + List allTagNodes = []; string? afterCursor = null; bool hasNextPage; @@ -414,7 +414,7 @@ public async Task> GetPullRequestsAsync( { try { - List allPullRequestNodes = new(); + List allPullRequestNodes = []; string? afterCursor = null; bool hasNextPage; @@ -498,7 +498,7 @@ public async Task> GetAllIssuesAsync( { try { - List allIssueNodes = new(); + List allIssueNodes = []; string? afterCursor = null; bool hasNextPage; diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubRepoConnector.cs b/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubRepoConnector.cs index 308f5b92..2e93434f 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubRepoConnector.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/GitHub/GitHubRepoConnector.cs @@ -609,9 +609,9 @@ private static int DetermineSearchStartIndex(int toIndex, int releaseCount) string repo) { // Initialize collections for tracking changes - HashSet allChangeIds = new(); - List bugs = new(); - List nonBugChanges = new(); + HashSet allChangeIds = []; + List bugs = []; + List nonBugChanges = []; // Process each commit that has an associated PR foreach (var pr in commitsInRange @@ -909,7 +909,7 @@ private static async Task> GetAllIssuesAsync( private static List GetCommitsInRange(IReadOnlyList commits, string? fromHash, string toHash) { // Initialize collection and state tracking - List result = new(); + List result = []; var foundTo = false; // Iterate through commits from newest to oldest diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/ItemControlsParser.cs b/src/DemaConsulting.BuildMark/RepoConnectors/ItemControlsParser.cs index 3d9b2888..47c8bcca 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/ItemControlsParser.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/ItemControlsParser.cs @@ -158,9 +158,24 @@ private static bool IsOpeningFence(string line, out string fence) foreach (var rawLine in blockLines) { var (key, value) = ParseKeyValue(rawLine); - if (key != null) + switch (key) { - ApplyBlockLineValue(key, value!, ref visibility, ref type, ref affectedVersions); + case "visibility" when value is VisibilityPublic or VisibilityInternal: + visibility = value; + break; + + case "type" when value is TypeBug or TypeFeature: + type = value; + break; + + case "affected-versions" when !string.IsNullOrEmpty(value): + var parsed = VersionIntervalSet.Parse(value!); + if (parsed.Intervals.Count > 0) + { + affectedVersions = parsed; + } + + break; } } @@ -194,40 +209,4 @@ private static (string? key, string? value) ParseKeyValue(string rawLine) return (line[..colonIdx].Trim().ToLowerInvariant(), line[(colonIdx + 1)..].Trim()); } - - /// - /// Applies a recognized key-value pair to the appropriate output parameter. - /// - /// Lowercased key from the buildmark block line. - /// Trimmed value from the buildmark block line. - /// Current visibility value (updated if key is "visibility"). - /// Current type value (updated if key is "type"). - /// Current affected versions (updated if key is "affected-versions"). - private static void ApplyBlockLineValue( - string key, - string value, - ref string? visibility, - ref string? type, - ref VersionIntervalSet? affectedVersions) - { - switch (key) - { - case "visibility" when value is VisibilityPublic or VisibilityInternal: - visibility = value; - break; - - case "type" when value is TypeBug or TypeFeature: - type = value; - break; - - case "affected-versions" when !string.IsNullOrEmpty(value): - var parsed = VersionIntervalSet.Parse(value); - if (parsed.Intervals.Count > 0) - { - affectedVersions = parsed; - } - - break; - } - } } diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/Mock/MockRepoConnector.cs b/src/DemaConsulting.BuildMark/RepoConnectors/Mock/MockRepoConnector.cs index 312523ca..2b6a83a9 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/Mock/MockRepoConnector.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/Mock/MockRepoConnector.cs @@ -343,9 +343,9 @@ private static (List bugs, List nonBugChanges, HashSet changes) { // Initialize collections for categorized changes - HashSet allChangeIds = new(); - List bugs = new(); - List nonBugChanges = new(); + HashSet allChangeIds = []; + List bugs = []; + List nonBugChanges = []; // Process and categorize each change foreach (var change in changes) @@ -504,7 +504,7 @@ private static List GetPullRequestsForTagRange(string? fromTagName, stri private List BuildChangesFromPullRequests(List prs) { // Initialize collection for changes - List changes = new(); + List changes = []; // Process each pull request foreach (var pr in prs) diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/RepoConnectorBase.cs b/src/DemaConsulting.BuildMark/RepoConnectors/RepoConnectorBase.cs index f9c017d9..914c5936 100644 --- a/src/DemaConsulting.BuildMark/RepoConnectors/RepoConnectorBase.cs +++ b/src/DemaConsulting.BuildMark/RepoConnectors/RepoConnectorBase.cs @@ -71,7 +71,7 @@ public void Configure(IReadOnlyList rules, IReadOnlyList Items)> result = new(); + List<(string SectionId, string SectionTitle, IReadOnlyList Items)> result = []; // Process each configured section in order foreach (var section in _sections) diff --git a/src/DemaConsulting.BuildMark/Version/VersionComparable.cs b/src/DemaConsulting.BuildMark/Version/VersionComparable.cs index 24b2f8b1..e0d83638 100644 --- a/src/DemaConsulting.BuildMark/Version/VersionComparable.cs +++ b/src/DemaConsulting.BuildMark/Version/VersionComparable.cs @@ -126,14 +126,9 @@ public int CompareTo(PreReleaseSegment other) // Convert each part into either numeric or text segment for (var i = 0; i < parts.Length; i++) { - if (int.TryParse(parts[i], out var numericValue)) - { - segments[i] = new PreReleaseSegment(numericValue); - } - else - { - segments[i] = new PreReleaseSegment(parts[i]); - } + segments[i] = int.TryParse(parts[i], out var numericValue) + ? new PreReleaseSegment(numericValue) + : new PreReleaseSegment(parts[i]); } return segments; diff --git a/src/DemaConsulting.BuildMark/Version/VersionInterval.cs b/src/DemaConsulting.BuildMark/Version/VersionInterval.cs index 7ff76547..dd70f43c 100644 --- a/src/DemaConsulting.BuildMark/Version/VersionInterval.cs +++ b/src/DemaConsulting.BuildMark/Version/VersionInterval.cs @@ -61,13 +61,9 @@ public bool Contains(VersionComparable version) if (LowerBound != null) { var lowerBoundVersion = VersionComparable.TryCreate(LowerBound); - if (lowerBoundVersion != null) + if (lowerBoundVersion != null && IsBelowLowerBound(version.CompareTo(lowerBoundVersion), LowerInclusive)) { - var lowerComparison = version.CompareTo(lowerBoundVersion); - if (lowerComparison < 0 || (lowerComparison == 0 && !LowerInclusive)) - { - return false; - } + return false; } } @@ -75,13 +71,9 @@ public bool Contains(VersionComparable version) if (UpperBound != null) { var upperBoundVersion = VersionComparable.TryCreate(UpperBound); - if (upperBoundVersion != null) + if (upperBoundVersion != null && IsAboveUpperBound(version.CompareTo(upperBoundVersion), UpperInclusive)) { - var upperComparison = version.CompareTo(upperBoundVersion); - if (upperComparison > 0 || (upperComparison == 0 && !UpperInclusive)) - { - return false; - } + return false; } } @@ -98,6 +90,18 @@ public bool Contains(VersionTag version) return Contains(version.Semantic.Comparable); } + /// + /// Returns true when a comparison result places a version below the lower bound. + /// + private static bool IsBelowLowerBound(int comparison, bool inclusive) => + comparison < 0 || (comparison == 0 && !inclusive); + + /// + /// Returns true when a comparison result places a version above the upper bound. + /// + private static bool IsAboveUpperBound(int comparison, bool inclusive) => + comparison > 0 || (comparison == 0 && !inclusive); + /// /// Parses a version interval from text. /// diff --git a/src/DemaConsulting.BuildMark/Version/VersionIntervalSet.cs b/src/DemaConsulting.BuildMark/Version/VersionIntervalSet.cs index 7d36537b..9775b8f9 100644 --- a/src/DemaConsulting.BuildMark/Version/VersionIntervalSet.cs +++ b/src/DemaConsulting.BuildMark/Version/VersionIntervalSet.cs @@ -65,7 +65,7 @@ public static VersionIntervalSet Parse(string text) { // Walk character by character tracking bracket depth // Split on ',' when depth==0 (these separate intervals) - List intervals = new(); + List intervals = []; var depth = 0; var pos = 0; var tokenStart = 0; @@ -96,11 +96,7 @@ public static VersionIntervalSet Parse(string text) } // Advance past closing bracket and any trailing comma/whitespace - pos++; - while (pos < text.Length && (text[pos] == ',' || char.IsWhiteSpace(text[pos]))) - { - pos++; - } + pos = SkipCommaAndWhitespace(text, pos + 1); tokenStart = pos; continue; } @@ -112,4 +108,17 @@ public static VersionIntervalSet Parse(string text) // Return VersionIntervalSet wrapping the list return new VersionIntervalSet(intervals); } + + /// + /// Advances past any comma and whitespace characters starting at . + /// + private static int SkipCommaAndWhitespace(string text, int pos) + { + while (pos < text.Length && (text[pos] == ',' || char.IsWhiteSpace(text[pos]))) + { + pos++; + } + + return pos; + } } diff --git a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnectorTests.cs b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnectorTests.cs index b7e3cbd7..1a16b464 100644 --- a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnectorTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/AzureDevOpsRepoConnectorTests.cs @@ -504,7 +504,7 @@ public void WorkItemMapper_ExtractItemControls_CustomAffectedVersionsField_Retur // Assert Assert.IsNotNull(controls); Assert.IsNotNull(controls.AffectedVersions); - Assert.IsTrue(controls.AffectedVersions.Intervals.Count > 0); + Assert.IsNotEmpty(controls.AffectedVersions.Intervals); } /// @@ -597,11 +597,12 @@ public async Task AzureDevOpsRepoConnector_GetBuildInformationAsync_WithConfigur // Assert Assert.IsNotNull(buildInfo); Assert.IsNotNull(buildInfo.RoutedSections); - Assert.IsTrue(buildInfo.RoutedSections.Count > 0, "Should have routed sections"); + Assert.IsNotEmpty(buildInfo.RoutedSections, "Should have routed sections"); // Verify bug was routed to bugs section var bugsSection = buildInfo.RoutedSections.FirstOrDefault(s => s.SectionId == "bugs"); - Assert.IsTrue(bugsSection.Items.Count > 0, "Bugs section should contain the routed bug"); + Assert.AreEqual("bugs", bugsSection.SectionId, "Should contain a bugs routed section"); + Assert.IsNotEmpty(bugsSection.Items, "Bugs section should contain the routed bug"); } // ───────────────────────────────────────────────────────────────────────── @@ -649,7 +650,7 @@ public async Task AzureDevOpsRestClient_GetCommitsAsync_ValidResponse_ReturnsCom // Assert Assert.IsNotNull(commits); - Assert.AreEqual(2, commits.Count); + Assert.HasCount(2, commits); Assert.AreEqual("abc123", commits[0].CommitId); Assert.AreEqual("First commit", commits[0].Comment); Assert.AreEqual("def456", commits[1].CommitId); @@ -674,7 +675,7 @@ public async Task AzureDevOpsRestClient_GetPullRequestsAsync_ValidResponse_Retur // Assert Assert.IsNotNull(prs); - Assert.AreEqual(2, prs.Count); + Assert.HasCount(2, prs); Assert.AreEqual(101, prs[0].PullRequestId); Assert.AreEqual("Feature PR", prs[0].Title); Assert.AreEqual("completed", prs[0].Status); @@ -698,7 +699,7 @@ public async Task AzureDevOpsRestClient_GetPullRequestWorkItemsAsync_ValidRespon // Assert Assert.IsNotNull(workItemRefs); - Assert.AreEqual(2, workItemRefs.Count); + Assert.HasCount(2, workItemRefs); Assert.AreEqual(200, workItemRefs[0].Id); Assert.AreEqual(201, workItemRefs[1].Id); } @@ -722,7 +723,7 @@ public async Task AzureDevOpsRestClient_GetWorkItemsAsync_ValidResponse_ReturnsW // Assert Assert.IsNotNull(workItems); - Assert.AreEqual(2, workItems.Count); + Assert.HasCount(2, workItems); Assert.AreEqual(200, workItems[0].Id); Assert.AreEqual(201, workItems[1].Id); } @@ -744,7 +745,7 @@ public async Task AzureDevOpsRestClient_QueryWorkItemsAsync_ValidWiql_ReturnsWor // Assert Assert.IsNotNull(query); - Assert.AreEqual(3, query.WorkItems.Count); + Assert.HasCount(3, query.WorkItems); Assert.AreEqual(300, query.WorkItems[0].Id); Assert.AreEqual(301, query.WorkItems[1].Id); Assert.AreEqual(302, query.WorkItems[2].Id); @@ -769,7 +770,7 @@ public async Task AzureDevOpsRestClient_GetPullRequestWorkItemsAsync_StringValue // Assert Assert.IsNotNull(workItemRefs); - Assert.AreEqual(2, workItemRefs.Count); + Assert.HasCount(2, workItemRefs); Assert.AreEqual(1234, workItemRefs[0].Id); Assert.AreEqual(5678, workItemRefs[1].Id); } @@ -793,7 +794,7 @@ public async Task AzureDevOpsRestClient_QueryWorkItemsAsync_StringValuedIds_Dese // Assert Assert.IsNotNull(query); - Assert.AreEqual(2, query.WorkItems.Count); + Assert.HasCount(2, query.WorkItems); Assert.AreEqual(300, query.WorkItems[0].Id); Assert.AreEqual(301, query.WorkItems[1].Id); } diff --git a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/ItemRouterTests.cs b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/ItemRouterTests.cs index 01147e8e..e4877357 100644 --- a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/ItemRouterTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/ItemRouterTests.cs @@ -211,9 +211,9 @@ public void ItemRouter_Route_ItemNotInConfiguredSections_CreatesNewSection() // Assert - item is routed to the new section, which is created dynamically Assert.IsEmpty(routedItems["changes"]); - Assert.IsTrue(routedItems.ContainsKey("new-section")); - Assert.HasCount(1, routedItems["new-section"]); - Assert.AreEqual("1", routedItems["new-section"][0].Id); + Assert.IsTrue(routedItems.TryGetValue("new-section", out var newSection)); + Assert.HasCount(1, newSection); + Assert.AreEqual("1", newSection[0].Id); } } diff --git a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/RepoConnectorsTests.cs b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/RepoConnectorsTests.cs index 28ea4b3d..467372f8 100644 --- a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/RepoConnectorsTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/RepoConnectorsTests.cs @@ -749,7 +749,7 @@ public async Task RepoConnectors_AzureDevOps_GetBuildInformation_WithPullRequest // Assert: changes include the work item from the PR Assert.IsNotNull(buildInfo); - Assert.IsTrue(buildInfo.Changes.Count > 0, "Changes should include items from merged PRs"); + Assert.IsNotEmpty(buildInfo.Changes, "Changes should include items from merged PRs"); } /// @@ -775,7 +775,7 @@ public async Task RepoConnectors_AzureDevOps_GetBuildInformation_WithOpenWorkIte // Assert: known issues include the open bug Assert.IsNotNull(buildInfo); - Assert.IsTrue(buildInfo.KnownIssues.Count > 0, "KnownIssues should include open bug work items"); + Assert.IsNotEmpty(buildInfo.KnownIssues, "KnownIssues should include open bug work items"); } /// diff --git a/test/DemaConsulting.BuildMark.Tests/Version/VersionComparableTests.cs b/test/DemaConsulting.BuildMark.Tests/Version/VersionComparableTests.cs index 9a636f13..10d529db 100644 --- a/test/DemaConsulting.BuildMark.Tests/Version/VersionComparableTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/Version/VersionComparableTests.cs @@ -28,6 +28,24 @@ namespace DemaConsulting.BuildMark.Tests.Version; [TestClass] public class VersionComparableTests { + private static readonly string[] SemanticVersionOrder = + [ + "1.0.0", + "2.0.0", + "2.1.0", + "2.1.1" + ]; + + private static readonly string[] PreReleaseSemVerOrder = + [ + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-alpha.beta", + "1.0.0-beta", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1" + ]; /// /// Test that VersionComparable creates instances from valid version strings. /// @@ -136,7 +154,7 @@ public void VersionComparable_CompareTo_DifferentMajor_ReturnsCorrectOrder() var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "1.2.3 should be less than 2.1.1"); + Assert.IsLessThan(0, result, "1.2.3 should be less than 2.1.1"); } /// @@ -153,7 +171,7 @@ public void VersionComparable_CompareTo_DifferentMinor_ReturnsCorrectOrder() var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "1.2.3 should be less than 1.3.1"); + Assert.IsLessThan(0, result, "1.2.3 should be less than 1.3.1"); } /// @@ -170,7 +188,7 @@ public void VersionComparable_CompareTo_DifferentPatch_ReturnsCorrectOrder() var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "1.2.3 should be less than 1.2.4"); + Assert.IsLessThan(0, result, "1.2.3 should be less than 1.2.4"); } /// @@ -187,7 +205,7 @@ public void VersionComparable_CompareTo_PreReleaseVsRelease_ReturnsCorrectOrder( var result = preRelease.CompareTo(release); // Assert - Assert.IsTrue(result < 0, "1.2.3-alpha should be less than 1.2.3"); + Assert.IsLessThan(0, result, "1.2.3-alpha should be less than 1.2.3"); } /// @@ -204,7 +222,7 @@ public void VersionComparable_CompareTo_PreReleaseVersions_ReturnsLexicographicO var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "alpha should be less than beta lexicographically"); + Assert.IsLessThan(0, result, "alpha should be less than beta lexicographically"); } /// @@ -278,13 +296,7 @@ public void VersionComparable_Operators_GreaterThanOrEqual_WorksCorrectly() public void VersionComparable_CompareTo_SemanticVersions_ReturnsCorrectOrder() { // Arrange - Test various semantic version scenarios - var versions = new[] - { - "1.0.0", - "2.0.0", - "2.1.0", - "2.1.1" - }.Select(v => VersionComparable.Create(v)).ToArray(); + var versions = SemanticVersionOrder.Select(v => VersionComparable.Create(v)).ToArray(); // Act & Assert - Test that they are in ascending order for (var i = 0; i < versions.Length - 1; i++) @@ -293,7 +305,7 @@ public void VersionComparable_CompareTo_SemanticVersions_ReturnsCorrectOrder() var next = versions[i + 1]; var result = current!.CompareTo(next); - Assert.IsTrue(result < 0, $"{current.CompareVersion} should be less than {next!.CompareVersion}"); + Assert.IsLessThan(0, result, $"{current.CompareVersion} should be less than {next!.CompareVersion}"); } } @@ -311,7 +323,7 @@ public void VersionComparable_CompareTo_NumericComparison_CorrectOrdering() var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "1.2.3 should be less than 1.11.2"); + Assert.IsLessThan(0, result, "1.2.3 should be less than 1.11.2"); } /// @@ -328,7 +340,7 @@ public void VersionComparable_CompareTo_ReleaseGreaterThanPreRelease_CorrectOrde var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result > 0, "1.2.3 should be greater than 1.2.3-beta.1"); + Assert.IsGreaterThan(0, result, "1.2.3 should be greater than 1.2.3-beta.1"); } /// @@ -345,7 +357,7 @@ public void VersionComparable_CompareTo_PreReleaseLexicographic_CorrectOrdering( var result = version1.CompareTo(version2); // Assert - Assert.IsTrue(result < 0, "alpha should be less than beta lexicographically"); + Assert.IsLessThan(0, result, "alpha should be less than beta lexicographically"); } /// @@ -363,7 +375,7 @@ public void VersionComparable_CompareTo_PreReleaseNumeric_ComparesNumerically() var result = version5!.CompareTo(version10); // Assert - Assert.IsTrue(result < 0, "1.0.0-alpha.5 should be less than 1.0.0-alpha.10 (numeric comparison)"); + Assert.IsLessThan(0, result, "1.0.0-alpha.5 should be less than 1.0.0-alpha.10 (numeric comparison)"); } /// @@ -373,16 +385,7 @@ public void VersionComparable_CompareTo_PreReleaseNumeric_ComparesNumerically() public void VersionComparable_CompareTo_PreReleaseSemVerRules_CorrectOrdering() { // Test cases from SemVer specification - var versions = new[] - { - "1.0.0-alpha", - "1.0.0-alpha.1", - "1.0.0-alpha.beta", - "1.0.0-beta", - "1.0.0-beta.2", - "1.0.0-beta.11", - "1.0.0-rc.1" - }.Select(v => VersionComparable.Create(v)).ToArray(); + var versions = PreReleaseSemVerOrder.Select(v => VersionComparable.Create(v)).ToArray(); // Test that they are in ascending order for (var i = 0; i < versions.Length - 1; i++) @@ -391,7 +394,7 @@ public void VersionComparable_CompareTo_PreReleaseSemVerRules_CorrectOrdering() var next = versions[i + 1]; var result = current!.CompareTo(next); - Assert.IsTrue(result < 0, $"{current.CompareVersion} should be less than {next!.CompareVersion}"); + Assert.IsLessThan(0, result, $"{current.CompareVersion} should be less than {next!.CompareVersion}"); } }