Skip to content

Instantly share code, notes, and snippets.

@dlwiii
Last active December 31, 2015 06:19
Show Gist options
  • Save dlwiii/7946777 to your computer and use it in GitHub Desktop.
Save dlwiii/7946777 to your computer and use it in GitHub Desktop.
Test Harness wrapper. I use this all the time to give a console application the generic ability to run specific methods in specific classes with or without arguments. It turns my console app into a Swiss army knife!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Dimension.Connectors.Procore.Test
{
public class TestMain
{
private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static void Main(string[] args)
{
var tester = new TestMain();
tester.RunDiagnostic(args);
}
public int RunDiagnostic(string[] args)
{
DateTime start = DateTime.Now;
int i = 0;
try
{
log.Info("\n\n\t***Starting Test");
string allArgs = "";
foreach (string arg in args)
{
allArgs += arg + " ";
}
allArgs = allArgs.Trim();
log.Info("Args: " + allArgs);
i = RunTest(args);
}
catch (Exception ex)
{
log.Error("Error: " + ex.ToString());
log.Error("Stack: " + ex.StackTrace.ToString());
if (ex.InnerException != null)
{
// an exception from an invoked method
log.Error("Inner Error: " + ex.InnerException.ToString());
log.Error("Inner Stack: " + ex.InnerException.StackTrace.ToString());
}
}
log.Info("RunTime: " + ((TimeSpan)(DateTime.Now - start)).TotalSeconds.ToString());
log.Info("Result: " + i.ToString());
return i;
}
int RunTest(string[] args)
{
if (args.Length < 2)
{
Help();
return 1;
}
// get a list of all classes that have the attribute "TestClass"
string classToRun = args[0];
string methodToRun = args[1];
string[] subargs = null;
if (args.Length > 2)
{
subargs = new string[args.Length - 2];
for (int n = 2; n < args.Length; n++)
{
subargs[n - 2] = args[n];
}
}
var allDiagnostics = GetClassesAndMethods();
var matches = allDiagnostics.Where(c => c.TheClass.Name == classToRun && c.TheMethod.Name == methodToRun).ToList();
if (matches.Count() == 1)
{
var match = matches[0];
Invoke(match.TheClass, match.TheMethod, subargs);
}
else if (matches.Count() > 1)
{
log.Warn("There is more than one match to this class and method - harass the developer!");
return 1;
}
else
{
log.WarnFormat("Requested class [{0}] and method [{1}] not found", classToRun, methodToRun);
Help();
return 1;
}
return 0;
}
protected void Help()
{
var allDiagnostics = GetClassesAndMethods();
// todo: follow some nice standard, winging it for now
log.Error("\nusage: CLASS METHOD <arguments...>");
var lastClassName = "";
foreach (var cm in allDiagnostics)
{
if (lastClassName != cm.TheClass.Name)
{
log.Info("\nClass: " + cm.TheClass.Name);
lastClassName = cm.TheClass.Name;
}
string message = "";
foreach (ParameterInfo pi in cm.TheMethod.GetParameters())
{
message += " " + pi.Name;
}
log.Info("\tMethod: " + cm.TheMethod.Name + message);
}
}
public class ClassAndMethod
{
public Type TheClass;
public MethodInfo TheMethod;
}
public IList<ClassAndMethod> GetClassesAndMethods()
{
var result = new List<ClassAndMethod>();
Assembly[] asses = AppDomain.CurrentDomain.GetAssemblies();
Assembly theAss = Assembly.GetEntryAssembly();
Type[] types = null;
try
{
types = theAss.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
foreach (Exception le in ex.LoaderExceptions)
{
log.Error(le.Message);
}
}
foreach (Type typ in types)
{
// we want this one
Object[] testClasses = typ.GetCustomAttributes(typeof(TestClassAttribute), false);
if (testClasses.Length > 0)
{
foreach (MethodInfo mi in typ.GetMethods())
{
Object[] testMethods = mi.GetCustomAttributes(typeof(TestMethodAttribute), false);
if (testMethods.Length > 0)
{
result.Add( new ClassAndMethod{TheClass=typ, TheMethod = mi});
}
}
}
}
return result;
}
protected void Invoke(Type testClass, MemberInfo method, string[] args)
{
// invoke this static, void method
DateTime start = DateTime.Now;
object result;
object baseObject = Activator.CreateInstance(testClass);
result = testClass.InvokeMember(method.Name, BindingFlags.Default | BindingFlags.InvokeMethod
, null, baseObject, args);
log.Info("RunTime: " + ((TimeSpan)(DateTime.Now - start)).TotalSeconds.ToString());
return;
}
}
public class TestClassAttribute : Attribute
{
}
public class TestMethodAttribute : Attribute
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment