Reflection is a major feature that distinguishes managed languages such as. NET and Java from traditional languages (such as C ++ and Delphi). Through reflection, we can dynamically create classes and call methods. After considering the nunit function, I thought I could use this feature to do it. So I made a manual exercise and basically achieved the effect. The nunit simulation framework is as follows:
// ================================================ =
Unitdll (simulate nunit. Framework)
[Attributeusage (attributetargets. Class)]
Public class testfixtureattribute: system. Attribute
{
Public testfixtureattribute ()
{
}
}
[Attributeusage (attributetargets. Method)]
Public class test: system. Attribute
{
Public test ()
{
}
}
// The preceding two attributes are used to identify the classes and methods to be tested.
/// <Summary>
/// Assert exception class, used to throw an Assert exception
/// </Summary>
Public class vassertexception: system. applicationexception
{
Private string m_expstr = "";
Public vassertexception ()
{
}
Public vassertexception (string ERR)
{
M_expstr = err;
}
Public String exceptionstr
{
Get {return m_expstr ;}
Set {m_expstr = value ;}
}
}
// The above is an exception class. When assert fails, an exception is thrown.
/// <Summary>
/// Assert class for unit test
/// </Summary>
Public class assert
{
Public assert ()
{
}
Public static void areequal (Object expected, object actual)
{
If (expected! = Actual)
{
String STR = "expected is:" + expected + "but actual is:" + actual;
Vassertexception E = new vassertexception (STR );
Throw E;
}
}
}
// The above provides the test method class, areequal, and assert class provided by nunit.
// ================================================ ==================================
Testdll: class for unit testing. Use the unitdll provided above.
/// <Summary>
//// Class for unit test
/// </Summary>
[Testfixture] // identifies the class to be tested
Public class vunittest
{
Public vunittest ()
{
System. Console. writeline ("Now the unit test class create ");
}
[Test]
Public void testmethod ()
{
System. Console. writeline ("this is a unit test method ");
Assert. areequal (1, 2); // use the assert class provided by unitdll for unit testing
}
// ==========================================
Unittest.exe simulates nunit.exe and provides a win form, which is displayed in Treeview mode.
The interface code is relatively simple and is not provided. It provides several key reflection and call codes:
Private void loaddll ()
{
This. treeview1.nodes. Clear ();
Rootnode = This. treeview1.nodes. Add (openfiledialog1.filename );
A = assembly. loadfrom (openfiledialog1.filename );
Type [] types = A. gettypes ();
Foreach (type in types)
{
Object [] attributes = type. getcustomattributes (false );
Foreach (Object OBJ in attributes)
{
// The class with the test information is obtained.
If (obj. GetType () = typeof (testfixtureattribute ))
{
// Add a class name
Treenode node = rootnode. nodes. Add (type. Name );
Methodinfo [] Methods = type. getmethods ();
Foreach (methodinfo method in methods)
{
Object [] methodattributes = method. getcustomattributes (false );
Foreach (Object objmehtodd in methodattributes)
{
If (objmehtodd. GetType () = typeof (TEST ))
{
Node. nodes. Add (method. Name );
}
}
}
}
}
}
This. treeview1.expandall ();
}
// The code above is relatively simple. Use reflection to obtain the classes and methods to be tested and display them in a Treeview.
Object OBJ = activator. createinstance (type );
Methodinfo method = type. getmethod (this. treeview1.selectednode. Text );
If (Method = NULL)
{
MessageBox. Show ("method mismatch ");
Return;
}
Object [] parameters = new object [0];
Method. Invoke (OBJ, parameters );
This. listbox1.items. insert (0, "OK ");
Setlabel (true );
}
Catch (system. reflection. targetinvocationexception ex)
{
String STR = ex. tostring ();
Exception exc = ex. innerexception;
If (EXC. GetType () = typeof (vassertexception ))
{
Vassertexception objex = (vassertexception) exc;
String SSTR = objex. exceptionstr;
This. listbox1.items. insert (0, SSTR );
This. listbox1.items. insert (0, exc. stacktrace );
This. listbox1.items. insert (0, Ex. stacktrace );
Setlabel (false );
}
// The above code is equivalent to run on the nunit interface and is also a core piece.
// Create the class to be tested (createinstance) and call invoke
// Determine whether the assertion fails (whether a custom exception is thrown out). If any, the test fails and the failure information is displayed on the interface.
// ================================================ ======================
Conclusion: The nunit effect can be basically achieved, but the business and interface code are mixed together, there is no good isolation,
A better way is to seal the reflection and provide an interface for interface response.
Thank you for your comments.