5. Getting Started

5.1. Writing Tests - Quick Start

Writing tests with Zanebug is easy. There are 4 steps that you must take:

  1. Add a reference to the test engine .dll

    • Adapdev.UnitTest.dll

    This is located in the Zanebug install directory, normally located at:

    C:\Program Files\Zanebug\Adapdev.UnitTest.dll

    Within VS.NET, you can simply click on the Add Reference option and the Adapdev.UnitTest assembly can be selected.

  2. Add the namespace reference to your test class

    using System;
    using Adapdev.UnitTest;
    
    namespace UnitTest
    {
    	public class SimpleClassTest
    	{
    	}
    }
  3. Add the [TestFixture] attribute above the class name

    using System;
    using Adapdev.UnitTest;
    
    namespace UnitTest
    {
    	[TestFixture]
    	public class SimpleClassTest
    	{
    	}
    }

    This tells the Zanebug engine that this class is a test class and should be included in the TestSuite tree. If you have a class that contains [Test] methods, but is not marked with the [TestFixture] attribute, the class will be ignored by Zanebug.

  4. Add the [Test] attribute above each method that you want to run as a test, and the specific test logic

    Note

    The signature for all [Test] methods must be public void with no return value

    using System;
    using Adapdev.UnitTest;
    
    namespace UnitTest
    {
    	[TestFixture]
    	public class SimpleClassTest
    	{
    		[Test]
    		public void FirstTest()
    		{
    			// ... test logic goes here ...
    		}
    
    		[Test]
    		public void SecondTest()
    		{
    			// ... test logic goes here ...
    		}
    	}
    }

Although Zanebug contains several other attributes and features, the above steps are at the heart of any unit test.

5.2. Writing Tests - Example

In order to demonstrate a full test, let's use a modified version of the famous "Hello World" example. We first create a simple class with two methods:

  • SayHello() - simply returns "Hello!"

  • SayHello(string name) - returns "Hello [name]!"

using System;

namespace Examples
{
	public class HelloWorld
	{
		public static string SayHello()
		{
			return "Hello!";
		}

		public static string SayHello(string name)
		{
			return String.Format("Hello {0}!", name);
		}
	}
}

In a traditional testing environment, this would most likely be validated with a simple console application:

using System;
using Examples;

namespace ConsoleApplication1
{
	class Class1
	{
		[STAThread]
		static void Main(string[] args)
		{
			Console.WriteLine(HelloWorld.SayHello());
			Console.WriteLine(HelloWorld.SayHello("Sean"));
			Console.ReadLine();
		}
	}
}

This would produce the following output:

Hello!

Hello Sean!

Unfortunately, this is a very rudimentary way to test and relies on human interaction to validate that a component behaved correctly. The more complex the component, the more error-prone.

Using Zanebug, automated tests can be easily written and rerun on a continual basis. To address the above example, we would write the following unit test:

using System;
using Adapdev.UnitTest;
using Examples;

namespace Examples.Test
{
	[TestFixture]
	public class HelloWorldTest
	{
		[Test]
		public void SayHello()
		{
			Assert.AreEqual("Hello!", HelloWorld.SayHello());
		}

		[Test]
		public void SayHelloWithName()
		{
			Assert.AreEqual("Hello Sean!", HelloWorld.SayHello("Sean"));
		}
	}
}

The above test is very simple. The first test, SayHello(), simple validates that the text being returned from the HelloWorld.SayHello() method is the expected text. The second test does the same thing, but tests the result with a name being passed in.

In both instances, the Assert class is used to test behavior. Assert is a key part of writing unit tests, since it does the actual work. When an assertion is performed, only one of two outcomes is possible -- correct or incorrect. If the response is correct, then that portion of the test passes. If the response is incorrect, an AssertionException is thrown and the test immediately fails without continuing.

The Assert class contains multiple methods. Listed below are some of the more common ones (see the API documentation for a full list):

  • AreEqual(object o1, object o2)

    Validates that the two objects are equal

    string name1 = "Joe";
    string name2 = "Joe";
    string name3 = "Joe Schmoe";
    
    Assert.AreEqual(name1,name2); // Passes
    Assert.AreEqual(name1,name3); // Fails
    
  • AreSame(object o1, object o2)

    Validates that the two objects have the same reference (i.e. point to the same object)

    CustomObject o1 = new CustomObject();
    CustomObject o2 = new CustomObject();
    CustomObject o3 = o1;
    
    Assert.AreSame(o1, o2); // Fails
    Assert.AreSame(o1, o3); // Passes
    
  • IsFalse(bool condition)

    Validates that a given condition is false

    int i = 1;
    int j = 2;
    int k = 2;
    
    Assert.IsFalse(i == j); // Passes
    Assert.IsFalse(j == k); // Fails
    
  • IsTrue(bool condition)

    Validates that a given condition is true

    int i = 1;
    int j = 2;
    int k = 2;
    
    Assert.IsTrue(i == j); // Fails
    Assert.IsTrue(j == k); // Passes
    

Test methods can (and normally should) contain multiple assertions. Revisiting our original HelloWorld example, we'll add some more assertions:

using System;
using Adapdev.UnitTest;
using Examples;

namespace Examples.Test
{
	[TestFixture]
	public class HelloWorldTest
	{
		[Test]
		public void SayHello()
		{
			Assert.AreEqual("Hello!", HelloWorld.SayHello());
			Assert.IsTrue(HelloWorld.SayHello().Length == 6);
		}

		[Test]
		public void SayHelloWithName()
		{
			Assert.AreEqual("Hello Sean!", HelloWorld.SayHello("Sean"));
			Assert.IsTrue(HelloWorld.SayHello("Sean").Length == 11);
		}
	}
}

The multiple assertions in the above example don't add much value in this instance, but it gets the point across...

Now, to round things out, let's show an explicit example of a test failing:

using System;
using Adapdev.UnitTest;
using Examples;

namespace Examples.Test
{
	[TestFixture]
	public class HelloWorldTest
	{
		[Test]
		public void SayHello()
		{
			// Test passes and continues
			Assert.AreEqual("Hello!", HelloWorld.SayHello()); 

			// Test fails because length is 6
			Assert.IsTrue(HelloWorld.SayHello().Length == 5); 
		}

		[Test]
		public void SayHelloWithName()
		{
			// Test fails because the returned value is Hello instead of Bonjour
			Assert.AreEqual("Bonjour Sean!", HelloWorld.SayHello("Sean")); 

			// Not tested, since the test has already failed
			Assert.IsTrue(HelloWorld.SayHello("Sean").Length == 11); 
		}
	}
}

5.3. Basic Steps - Summary

In summary, to write a test you need the following basic components:

  1. Add a reference to the test engine in your project (Adapdev.UnitTest.dll)

  2. Add a namespace reference in your code

    ...
    using Adapdev.UnitTest
    ...
    
  3. Add a TestFixture attribute above your class declaration

    ...
    using Adapdev.UnitTest
    ...
    
    namespace XXX{
    
        [TestFixture]
        public class YYY{
    
        }
    }
    
  4. Add a Test attribute above a test method

    ...
    using Adapdev.UnitTest
    ...
    
    namespace XXX{
    
        [TestFixture]
        public class YYY{
    
            [Test]
            public void ZZZ(){
            }
    
        }
    }
    
  5. Add any assertions within your test method

    ...
    using Adapdev.UnitTest
    ...
    
    namespace XXX{
    
        [TestFixture]
        public class YYY{
            ...
            Assert.IsTrue(some statement);
            ...
        }
    }