Assert.That

Topics: Developer Forum
Developer
Jun 25, 2006 at 1:05 AM
So I had some time today to sit down and consider how I might implement the Assert.That model. I'm beginning to see a few problems which I think might be stumbling blocks on a Non-2.0 project. Specifically:

* Boxing/Unboxing : NUnit's asserters carry a large number of overloads which are needed exclusively to support other languages and how they Box certain types. While
Assert.That(57.0, new EqualTo(myVariable));
seems simple enough, the rub comes in the implementation of the Interface which EqualToOrGreaterThan has to implement. The That method can be overloaded to support multiple types, but the Interface which also accepts a value be forced to use a System.Object because that command works just as well with 57.0 as it does with "Hello World" as it does with any IComparable object.

Under .NET Framework 2.0 I can see how we do this, the above line becomes :
Assert<string>.That("Hello World", new EqualTo(myVariable));
Because the method signature of That looks like:
public static void That(T actual, IAssertCompare<T>)

This is clean, but requires generics and leaves the ability to choose to support a type clearly in the ballpark of the person greater the IAssertCompare object and/or forces the person calling Assert to realize what they are doing when they call Assert<object>.

I welcome any ideas around this, but I simply can't find a way around this problem.

Tim
Coordinator
Aug 29, 2006 at 9:29 PM
In the first cut of an implementation, I didn't worry about any languages other than C#.

However, since Assert only has one method that we need to worry about, it seems to me that we will end up with less overloading than in NUnit. For C++ and other languages, I'll need

Assert.That(int)
Assert.That(decimal)
etc.

Similarly, the base class for Matchers will need to define a bunch of value type overloads that vector to the abstract overload of type object.

So it doesn't seem insurmountable, but I may be missing something.
Developer
Aug 30, 2006 at 12:25 AM
I guess I'm not certain how the matchers will cleanly handle the following example (I'm moving fast tonight, if there is syntax errors, please forgive me):

int myValInt = 10;
string myValString = "To be or not to be";

Assert.That(myValInt, new EqualityMatcher(myValString));

Unlike in the Assert model of NUnit itself, there is no way to ensure compile-time type correctness. And handling all various odd-ball casts in each and every Matcher seems a little crazy. Sure we can likely abstract alot of it into base classes which the Matcher's share, but it's going to be "interesting" to get right.

Tim
Coordinator
Aug 30, 2006 at 1:04 AM
Well, let's see...

First the EqualityMatcher has to be constructed. The constructor takes an object and you're giving it an object, so no problem.

Next a proper That overload needs to be identified. In C#, the int is automatically boxed and the That( object ) method is used. In C++, we would need to have That( int ), which would redirect to That( object ). This is the same as current NUnit.

Now, lets say you called the following, in C++

Assert.That( 2+2, new EqualMather( 4 ) );

This has the added problem that there is no int constructor for EqualMatcher. So yes, we would be forced to add a new constructor of type int to EqualMatcher.

But again, this seems no worse than what we already do for Assert. Note that we don't have to handle ALL possible casts. If we cover double, then float will be handled. Long takes care of int and short. And so on...

Of course, this is speculative till I get a chance to write some C++ tests

Charlie
Coordinator
Aug 30, 2006 at 1:37 AM
I set up a small test and managed to get the following test to run using C++/CLI...

TestFixture
public ref class AssertTests
{
public:
Test
void AssertTest()
{
Assert::That(2+2, Is::EqualTo(4));
}
};

This requires more testing, but I'm thinking that the new C+/CLI is more forgiving than the older managed C+.