Introduction
Whenever you need to test a new code library with a lot of public
methods and without a unit test case written from the developer, you can automatically generate a NUnit test case, method by method, with NUTestCaseCodeGenerator
, that allows you to generate a C# source code template for NUnit test case starting from library methods to test.
To run the application, the following is required:
- Windows XP SP2 or Windows 2003 Server SP1
- IIS 5.1/6.0 (add from Windows Components)
- Visual Studio 2005
- Microsoft Framework 2.0 (that will already be installed by SP2 or VS05)
- NUNIT Framework 2.4.7
NUTestCaseCodeGenerator
doesn't check system requirements, it's only a starting idea for didactic use and does not have a GUI or written code optimized.
Background
A unit test is a test for the smallest testable part of an application (methods). Unit testing is typically done by software developers to ensure that the code they have written meets software requirements and behaves as the developer intended.
Test-driven software development technique requires that an automated unit test, defining requirements of the code, is written before each aspect of the code itself. These tests contain assertions that are either true or false.
Running the tests gives rapid confirmation of correct behavior as the code evolves and is refactored. Testing frameworks like NUnit provide a mechanism for creating and running sets of automated test cases. In test-driven development, each feature begins with writing a test, so for each method, the developer should have to write a unit tests related case. Every method will have more than one test case depending on the complexity of the method signature.
In the real world, developers do not have the time to write a unit test and the software is tested only during integration test or system test phases, but, of course, in these phases not all methods or modules interactions with all possible parameters are called and not all regressions are checked. Consequently, test code coverage and software quality is low, and integration and system test phases are very hard.
Another consideration regarding the importance of unit tests, even if making unit tests takes a lot of time, is that they are the only types of tests that are really automatizable, because you're working with the code, so unit tests can run without a tester. This is better because integration and system tests are difficult to make automatizable and are time consuming, because you are working with GUI interaction.
As I have already said, the real world of software development is not "test-first" but "test-last", and there isn't a clear separation between main test phases (Unit, Integration and System), thus, more and more often, a mix is chosen. Take advantage of the unit test framework in the integration and system test phases, using framework utility functionality for the automatic evaluation of the results without human action, and embedding inside unit test cases, not a single method call, but a procedure as sequences (methods to call and GUI interaction). This is a different way of testing main software user functionality, which is typically tested manually during integration and system test phases.
There are two problems to make a test really automatic. First, make the "action" automatic (call the method for library tests or click the button for GUI test). Second, make automatic the evaluation of the action results.
There are many frameworks that help you to automatize software tests, and you make them work together. I just spoke of NUnit for code library unit testing, but it is not the only one, there is WatiN for ASP.NET pages and NUnitForms for .NET Windows Forms.
In the example below, you can see an unconventional NUnit test, usable for automatized integration and system tests, where two test frameworks work together for executing a sequence that is more complex than a unit test.
This could be a use (or abuse) of a unit test but, as I have already said, this is for the real world.
using System;
using NUnit.Framework;
using Watin.Core;
namespace ExampleLibraryToTest_NU
{
[TestFixture, Description("ExampleLibraryToTest.Class1")]
public class Class1_Fixture
{
[Test, Description("ASPNET GUI testing")]
public void ASPNET_GUI_Testing_TC()
{
IE ie = new IE("http://localhost:1036/WebSite1/Default.aspx");
Assert.IsNotNull(ie, "Error creating IE instance.");
string cellVal = ie.TableCell(Find.ByIndex(0)).Text;
Assert.That(cellVal, Is.EqualTo("ValueExpected"), "Error");
ie.Button(Find.ById(New Regex(OKButton))).Click()
string ret = UserLibrary.GetResultOfClick();
Assert.That(ret, Is.EqualTo("ValueExpected"), "Error");
}
}
}
Using the Code
Before starting the application, open a *.config file and set the NUnit installation path:
add key="NUnitFrameworkInstall" value="C:\Program Files\NUnit 2.4.7\"
NUTestCaseCodeGenerator works in two steps:
First load in the left side panel .NET assembly with the library to test, drag and drop from the left side panel to the right side panel a class with method to test and check the desired method. From the right side panel context menu, select the first option, "Create NUnit source code and VS project".
Visual Studio will be opened with a project template of NUnit test case source code, so you will have to valorize the method input variable and the NUnit statement for return evaluation, Assert.That(return, Is.EqualTo("put expected value here"))
and build the project.
For example, if you have to test a method with a signature like this, with...
public bool M3_WithClass(int MyInt1, int MyInt2, Class1_2 cl1_2)
... this will be the Nunit test case code automatically generated by the application:
namespace ExampleLibraryToTest_NU
{
[TestFixture, Description("ExampleLibraryToTest.Class1")]
public class Class1_Fixture
{
[Test, Description("M3_WithClass")]
public void M3_WithClass_TC()
{
Console.Out.WriteLine( "Try to instance Class" );
ExampleLibraryToTest.Class1 myClToTest = new ExampleLibraryToTest.Class1();
Assert.IsNotNull(myClToTest,
"Error creating ExampleLibraryToTest.Class1 instance.");
Console.Out.WriteLine("instance ok");
System.Int32 MyInt1 = 0;
System.Int32 MyInt2 = 0;
Console.Out.WriteLine( "Try to instance Class" );
ExampleLibraryToTest.Class1_2 cl1_2 = new ExampleLibraryToTest.Class1_2();
Assert.IsNotNull(cl1_2,
"Error creating ExampleLibraryToTest.Class1_2 instance.");
Console.Out.WriteLine("instance ok");
Console.Out.WriteLine("Call the method");
System.Boolean ret = myClToTest.M3_WithClass(MyInt1,MyInt2,cl1_2);
Assert.That(ret, Is.EqualTo("Boolean"), "Error");
Console.Out.WriteLine("Method ok");
}
}
}
In the second step load in the left side panel NUnit assembly with a test case just created, drag and drop from the left side panel to the right side panel a class fixture with a test case. From the right side panel context menu, select the second option "Create NUnit project and WebApplication".
A NUnit GUI for running a test case from the GUI application will be created and opened automatically and a Web page made to call the same test case from a different environment caller. This allows you to check security and access problems because, in a Windows application process, the owner is a logon user, otherwise, in a Web application process the owner depends on the configuration.
In the zip file attached, there is a .NET library ExampleClassLibraryToTest
for demo use, try to load it.
Points of Interest
Here is a brief summary of points of interest because the code is too large (see the source attached):
- The core of application is a recursive method (
RecursiveInspecting()
) to explore an assembly with Reflection and load a treeview (see INSPECTING region in Actions.cs). - Create a Visual Studio project: directory structure and AssemblyInfo.cs, projectName.csproj, NUnitTestCase.cs files (see VS PROJECT region in Actions.cs).
- Create an NUnit project file: XML file .nunit (see
CreateNUnitProj()
method in Actions.cs). - Create a Web Application in local IIS: create a virtual directory, directory structure on wwwroot and all files and DLL (see WEB APPLICATION region in Actions.cs).
To Do
All files, XML, CS and others are built with the StringBuilder
class like a text file, but it would be better to use an appropriate builder for each type of file, or use class Serialization instead of a builder (a more elegant solution).
History
- 8th August, 2008: Initial post
- 12th August, 2008: Article updated
- 13th August, 2008: Source code and article updated