Question

I build my own comparison for this following object to be used in my testing. It works as it currently stands and passes the false value out when one of the compared fields does not match. Is there a way that I would do this that would give me more detailed information as to which field the comparison failed on?

[DataContract]
public class Stats : IEquatable<Stats>
{
    [DataMember]
    public string StatusCode { get; set; }
    [DataMember]
    public int ProspectCount { get; set; }
    [DataMember]
    public int MessageCount { get; set; }
    [DataMember]
    public int NewListingCount { get; set; }
    [DataMember]
    public int ReminderCount { get; set; }
    [DataMember]
    public int MyListingCount { get; set; }
    [DataMember]
    public int OfficeListingCount { get; set; }

    public bool Equals(Stats other)
    {
        if (Object.ReferenceEquals(other, null)) return false;

        if (Object.ReferenceEquals(this, other)) return true;

        return StatusCode.Equals(other.StatusCode) &&
               ProspectCount.Equals(other.ProspectCount) &&
               MessageCount.Equals(other.MessageCount) &&
               NewListingCount.Equals(other.NewListingCount) &&
               ReminderCount.Equals(other.ReminderCount) &&
               MyListingCount.Equals(other.MyListingCount) &&
               OfficeListingCount.Equals(other.OfficeListingCount);
    }

}

Test:

[Theory]
[ExcelData("Stats.xls", "Select * from TestData")]
public void GoodDataTests(int SubscriptionId, int ProfileId, int ClientID, string statusCode, int prospectCount,
    int messageCount, int newListingCount, int reminderCount, int myListingCount, int officListingCount)
{
    DataContainers.Stats expectedStats = new DataContainers.Stats{
        StatusCode = statusCode,
        ProspectCount = prospectCount,
        MessageCount = messageCount,
        NewListingCount = newListingCount,
        ReminderCount = reminderCount,
        MyListingCount = myListingCount,
        OfficeListingCount = officListingCount
    };    

    string url = Utils.CreateStatisticsUrlRequest(SubscriptionId,ProfileId,ClientID);
    string response = Utils.GetResponseBody(url);

    DataContainers.Stats results = JsonConvert.DeserializeObject<DataContainers.Stats>(response);

    Assert.Equal(expectedStats, results);
}

My current failure output from xunit looks something like this:

Test Name: GoodDataTests Test FullName: ThunderBallApiTests.StatisticsTests.GoodDataTests Test Source: \sky.dom\mlfile1\users\DanS\My Documents\Visual Studio 2012\Projects\ThunderBallApiTests\ThunderBallApiTests\StatisticsTests.cs : line 20 Test Outcome: Failed Test Duration: 0:00:20.203

Result1 Name: GoodDataTests(SubscriptionId: 167769, ProfileId: 1571394, ClientID: 1234, statusCode: "Active", prospectCount: 54, messageCount: 17, newListingCount: 0, reminderCount: 33, myListingCount: 0, officListingCount: 2) Result1 Outcome: Failed Result1 Duration: 0:00:01.471 Result1 Message:
Assert.Equal() Failure Expected: ThunderBallApiTests.DataContainers.Stats Actual: ThunderBallApiTests.DataContainers.Stats Result1 StackTrace: at ThunderBallApiTests.StatisticsTests.StatisticsGoodDataTests(Int32 SubscriptionId, Int32 ProfileId, Int32 Id, String statusCode, Int32 prospectCount, Int32 messageCount, Int32 newListingCount, Int32 reminderCount, Int32 myListingCount, Int32 officListingCount) in \sky.dom\mlfile1\users\DanS\My Documents\Visual Studio 2012\Projects\ThunderBallApiTests\ThunderBallApiTests\StatisticsTests.cs:line 36

Was it helpful?

Solution

Note that putting an equality operation on a data contract isnt generally a good smell. The xUnit Test Patterns Book gives good general advice and patterns in this space. The book covers the notions of test-specific equality and equality pollution. It also has the notion of a Custom Assertion, which can address your need (assuming the equality is not directly needed in the production code).

Other useful tricks are:

  • override ToString and Assert.Equal will give better diagnostics for free (You could use a CR or R# tem[plate to do so)
  • map to a Tuple or an anonymous class and get said ToString impl for free.

In terms of tools to automate stuff like this You can use AutoFixture's Likeness (It's overkill for this scenario but can be excellent for mappers and is a potential golden hammer worth being aware of ;). Also, if you're writing your tests in F# (you really should), you can lean on unquote.

OTHER TIPS

I think this actually confuses two concepts--comparison and testing. The "test" for equality has a true/false value, but neither is a "failure". If the wider scenario is that the two objects should be equal to satisfy a test case, then if you find they're not equal, test each property for equality, which will give the more detailed test results you're after.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top