Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

String Comparison Unit Test Helper

View TestHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
public static class TestHelpers
{
public static void ShouldEqualWithDiff(this string actualValue, string expectedValue)
{
ShouldEqualWithDiff(actualValue, expectedValue, DiffStyle.Full, Console.Out);
}
 
public static void ShouldEqualWithDiff(this string actualValue, string expectedValue, DiffStyle diffStyle)
{
ShouldEqualWithDiff(actualValue, expectedValue, diffStyle, Console.Out);
}
 
public static void ShouldEqualWithDiff(this string actualValue, string expectedValue, DiffStyle diffStyle, TextWriter output)
{
if(actualValue == null || expectedValue == null)
{
//Assert.AreEqual(expectedValue, actualValue);
Assert.Equal(expectedValue, actualValue);
return;
}
 
if (actualValue.Equals(expectedValue, StringComparison.Ordinal)) return;
 
output.WriteLine(" Idx Expected Actual");
output.WriteLine("-------------------------");
int maxLen = Math.Max(actualValue.Length, expectedValue.Length);
int minLen = Math.Min(actualValue.Length, expectedValue.Length);
for (int i = 0; i < maxLen; i++)
{
if (diffStyle != DiffStyle.Minimal || i >= minLen || actualValue[i] != expectedValue[i])
{
output.WriteLine("{0} {1,-3} {2,-4} {3,-3} {4,-4} {5,-3}",
i < minLen && actualValue[i] == expectedValue[i] ? " " : "*", // put a mark beside a differing row
i, // the index
i < expectedValue.Length ? ((int)expectedValue[i]).ToString() : "", // character decimal value
i < expectedValue.Length ? expectedValue[i].ToSafeString() : "", // character safe string
i < actualValue.Length ? ((int)actualValue[i]).ToString() : "", // character decimal value
i < actualValue.Length ? actualValue[i].ToSafeString() : "" // character safe string
);
}
}
output.WriteLine();
 
//Assert.AreEqual(expectedValue, actualValue);
Assert.Equal(expectedValue, actualValue);
}
 
private static string ToSafeString(this char c)
{
if (Char.IsControl(c) || Char.IsWhiteSpace(c))
{
switch (c)
{
case '\r':
return @"\r";
case '\n':
return @"\n";
case '\t':
return @"\t";
case '\a':
return @"\a";
case '\v':
return @"\v";
case '\f':
return @"\f";
default:
return String.Format("\\u{0:X};", (int)c);
}
}
return c.ToString(CultureInfo.InvariantCulture);
}
}
 
public enum DiffStyle
{
Full,
Minimal
}

Moved the Math.Max() outside the loop declaration: https://gist.github.com/1610860

Not knowing C#, I learned with your example the meaning of the prefix @ before a string literal in C# = no escaped char sequences.

Owner

@jarshwah Thanks! Are you sure that makes a difference? There are many cases where the C# compiler can optimize calls like this. For example, since it knows that actualValue and expectedValue don't change, it can evaluate the length and max once. I don't know if it does it in this particular case, but would be interesting to check the IL and measure it to see if it really does make a difference. :)

I forked and made some modifications to your snippet, here it is: https://gist.github.com/1615334

PS. how can I send a pull request for a gist?

Owner

@sinairv thanks! I'll take a look at it. Unfortunately, gistts don't support pull requests.

@haacked & @sinairv, for readability, I would suggest removing the call to string.Format & using the overload output.WriteLine(string format, params object[] args)

output.WriteLine("{0} {1,-3} {2,-4} {3,-3}  {4,-4} {5,-3}",
    i < minLen && actual[i] == expected[i] ? " " : "*", // put a mark beside a differing row
    i, // the index
    i < expected.Length ? ((int)expected[i]).ToString() : "", // character decimal value
    i < expected.Length ? expected[i].ToSafeString() : "", // character safe string
    i < actual.Length ? ((int)actual[i]).ToString() : "", // character decimal value
    i < actual.Length ? actual[i].ToSafeString() : "" // character safe string
);
Owner

@dotnetzebra good suggestion. I made the change.

Thx man.
This helper class help me A LOT with some tricky tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.