C# School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become a C# Expert!

Join 300,360 C# Programmers for FREE! Get instant access to thousands of C# experts, tutorials, code snippets, and more! There are 1,696 people online right now. Registration is fast and FREE... Join Now!




Automated Unit Testing

 
Reply to this topicStart new topic

> Automated Unit Testing, Unit testing using C# and NUnit

egof
Group Icon



post 6 Jun, 2009 - 08:08 AM
Post #1


Prereqs:
  1. You will need to have the Nunit frame work installed http://www.nunit.org/index.php
  2. Visual Studio
Im going to walk through Nunit using a simple soda machine example.

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

Add the nunit frame work to your project
IPB 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
IPB Image

Next click on Debug tab on the left

IPB 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.

IPB Image

Now hit F5 to run it and you should see this
IPB 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.
CODE

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
CODE

[TestFixture]
public class SodaLibraryUnitTest
{
}

Now your solution should have these classes in it.
IPB Image
If you run the project now you should see this.
IPB 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.
CODE

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.
IPB 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
CODE
SodaMachine sMachine = new SodaMachine();

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

Now compile it.
IPB 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
IPB 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
CODE

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.
CODE

[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
CODE

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.

IPB 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.


IPB 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
CODE

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.


IPB 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,
CODE

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)
Attached File  SodaLibrary.zip ( 8.41k ) Number of downloads: 44
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!


Fast ReplyReply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/7/09 07:51PM

Live C# Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

C# Tutorials

Reference Sheets

C# Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month