ClassTester - Test automatically all the stuff you don't bother testing with hand written tests - ISerializable - Roy Osherove's Blog

ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

A dude named Josh sent me an email about a Class Tester he's developed, available here. The idea is to take care of all the things I usually avoid writing unit tests for because it takes too much effort for too little benefit:

"What it can do:
  • Automatically test properties, spotting any miswired getters or setters
  • Increase code coverage, reaching parts manual tests don't even try to
  • Supports ignoring specified properties if you have any funky logic in there that needs a manual test
  • Tests for PropertyChanged events if your class implements INotifyPropertyChanged
  • Tests constructors and that they map parameters to properties "

Looks pretty cool, and might make a fine addition to the unit testing tool set. Thanks Josh!

Published Friday, August 03, 2007 12:12 PM by RoyOsherove

Comments

Friday, August 03, 2007 3:43 PM by Adrian Aisemberg

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

When testing the constructors, it creates instances of all the parameters types and test the properties using these instances.

From the source code:

"default:  return Activator.CreateInstance(type);"

What if my constructor gets an abstract (or an interface) instance?

Well. I've tried it with this constructor:

public Dummy(IContainer someContainer).

The test fails with a "MissingMethodException" (Cannot create an instance of an interface).

Friday, August 03, 2007 10:23 PM by Kelly Summerlin

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

I normally don't post comments on blogs, especially making a comment to a comment. But Adrian your comment just seems a bit harsh and comments like this are probably the #1 reason more people don't post good ideas and their code. Other folks come along and the first thing they do is criticize someone's effort.

Rather than posting how to break the original author's idea, why not start off with something like, "Hey this is a good start. Do you have any ideas on how this could be extended to support abstract or interfaces in the constructor arguments?" That is much more constructive and can really get a good discussion started.

The originally post clearly states that this code should be considered sample code, not something that will solve all your problems.

Sorry, off the soap box now.

Saturday, August 04, 2007 12:39 AM by RoyOsherove

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

Thanks Kelly. I think it's a fine point. Adrian - Perhaps you could add that ability...

Roy.

Saturday, August 04, 2007 5:49 PM by Adrian Aisemberg

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

Creating an instance of an interface is easy using a dynamic proxy.

We can just implement a RealProxy and use it to create instances of any interface.

The problem arrives when we need to actually call methods from that proxy.

One such method is the "Equals" method (It's in every interface...). The ClassTester calls that method somewhere, so we need to implement the proxy invoker of RealProxy (otherwise - we can just leave it "NotImplemented").

Another problem is with abstract classes.

Only MarshalByRef classes can have proxies.

Anyway, because the ClassTester is supposed to run in a testing environment, we can add a reference to nunit.mocks and use their DynamicMock. It's the same, but with the proxy methods implemented. Well, at least "Equals".

After changing the previous "Activator.CreateInstance" call to this code:

default:

return CreateObject(type);

}

}

private static object CreateObject(Type type)

{

if (type.IsInterface || type.IsAbstract)

{

DynamicMock mock = new DynamicMock(type);

return mock.MockInstance;

}

return Activator.CreateInstance(type);

}

And fixing this code:

bool testSet = property.CanWrite && (HasDefaultConstructor(property.PropertyType) || property.PropertyType == typeof(String));

To this:

bool testSet = property.CanWrite;

We can add the RaiseEvent call to the "InterfaceProperty" setter and see all tests pass.

We can even create an abstract class property, as the interface, and see it fail or pass, and that depends on whether the class is MarshalByRef or not.

----

A proxy to a not-MarshalByRef abstract:

I don't have a clue on that. Anyone?

Sunday, August 05, 2007 4:50 PM by Josh

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

Adrian, if you'd have posted the comment on the blog that offers the source (mine) I'd have been able to reply in a more timely and direct fashion.

Firstly, thanks to Kelly for his response. I couldn't have put it better myself.

Secondly, I think you're missing the point of the ClassTester. It's for the most basic of cases, anything else requires a manual test. Admittedly, the TestConstructors functionality is less well implemented but I have use for it.

Monday, August 06, 2007 10:47 PM by FredericALTorres

# re: ClassTester - Test automatically all the stuff you don't bother testing with hand written tests

Regarding ClassTester, Interesting how some people are trying to write unit tests differently than the xUnit way.

I created QuickUnit.net, it is different from ClassTester idea, but it is in the same world.

www.QuickUnit.net, feedback welcome.