Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
String Comparison Unit Test Helper
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
}
@jarshwah

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

@rplantiko

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

@Haacked
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. :)

@sinairv

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?

@Haacked
Owner

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

@af4jm

@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
);
@Haacked
Owner

@dotnetzebra good suggestion. I made the change.

@jplindgren

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.