I’m working on a test framework that needs to be run by less-technical testers. The tests are data driven from a spreadsheet (google docs spreadsheet API + gdata.)
Tests will be run locally (for now at least) since there isn’t a test lab available for remote execution, and no CI. I didn’t want to have to require users to install NUnit to execute tests.
At first I started by writing a main() class and rolling my own assertions. But I decided that the parameterized test features of NUnit were worth the effort of a little research. NUnit can, in fact, be run programmatically, though the execution appears less flexible than with other frameworks.
I created a TestRunner class with main function:
using System; using NUnit.Core; using NUnit.Framework.Constraints; using NLog; namespace oneshore.qa.testrunner { class TestRunner { Logger log = NLog.LogManager.GetCurrentClassLogger(); public static void Main(String[] args) { //get from command line args String pathToTestLibrary = "C:\\dev\\oneshore.Tests.DLL"; DateTime startTime = System.DateTime.Now; log.Info("starting test execution..."); TestRunner runner = new TestRunner(); runner.run(pathToTestLibrary); log.Info("...test execution finished"); DateTime finishTime = System.DateTime.Now; TimeSpan elapsedTime = finishTime.Subtract(startTime); log.Info("total elapsed time: " + elapsedTime); } public void run(String pathToTestLibrary) { CoreExtensions.Host.InitializeService(); TestPackage testPackage = new TestPackage(@pathToTestLibrary); testPackage.BasePath = Path.GetDirectoryName(pathToTestLibrary); TestSuiteBuilder builder = new TestSuiteBuilder(); TestSuite suite = builder.Build(testPackage); TestResult result = suite.Run(new NullListener(), TestFilter.Empty); log.Debug("has results? " + result.HasResults); log.Debug("results count: " + result.Results.Count); log.Debug("success? " + result.IsSuccess); } } }
The advantage to running tests this way is that NUnit does not need to be installed (though DLLs for NUnit — nunit.core.dll & nunit.core.interfaces.dll — and any other dependencies like NLog need to be packaged with the TestRunner.) You can still write and execute your tests from NUnit while under development.
One disadvantage is that you don’t have the full test results by using the TestSuiteBuilder to bundle every test it finds into one suite. I’d like to find a way to improve that. You also can’t run more than one test assembly at the same time — you can create a nunit project xml for that — and at that point you might as well bundle the nunit test framework.
For now, my base test class (that each of my Nunit tests inherit from) reports via catching and counting assertion failures and writing to a log file. It can then use the Quality Center integration tool I described in an earlier post, though I’m planning on wiring it all together eventually, so anyone can run tests automatically by clicking on an icon, using a File Picker dialog to select the test library (see upcoming post) and have test results entered in QC.
This will allow distributed parameterized testing that can be done by anyone. I may try to set up a web UI like fitnesse for data driven tests as well.