Views
3 years ago

DNDJ 3-6 June.indd - sys-con.com's archive of magazines - SYS ...

DNDJ 3-6 June.indd - sys-con.com's archive of magazines - SYS ...

Tomorrow’s

Tomorrow’s .NETZanebugThe development of an automated unit testing toolBY SEANMCCORMACKautomated unit testinghas rapidly growninto an integral part ofthe development lifecycle. With the increased usage ofagile disciplines such as eXtremeProgramming (XP) and Test DrivenDevelopment (TDD), along with theintroduction of continuous integrationtools such as CruiseControl.NET and Draco.NET, the need forautomated testing tools has growneven stronger. If you’ve done unittesting in .NET, then chances areyou’ve worked with NUnit, whichwas one of the first feature-richtesting applications available to the.NET Community.This article will outline the developmentof a similar testing tool calledZanebug. The need for Zanebug cameabout while developing a persistenceframework for an eCommercecompany. At the time, our teamwas using NUnit for all of our testingneeds. Although it’s an excellentframework, it unfortunately didn’tprovide all of the testing capabilitieswe needed – especially in the realmof performance-centric testing. As aresult, I began to develop Zanebug asan open-source tool to address someof those needs, along with providinga more feature-rich UI. The currentversion of Zanebug provides a robustUI, a console version, and VS.NETintegration.The development of Zanebughas been a fascinating experience.Although it’s a free application, thechallenges I encountered were similarto those of a commercial application.Additionally, because Zanebug hasbeen used to test hundreds of realworldapplications, it provides greatinsight into the challenges almostany development team may face, andhow to solve them.4The Joy of AppDomainsDynamically Loading AssembliesBy far, the most challengingaspect of Zanebug was dealingwith AppDomains. Anytime youlaunch a new application it runsin an AppDomain. When youdynamically load an assemblyinto memory, it is added to thelist of assemblies in the currentAppDomain. This unfortunatelyputs a lock on the loaded assembly,preventing it from being overwritten.For Zanebug to work effectively,it needs to load an assemblywithout locking so that a developercan make changes and recompile.If the assembly is locked by theAppDomain, the developer can’trecompile his assembly withoutfirst closing the Zanebug GUI –which is far from ideal. In a perfectworld, AppDomain would allow youto not only load an assembly intomemory, but also unload it. Sincef 1Figure 1: Zanebug GUI (main)this isn’t the case with .NET 1.1, adifferent solution is required.The way to get around this isto create a remote AppDomainthat copies the target assemblyto a separate location and load itfrom there. This allows compilationto take place without any issues,while still being able to run tests.Unfortunately, AppDomain is a verypicky class, and requires a lot of testingto get it just right. To help centralizethe AppDomain functionality,an AppDomainManager class wascreated which allows you to load anassembly either locally or remotelywith only a few API calls and hidesthe complexity of the AppDomainremoting. Another useful class thatwas created is AssemblyCache.Since loading assemblies into anAppDomain is an expensive operation,the AssemblyCache preventsthis from happening more thanonce for any given assembly, andspeeds the retrieval process. Both ofthese classes are available with theZanebug source code.42June 2005 • dotnetdevelopersjournal.com

