Assert equality in mstest when types may differ

I’ve been working on some MSTest automated test infrastructure, that is testing a tool that merges data sets into SQL Server database tables. The basic structure of the test is to:

  1. Define the incoming dataset using anonymous types
  2. Apply the data using the reconcile tool
  3. Read records from the output tables
  4. Compare result rows to input data, column by column

Example input data:

public class InputData : List<dynamic> {} // Inspired by Massive etc

InputData input = new InputData()
{
    new { ExternalID = 1, PropertyName = "hello", Agent = "test" },
    new { ExternalID = (Int64)2, PropertyName = "fred", Agent = "test" } // Fixes the problem with a cast
};

The issue I’m dealing with, is that the type inferred on my anonymous objects will be an Int32, but the corresponding column in my target table is a bigint, and hence the record will have an Int64 value. As a result, when I use Assert.AreEqual across each column, it fails on any int fields:

Assert.AreEqual failed. Expected:<1 (System.Int32)>. Actual:<1 (System.Int64)>

You can see I have cast the int on my second anonymous object, this can be used to fix the issue. The primary aim of these tests is to make the sample data as slim and easy to read/write as possible, and I’d prefer to avoid the visual noise of all those casts.

I’m thinking about the best way to deal with the assertions. It seems like I should use dedicated assertions based on type. I guess the real question is, how aggressive should I be in converting between types automatically?

2

Assert.AreEqual is basically just sugar for Assert.IsTrue(object.Equals(...)). If there isn’t a known comparison operator for the two argument types, they’ll compare false.

dynamic is pretty smart about this, so, for example, (dynamic)(int)1 == (decimal)1.0 evaluates to true. That only works if you use the == operator, though; it won’t work if you try to use object.Equals, Assert.AreEqual, ((dynamic)x).Equals(...) or anything similar. Simply casting to dynamic won’t work, you need to actually use its == operator. The good news is, the dynamic == allows any operand, which means you can get this to compile in a general-purpose assertion; if the comparison is invalid (e.g. comparing int to string, then it will fail at runtime with a RuntimeBinderException.

The next best thing, if you know they’re going to be numeric types, would be to cast them all to Decimal or Double, although note that if you use Double you’ll have to take into account the possibility of floating-point rounding error, and you should define equality based on some threshold, typically a multiple of Double.Epsilon. Decimal is a lot simpler unless you know for certain that you’ll be dealing with floating point.

I don’t think that you really have a lot of other choices. I personally would not recommend string conversion because lots of classes don’t override ToString, so you end up comparing two instances of something like System.Collections.Generic.List``1[System.Int32], and your assertion declares that these are equal because they have the same string representation when in fact they are not only different instances but contain completely different elements. So don’t do that. String coercion can easily mask serious errors in your tests. Stick to non-lossy, all-or-nothing conversions as above.

Convert to strings is what I think. Strings are underestimated in test cases. Then you can write a method thats like

void AssertEqual(Object a, Object b)
{
  Assert.AreEqual(a.ToString(), b.ToString();
}

and maybe add a parameter that is the fail message.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Assert equality in mstest when types may differ

I’ve been working on some MSTest automated test infrastructure, that is testing a tool that merges data sets into SQL Server database tables. The basic structure of the test is to:

  1. Define the incoming dataset using anonymous types
  2. Apply the data using the reconcile tool
  3. Read records from the output tables
  4. Compare result rows to input data, column by column

Example input data:

public class InputData : List<dynamic> {} // Inspired by Massive etc

InputData input = new InputData()
{
    new { ExternalID = 1, PropertyName = "hello", Agent = "test" },
    new { ExternalID = (Int64)2, PropertyName = "fred", Agent = "test" } // Fixes the problem with a cast
};

The issue I’m dealing with, is that the type inferred on my anonymous objects will be an Int32, but the corresponding column in my target table is a bigint, and hence the record will have an Int64 value. As a result, when I use Assert.AreEqual across each column, it fails on any int fields:

Assert.AreEqual failed. Expected:<1 (System.Int32)>. Actual:<1 (System.Int64)>

You can see I have cast the int on my second anonymous object, this can be used to fix the issue. The primary aim of these tests is to make the sample data as slim and easy to read/write as possible, and I’d prefer to avoid the visual noise of all those casts.

I’m thinking about the best way to deal with the assertions. It seems like I should use dedicated assertions based on type. I guess the real question is, how aggressive should I be in converting between types automatically?

2

Assert.AreEqual is basically just sugar for Assert.IsTrue(object.Equals(...)). If there isn’t a known comparison operator for the two argument types, they’ll compare false.

dynamic is pretty smart about this, so, for example, (dynamic)(int)1 == (decimal)1.0 evaluates to true. That only works if you use the == operator, though; it won’t work if you try to use object.Equals, Assert.AreEqual, ((dynamic)x).Equals(...) or anything similar. Simply casting to dynamic won’t work, you need to actually use its == operator. The good news is, the dynamic == allows any operand, which means you can get this to compile in a general-purpose assertion; if the comparison is invalid (e.g. comparing int to string, then it will fail at runtime with a RuntimeBinderException.

The next best thing, if you know they’re going to be numeric types, would be to cast them all to Decimal or Double, although note that if you use Double you’ll have to take into account the possibility of floating-point rounding error, and you should define equality based on some threshold, typically a multiple of Double.Epsilon. Decimal is a lot simpler unless you know for certain that you’ll be dealing with floating point.

I don’t think that you really have a lot of other choices. I personally would not recommend string conversion because lots of classes don’t override ToString, so you end up comparing two instances of something like System.Collections.Generic.List``1[System.Int32], and your assertion declares that these are equal because they have the same string representation when in fact they are not only different instances but contain completely different elements. So don’t do that. String coercion can easily mask serious errors in your tests. Stick to non-lossy, all-or-nothing conversions as above.

Convert to strings is what I think. Strings are underestimated in test cases. Then you can write a method thats like

void AssertEqual(Object a, Object b)
{
  Assert.AreEqual(a.ToString(), b.ToString();
}

and maybe add a parameter that is the fail message.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật