Page 1 of 1

Automated Unit Testing Unit testing using C# and NUnit

#1 egof  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 132
  • Joined: 27-March 09

Posted 06 June 2009 - 09:08 AM

Prereqs:Im going to walk through Nunit using a simple soda machine example.

Lets start by creating a new c# class library.
Posted Image

Add the nunit frame work to your project
Posted Image

For this example Ive chosen to use a DLL but Nunit can easily work with executables.
Since this is a DLL project you cant launch it, but you can have another program do that job for you. When we go into debug mode we are going to have the NUnit GUI launch and run the code for us.
Lets set that up, right click on the soda library and go to properties
Posted Image

Next click on Debug tab on the left

Posted Image

Change the start action to “Start external program” and browse to the nunit gui. You can find in here: C:\Program Files\NUnit 2.4.7\bin\nunit.exe

This part is optional but its forces the Nunit GUI to automatically load our dll. Change the command line arguments to SodaLibrary.dll.

Posted Image

Now hit F5 to run it and you should see this
Posted Image
NUnit says that we haven’t built and tests yet.
So lets get started.
We are going to construct a SodaMachine that when we make a soda selection we receive a soda can of that type.
To accomplish this Im going to have 2 classes SodaMachine & SodaCan. The SodaMachine will dispense the soda when told the type. Im going to make the type an enum. In this example Im only going to have these types of sodas, Coke, Sprite & Jolt

Lets add the two classes and the enumeration to the project.
public enum SodaType
{
	Coke,
	Sprite,
	Jolt
}
public class SodaMachine
{
}
public class SodaCan
{
}



For testing purposes Im going to add another class and Im calling it SodaLibraryUnitTest. Your not required to add a separate class, in a real environment Id add a test class for each class that your testing.
Now to tell NUnit to test this you need to add [TestFixture] before every class you want to test
[TestFixture]
public class SodaLibraryUnitTest
{
}


Now your solution should have these classes in it.
Posted Image
If you run the project now you should see this.
Posted Image
Still no tests but it now knows about SodaLibraryUnitTest.

Im practicing TDD (Test Driven Development). This means I start with the tests then I write the code. In this example a person choosing a sode doesn’t care about the internals of the machine only that they get their soda.

In a normal soda machine cost is part of the soda but for this example I don’t care about that so the test become a lot simpler.
Test 1: Randomly pick a soda then check to see if I receive the correct type of soda.
If I also included cost into the “SodaMachine” then I would have a test for entering in exact change, to much change and not enough change. I might also consider keep pushing the button until it ran out of sodas and see that finally I receive nothing back.

My one and only test Im going to call it “PushARandomButtonAndGetASodaAndCheckToSeeIfItsTheCorrectType”

To tell NUnit to run this test you have to add the attribute “[Test]” and the method needs to be public and return void with no parameters.
Now this is what I have in my Unit test class.
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;//very important

namespace SodaLibrary
{
	[TestFixture]
	public class SodaLibraryUnitTest
	{
		[Test]
		public void PushARandomButtonAndGetASodaAndCheckToSeeIfItsTheCorrectType()
		{
		}
	}
}


Lets do a quick run and see what happens. Hit F5 then click the Run Button you should see this.
Posted Image
My one test ran and passed to bad there wasn’t anything of value to be tested yet.
In my test I need a soda machine
SodaMachine sMachine = new SodaMachine();

Of couse soda machines know how to dispence sodas if you tell it what type of soda that you want.
SodaCan mySodaCan = sMachine.Dispense(SodaType.Coke);

Now compile it.
Posted Image
You should receive an error because that method has not been built yet.
If your using VS2005 or later and you click on the Dispense name you should see the D get underlined
Posted Image
It wants to generate it for you, if your using something older then you have to type it in yourself.

Your soda machine now should look like this
public class SodaMachine
{
	internal SodaCan Dispense(SodaType sodaType)
	   {
			throw new Exception("The method or operation is not implemented.");
	   }
}


It now compiles
Lets get back to the testing. Im going to randomly pick a soda and test to see if I get it back.
[Test]
public void PushARandomButtonAndGetASodaAndCheckToSeeIfItsTheCorrectType()
{
	Random randomChooser = new Random(DateTime.Now.Second);
	SodaMachine sMachine = new SodaMachine();
	SodaCan myCanOfSoda = null;
	SodaType sodaChoice = SodaType.Jolt;//default value
	int randomSelection = randomChooser.Next(100);
	switch (randomSelection % 3)
	{
		case 0:
			sodaChoice = SodaType.Coke;
			break;
		case 1:
			sodaChoice = SodaType.Jolt;
			break;
		case 2:
			sodaChoice = SodaType.Sprite;
			break;
	}
	myCanOfSoda = sMachine.Dispense(sodaChoice);
	Assert.AreEqual(myCanOfSoda.SodaType, sodaChoice, "Wrong type returned");
}



Now when you compile you get an error again saying it doesn’t know that SodaCan doesn’t have a definition for Type.

Im going to add the property “Type” and 2 constructors one a default the other that accepts a “soda type”. At this point Im not certain if I’ll use the second constructor but its nice to have options.

This is now my soda can class
public class SodaCan
{
	private SodaType _SodaType;
	public SodaType SodaType
	{
		get { return _SodaType; }
		set { _SodaType = value; }
	}
	public SodaCan()
	{
	}
	public SodaCan(SodaType sodaType)
	{
		this.SodaType = sodaType;
	}
}




Now it all compiles so lets hit F5 and then the run button.

Posted Image

Looks like we have a problem.This will tell you the error and the line number, go ahead and put a break point on "myCanOfSoda = sMachine.Dispense(sodaChoice);" and run it again. You should be able to debug your code.


Posted Image


The error shows that we need to make the Dispence method work. Since I dont care about seeing if they entered the correct change or if I should return some change I just going to make it easy.


Now it looks like this
internal SodaCan Dispense(SodaType sodaType)
{
	switch (sodaType)
	{
		case SodaType.Sprite:
			return new SodaCan(SodaType.Sprite);
		case SodaType.Jolt:
			return new SodaCan(SodaType.Jolt);
		case SodaType.Coke:
			return new SodaCan(SodaType.Coke);
	}
	return null;
}



And running the NUnit again shows that the test is working.


Posted Image

Now we come to the interesting pieces of it.
Interesting point
1. If you’re the boss all you have to do is come in the morning get the latest version and run this to see whats going on.
2. Safety net for any new development. This current test will always check for any developer that wants to look.
3. You dont have to have a UI (web or windows) to load your business logic layer.





This is the safty net portion.

Lets assume business wants some changes, they give a spec to a new developer. The developer makes some changes to the code to accomplish the business requirement.
This is the “New & Improved” Dispense method per spec,
internal SodaCan Dispense(SodaType sodaType)
{
	switch (sodaType)
	{
		case SodaType.Sprite:
			return new SodaCan(SodaType.Sprite);
		case SodaType.Jolt:
			return new SodaCan(SodaType.Jolt); 
		case SodaType.Coke:
			//return new SodaCan(SodaType.Coke); 
			//business says this and that
			//then the developer copies and pastes
			return new SodaCan(SodaType.Jolt);  
	}
return null;
}



Questions for you
1. Does the unit test fail?
2. How can you improve the unit test?

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: Automated Unit Testing

#2 egof  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 20
  • View blog
  • Posts: 132
  • Joined: 27-March 09

Posted 09 March 2010 - 05:38 AM

I found a new use for unit testing, Code Security. A few days ago a unit test started failing I check into it and found that a stored proc had been changed. I check to see who had made the change but the person never checked it out they never left any finger prints on the stored proc. You say it was probably a fat finger mistake except the unknown person dropped the sproc into our staging area ready for production release. If the unit test hadnt failed it wouldnt have been found for a long time.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1