Skip to content

Commit 77f7c29

Browse files
DRY follow-ups: collapse * early-returns, EscapeForDisplay delegates to EscapeChar, extract test helpers
- WildcardMatchAnalyzer: collapse two identical early-exit paths in ExtractWildcardMatches into one combined condition (nextPatternPos >= Length || nextLiteralIndex == -1); compute FindNextLiteralMatch once before the guard. - WildcardMatchAnalyzer: EscapeForDisplay now iterates chars and delegates to EscapeChar via StringBuilder, eliminating three chained .Replace calls. - EnhancedErrorMessageTests: extract GetMismatchMessage() helper used by three tests. - WildcardMatchAnalyzerTests: extract GetDiff() helper used by two GenerateDetailedDiff tests.
1 parent e2c4112 commit 77f7c29

3 files changed

Lines changed: 48 additions & 85 deletions

File tree

IntelliTect.TestTools.Console.Tests/EnhancedErrorMessageTests.cs

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,78 +6,56 @@ namespace IntelliTect.TestTools.Console.Tests;
66
[TestClass]
77
public class EnhancedErrorMessageTests
88
{
9+
/// <summary>
10+
/// Runs <paramref name="consoleAction"/> via <see cref="ConsoleAssert.ExpectLike"/>, asserts it
11+
/// throws <see cref="ConsoleAssertException"/>, and returns the exception message.
12+
/// </summary>
13+
private static string GetMismatchMessage(string expected, Action consoleAction)
14+
{
15+
var ex = Assert.ThrowsExactly<ConsoleAssertException>(
16+
() => ConsoleAssert.ExpectLike(expected, consoleAction));
17+
return ex.Message;
18+
}
19+
920
[TestMethod]
1021
public void ExpectLike_WildcardMismatch_ShowsDetailedDiff()
1122
{
12-
// Arrange - pattern with wildcards that will NOT match
13-
string expected = "PING *(::1) 56 data bytes\n64 bytes from *";
14-
15-
// Act & Assert - ConsoleAssert throws ConsoleAssertException on mismatch
16-
ConsoleAssertException exception = Assert.ThrowsExactly<ConsoleAssertException>(() =>
17-
{
18-
ConsoleAssert.ExpectLike(expected, () =>
19-
{
20-
System.Console.Write("PING localhost(::1) WRONG data bytes\n64 bytes from localhost");
21-
});
22-
});
23+
string errorMessage = GetMismatchMessage(
24+
"PING *(::1) 56 data bytes\n64 bytes from *",
25+
() => System.Console.Write("PING localhost(::1) WRONG data bytes\n64 bytes from localhost"));
2326

24-
// Assert - Check that the error message contains the enhanced output
25-
string errorMessage = exception.Message;
26-
27-
// Should contain the line-by-line comparison header
2827
StringAssert.Contains(errorMessage, "Line-by-line comparison");
29-
30-
// Should contain status indicators
31-
StringAssert.Contains(errorMessage, "❌"); // Lines don't match
28+
StringAssert.Contains(errorMessage, "❌");
3229
}
3330

3431
[TestMethod]
3532
public void ExpectLike_ExtraLines_IdentifiedAsSuch()
3633
{
37-
// Arrange - pattern expecting one line, but getting two
38-
string expected = "Line 1";
39-
40-
// Act & Assert
41-
ConsoleAssertException exception = Assert.ThrowsExactly<ConsoleAssertException>(() =>
42-
{
43-
ConsoleAssert.ExpectLike(expected, () =>
34+
string errorMessage = GetMismatchMessage(
35+
"Line 1",
36+
() =>
4437
{
4538
System.Console.WriteLine("Line 1");
4639
System.Console.WriteLine("Line 2");
4740
});
48-
});
4941

50-
// Assert
51-
string errorMessage = exception.Message;
52-
// With line-by-line comparison, we should see the extra line marked
5342
StringAssert.Contains(errorMessage, "Line 2: ❌");
5443
StringAssert.Contains(errorMessage, "Unexpected extra line");
5544
}
5645

5746
[TestMethod]
5847
public void ExpectLike_MissingLines_IdentifiedAsSuch()
5948
{
60-
// Arrange - pattern with wildcards expecting more lines
61-
string expected = "Line 1\nLine *";
62-
63-
// Act & Assert
64-
ConsoleAssertException exception = Assert.ThrowsExactly<ConsoleAssertException>(() =>
65-
{
66-
ConsoleAssert.ExpectLike(expected, () =>
67-
{
68-
System.Console.WriteLine("Line 1");
69-
});
70-
});
49+
string errorMessage = GetMismatchMessage(
50+
"Line 1\nLine *",
51+
() => System.Console.WriteLine("Line 1"));
7152

72-
// Assert
73-
string errorMessage = exception.Message;
7453
StringAssert.Contains(errorMessage, "Missing line");
7554
}
7655

7756
[TestMethod]
7857
public void ExpectLike_SuccessfulWildcardMatch_DoesNotThrow()
7958
{
80-
// Verify the feature doesn't break the happy path
8159
ConsoleAssert.ExpectLike("Hello * world", () =>
8260
{
8361
System.Console.Write("Hello beautiful world");

IntelliTect.TestTools.Console.Tests/WildcardMatchAnalyzerTests.cs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ namespace IntelliTect.TestTools.Console.Tests;
66
[TestClass]
77
public class WildcardMatchAnalyzerTests
88
{
9+
/// <summary>
10+
/// Calls <see cref="WildcardMatchAnalyzer.AnalyzeMatch"/> then
11+
/// <see cref="WildcardMatchAnalyzer.GenerateDetailedDiff"/> and asserts the result is non-empty.
12+
/// </summary>
13+
private static string GetDiff(string expected, string actual)
14+
{
15+
var results = WildcardMatchAnalyzer.AnalyzeMatch(expected, actual);
16+
string diff = WildcardMatchAnalyzer.GenerateDetailedDiff(results);
17+
Assert.IsFalse(string.IsNullOrEmpty(diff));
18+
return diff;
19+
}
20+
921
[TestMethod]
1022
public void AnalyzeMatch_SingleLineMatch_IdentifiesWildcardMatches()
1123
{
@@ -96,37 +108,19 @@ public void AnalyzeMatch_MissingLinesInActual_MarkedAsMissing()
96108
[TestMethod]
97109
public void GenerateDetailedDiff_CreatesReadableOutput()
98110
{
99-
// Arrange
100-
string expected = "Hello * world\nLine *";
101-
string actual = "Hello beautiful world\nLine 2";
102-
103-
var results = WildcardMatchAnalyzer.AnalyzeMatch(expected, actual);
104-
105-
// Act
106-
string diff = WildcardMatchAnalyzer.GenerateDetailedDiff(results);
111+
string diff = GetDiff("Hello * world\nLine *", "Hello beautiful world\nLine 2");
107112

108-
// Assert
109-
Assert.IsFalse(string.IsNullOrEmpty(diff));
110113
StringAssert.Contains(diff, "Line-by-line comparison");
111-
StringAssert.Contains(diff, "✅"); // Should contain success markers
114+
StringAssert.Contains(diff, "✅");
112115
StringAssert.Contains(diff, "Wildcard matches");
113116
}
114117

115118
[TestMethod]
116119
public void GenerateDetailedDiff_WithMismatch_ShowsFailure()
117120
{
118-
// Arrange
119-
string expected = "Expected text";
120-
string actual = "Actual text";
121-
122-
var results = WildcardMatchAnalyzer.AnalyzeMatch(expected, actual);
121+
string diff = GetDiff("Expected text", "Actual text");
123122

124-
// Act
125-
string diff = WildcardMatchAnalyzer.GenerateDetailedDiff(results);
126-
127-
// Assert
128-
Assert.IsFalse(string.IsNullOrEmpty(diff));
129-
StringAssert.Contains(diff, "❌"); // Should contain failure marker
123+
StringAssert.Contains(diff, "❌");
130124
}
131125

132126
[TestMethod]

IntelliTect.TestTools.Console/WildcardMatchAnalyzer.cs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -210,24 +210,15 @@ private static void ExtractWildcardMatches(string pattern, string text, List<Wil
210210
nextPatternPos++;
211211
}
212212

213-
if (nextPatternPos >= pattern.Length)
214-
{
215-
// '*' at the end matches everything remaining
216-
wildcardMatches.Add(new WildcardMatch
217-
{
218-
Pattern = "*",
219-
MatchedText = text.Substring(textPos)
220-
});
221-
return;
222-
}
213+
// Find where the next literal prefix of the remaining pattern appears in the text.
214+
// If '*' is at the end of the pattern, skip the search entirely.
215+
string remainingPattern = nextPatternPos < pattern.Length ? pattern.Substring(nextPatternPos) : null;
216+
int nextLiteralIndex = remainingPattern != null ? FindNextLiteralMatch(text, textPos, remainingPattern) : -1;
223217

224-
// Find where the next literal prefix of the remaining pattern appears in the text
225-
string remainingPattern = pattern.Substring(nextPatternPos);
226-
int nextLiteralIndex = FindNextLiteralMatch(text, textPos, remainingPattern);
227-
228-
if (nextLiteralIndex == -1)
218+
if (nextPatternPos >= pattern.Length || nextLiteralIndex == -1)
229219
{
230-
// Could not find a match for the remaining pattern — '*' consumed the rest
220+
// '*' at the end of pattern, or remaining pattern has no literal anchor —
221+
// consume everything remaining in the text.
231222
wildcardMatches.Add(new WildcardMatch
232223
{
233224
Pattern = "*",
@@ -384,10 +375,10 @@ private static string EscapeForDisplay(string text)
384375
if (text == null) return "<null>";
385376
if (text == string.Empty) return "<empty>";
386377

387-
return text
388-
.Replace("\r", "\\r")
389-
.Replace("\n", "\\n")
390-
.Replace("\t", "\\t");
378+
var sb = new StringBuilder(text.Length);
379+
foreach (char c in text)
380+
sb.Append(EscapeChar(c));
381+
return sb.ToString();
391382
}
392383

393384
/// <summary>

0 commit comments

Comments
 (0)