f 2Figure 2: Zanebug GUI (results)Assembly ProbingWhen you dynamically load anassembly, the CLR loads not only thatassembly but also all of its dependencies.This can prove to be veryproblematic, since the CLR will onlytraverse the GAC and the immediateexecutable directory or subdirectories.If the CLR can’t find what it’s lookingfor, an exception is raised. Thisbecomes an even bigger issue whendealing with a remote AppDomainthat copies the assembly to a newlocation. Fortunately, there’s a way toaddress this using the AppDomain.AssemblyResolve event. WithAssemblyResolve, you can point theruntime to a different location outsideof the common probing paths. In thecase of Zanebug, the CLR probes thenew temp path, and AssemblyResolvethen probes the original assemblypath. For your own purposes, you canpoint it to any location you want.RemotingThe fact that assemblies aredynamically loaded into a remoteAppDomain brings a new slewof remoting issues to the table.The first main issue is that forthe Zanebug GUI to interact withobjects in the remote AppDomain,they have to either be markedas Serializable or inherit fromMarshalByRefObject. The Serializableattribute allows an object to be sentback and forth as a value object.The MarshalByRefObject inheritanceallows calls to be made to aremote object. An example of thisis the TestRunner class, which actuallyexecutes the tests in the remoteAppDomain. When a user clicks the“Run” button on the Zanebug GUI,it must tell the TestRunner to startrunning the tests. In order for thisto work, TestRunner has to inheritfrom MarshalByRefObject so thatthe call to TestRunner can be maderemotely from the Zanebug GUI.Likewise, the test results need to besent back to the Zanebug GUI fromthe TestRunner. This is possible bymarking the TestAssemblyResult asSerializable.A second issue is that consoleoutput within a Test wouldn’t displayin the Zanebug GUI, since itexecutes in the remote AppDomain.This required intercepting the consoleoutput and redirecting it to aStringWriter, which is then addedto the test result and sent back overto the GUI via the serialized resultsobject. The benefit of this approachis that all console output is storedwithin the test result, allowing you tosave the console output and archive itfor future viewing.A third issue was logging.Zanebug uses the excellent log4netlibrary for all logging. Unfortunately,logging runs into the same issueswith remoting. The log4net consoleoutput wouldn’t be displayed andlog files wouldn’t be created becausethe primary AppDomain had alock on it. The way this is resolvedis to use the UDP appender andTraceTool to view the output. Thisallows for full logging to take placeremotely and for the developer toview the results in real time.The last issue was with callbacks.Since Zanebug uses a progress bar todisplay how many tests have executed,it’s necessary to send informationto the Zanebug GUI each time a testcompleted, so that it can incrementthe progress. This is possible withevent delegates. Event delegates areextremely powerful, allowing formultiple classes to “subscribe” to anevent and be notified when that eventoccurs. Even better, event delegateswork over remoting (as long as theinformation you send back is markedas Serializable). With delegates, I wasable to create a number of events forthe Zanebug GUI to subscribe to.4Strong Naming and VersioningAnother interesting problemwas whether to strong name theZanebug assemblies. The Zanebugapplication, and all of its assemblies,is normally installed toC:\Program Files\Zanebug. Whenyou load a test assembly from, say,D:\projects\Foo\bin\Debug, it willsearch for the Zanebug assemblieswithin Foo’s Debug directory (asmentioned in the Assembly Probingsection above). Therefore, it’s necessaryto somehow add the Zanebugassemblies to Foo’s path. The twoways to do this are to either copythe Zanebug assemblies to theFoo directory or strong name theZanebug assemblies and add themto the GAC. For various reasons, thecopying approach wouldn’t work forZanebug, so the second approachwas necessary. This introduced twoproblems however.Installing to the GACIf you use an installer otherthan the default VS.NET Setupf 3Figure 3: Zanebug ConsoleAUTHOR BIOSean is a C# MVP and serves assenior systems analyst for MillerBrewing Co., leading their .NETArchitecture team. His previousexperience includes serving asthe director of technology foran eCommerce company and atouch-screen voting company, leaddeveloper for an enterprise contentmanagement company, technicalmanager for a national automotiveportal, and as an Arabic linguist andcryptologist for the Department ofDefense. Sean currently leads theAdapdev open-source foundation,helping to develop top-notch opensource applications for the .NETcommunity. His two most recentapplications include Zanebug (aunit testing tool) and Codus (a codegeneration tool).4smccormack@adapdev.comdotnetdevelopersjournal.com • June 200543

DNDJ 6-3 web.indd - sys-con.com's archive of magazines - SYS ...
DNDJ 6-3WEB.indd - sys-con.com's archive of magazines - SYS ...
DNDJ 3-11 Nov.indd - sys-con.com's archive of magazines - SYS ...
DNDJ 6-4 web.indd - sys-con.com's archive of magazines - SYS ...
DNDJ February 3-2.indd - sys-con.com's archive of magazines ...
DNDJ 4-9.indd - sys-con.com's archive of magazines - SYS-CON ...
DNDJ 3-7 July.indd - sys-con.com's archive of magazines - SYS ...
JAVA Vol 3 Issue4 - sys-con.com's archive of magazines
DNDJ 4-8.indd - sys-con.com's archive of magazines - SYS-CON ...
JDJ 10-10.indd - sys-con.com's archive of magazines - SYS-CON ...
LWM 3-12.indd - sys-con.com's archive of magazines - SYS-CON ...
issue 6 - sys-con.com's archive of magazines - SYS-CON Media
in PowerBuilder - sys-con.com's archive of magazines - SYS-CON ...
JDJ 10-12 Dec.indd - sys-con.com's archive of magazines
Conclusion - sys-con.com's archive of magazines
JDJ 12-1 Jan.indd - sys-con.com's archive of magazines - SYS-CON ...
LinuxWorld.com - sys-con.com's archive of magazines - SYS-CON ...
jdjedge conference & expo - sys-con.com's archive of magazines ...
DNDJ 2-8.qxd - sys-con.com's archive of magazines - SYS-CON ...
JDJ 10-6.indd - sys-con.com's archive of magazines - SYS-CON Media
WebSphere vs WebLogic: - sys-con.com's archive of magazines ...
issue 10 - sys-con.com's archive of magazines - SYS-CON Media
SCOTT McNEALY - sys-con.com's archive of magazines - SYS-CON ...
MX - sys-con.com's archive of magazines - SYS-CON Media
!"0&$+ ,!" - sys-con.com's archive of magazines - SYS-CON Media
issue 9 - sys-con.com's archive of magazines - SYS-CON Media
Figure 1 - sys-con.com's archive of magazines - SYS-CON Media
Bulletproof Web Services - sys-con.com's archive of magazines ...
NET - sys-con.com's archive of magazines - SYS-CON Media
Web Services Edge 2003 - sys-con.com's archive of magazines ...