Threw this together really quick. Not very optimized but it does the basics. I sure do miss Linq, Attributes, PropertyInfo, IList, extensions, etc… ;D
I have my sln divided up into 2 micro console applications (my application and a unit test project) and a common library. Test classes (in your test app) must implement ITestClass interface, and test methods must be prefixed with “Test” and return a bool.
I hope this helps someone!
public interface ITestClass
{
}
public class Test
{
public string Class { get; set; }
public Type ClassType { get; set; }
public MethodInfo[] MethodTypes { get; set; }
}
private static void runTests()
{
ArrayList tests = getTestList();
int testCounter = 0;
int testFailCounter = 0;
foreach (Test test in tests)
{
var ctor = test.ClassType.GetConstructor(new Type[0]);
var classInstance = ctor.Invoke(new object[0]);
foreach (MethodInfo method in test.MethodTypes)
{
testCounter++;
Debug.Print("Running " + test.Class + "::" + method.Name);
bool returnValue = (bool)method.Invoke(classInstance, new object[0]);
if (!returnValue) testFailCounter++;
Debug.Assert(returnValue, "Test failed " + test.Class + "::" + method.Name);
}
}
Debug.Print("Ran " + testCounter.ToString() + " tests");
Debug.Print(testFailCounter + " tests failed");
}
private static ArrayList getTestList()
{
const string TEST_METHOD_PREFIX = "Test";
ArrayList tests = new ArrayList();
Assembly thisAssembly = Assembly.GetAssembly(typeof(Program));
foreach (Type classType in thisAssembly.GetTypes())
{
foreach (Type interfaceType in classType.GetInterfaces())
{
if (typeof(ITestClass) == interfaceType)
{
ArrayList methodInfos = new ArrayList();
foreach (MethodInfo method in classType.GetMethods())
{
if (method.Name.Substring(0, TEST_METHOD_PREFIX.Length) == TEST_METHOD_PREFIX)
{
methodInfos.Add(method);
}
}
tests.Add(new Test() { Class = classType.Name, ClassType = classType, MethodTypes = (MethodInfo[])methodInfos.ToArray(typeof(MethodInfo)) });
}
}
}
return tests;
}