About Me

Showing posts with label unit testing. Show all posts
Showing posts with label unit testing. Show all posts

Monday, September 19, 2011

Good unit tests

This article is a short description of the way how to create good unit tests.
I want to recomend the book "The Art Of Unit Testing" to every one who is facing with requirements to cover its code with unit tests. Its really great book that contains enough descriptions and examples (in C#) to write the correct tests.
What's the "correct" tests are? Related to the book, "correct" tests should follow the following requirements:
  • It’s an automated piece of code that invokes a different method and
    then checks some assumptions on the logical behavior of that
    method or class.

    Correct unit test should contain 3 small piece of code - Arrange-Action-Assert (AAA):
    [Test]
    public void SetCurrentSpeed_NewSpeedOfThePlaneIsBiggerThenMinimumTakeOffSpeed_PlaneCanTakeOff()
      {
       ///Arrange - prepare object that is going to be tested
       Plane plane = PlanesFactory.CreatePlane(Planes.Boeing747_400);
       int takeOffSpeed = 160;
    
       ///Action - execute method that's going to be tested
       plane.SetCurrentSpeed(takeOffSpeed);
    
       ///Assert - test the state of the object
       Assert.IsTrue(plane.CanTakeOff);
    
      }
  • It’s written using a unit-testing framework.
    Normally you can use NUnit framework for it. Most of companies I worked for used NUnit. But, there are other you can also use. The principles are the same everywhere.
  • It can be written easily.
    As you may see in example above, its not need to create big amount of lines of code. The code should contain minimum lines of code. In my experience, most of unit test code is taking Arrange part. Its taking a lot of lines to initialize all objects and prepare them for the execution.
    Using Moq library can significant reduce the number of lines you have to type to create stubs of the components you are going to use in the test.
    For instance, in the example below we are going to test, is factory creates correct plane:
    [Test]
      public void SetCurrentSpeed_NewSpeedOfThePlaneIsBiggerThenMinimumTakeOffSpeed_PlaneCanTakeOff()
      {
       ///Arrange - prepare object that is going to be tested
       Mock<iwings> moqWings = new Mock<iwings>();
       moqWings.Setup(f => f.WingSize).Returns(100);
    
       ///Our factory will create plane according to the size of its wings.
       /// The take off speed depends of the size of the wing
       Plane plane = PlanesFactory.CreatePlane(moqWings.Object);
       int takeOffSpeed = 160;
    
       ///Action - execute method that's going to be tested
       plane.SetCurrentSpeed(takeOffSpeed);
    
       ///Assert - test the state of the object
       Assert.IsTrue(plane.CanTakeOff);
    
      }
    
    As you may see from the example, the PlanesFactory takes an object that describes wings of the plane. Without using Moq, you would need to create test class that implements IWing interface, create instance, set the size of the wing to 100 and only after that pass it to the the PlanesFactory. Moq is making your life easier, the code less and much more easier to understand - it creates the instance of IFly interface on the fly for you.
  • It runs quickly.
    This is obvious, as more simple your test code, as more fast it working
  • It can be executed repeatedly by anyone on the development team.
    One of the purpose of writing unit tests is to make the life of your coworkers easier. When the guy from your team want to change your code or a code in a functionality that relates to the one you created, he need to be sure, that he did not break something.
    The guy is changing the code, then running all existing unit tests and saying "Woohoo! I did not break anything!". As more the code of your applicaiton is covered with the unit tests, as more free can feel the developer while adding a modifications to the code.
Things above are principles of writing unit tests.
Below, I going to specify few  important recommendations about the structure of the unit test.
They were also taken from the book with my short explanation.


  • It’s common practice to have one test class per tested class, one test
    project per tested project, and at least one test method per tested method.
    This advice related to the structure of your code. Everything is obvious here. To make the code clear and easy to read and modify, create a separate file for each testing class.
    In my opinion, sometimes, when you are writing a test to some manager class that contains a lot of methods independent from each other, its better to have one class for each testing method. In this case, its better to create a folder with the name of the manager class and put there all methods testing classes:
  • Name your tests clearly using the following model: [MethodUnderTest]_[Scenario]_[ExpectedBehavior].
    As you may see in example above, my test class is following to the requirement and has name "SetCurrentSpeed_NewSpeedOfThePlaneIsBiggerThenMinimumTakeOffSpeed_PlaneCanTakeOff".
    The reason of naming the method in this way is that its much easier to understand which tests did not pass, what functionality they do and where are they are locating.
    You may also be less strict in using the rule. The main idea of naming the test method is that  its name should follow if/then manner : "If_I_Put_New_Speed_Of_Plane_To_The_Value_That_Is_Bigger_Then_A_TakeOff_Speed_Then_CanTakeOff_property_should_be_set". This name can be also quite informative.
  • Use the [SetUp] and [TearDown] attributes to reuse code in your tests, such as code for creating and initializing objects all your tests use.
    If your test requires initialization of the DB or some complex object like COM, this staff should be placed to the [SetUp] method. The reason is simple - to keep the testing code as much simpler as possible.
    If you have few classes that doing the same in [SetUp] and [TearDown], create an abstract test class and move all logic in there. Then create your tests as inheritors of that base class.
    Don't confuse two attributes [SetUp] and [SetUpFixture]. [SetUp] is calling before EACH TEST in a test class and [SetUpFixture] is calling before FIRST TEST in a class will be called.
  • Don’t use [SetUp] and [TearDown] to initialize or destroy objects that
    aren’t shared throughout the test class in all the tests, because it makes
    the tests less understandable. Someone reading your code won’t
    know which tests use the logic inside the setup method and which
    don’t.

    Let's take a look on the example below:
    [TestFixture]
     public class PlaneTests
     {
      private iengine[] _enginesForTestCollection;
    
      [SetUp]
      public void SetUp()
      {
       Mock<iengine>() engine1 = new Mock<iengine>();
       engine1.Setup(f => f.Power).Returns(50);
    
       Mock<iengine>() engine2 = new Mock<iengine>();
       engine2.Setup(f => f.Power).Returns(99);
       
       _enginesForTestCollection = new IEngine[] {engine1.Object, engine2.Object};
      }
    
      [Test]
      public void SetCurrentSpeed_NewSpeedOfThePlaneIsBiggerThenMinimumTakeOffSpeed_PlaneCanTakeOff()
      {
       ///Arrange - prepare object that is going to be tested
       ...
       
       Plane plane = PlanesFactory.CreatePlane(moqWings.Object, _enginesForTestCollection[0]);
       int takeOffSpeed = 160;
    
       ///Action - execute method that's going to be tested
       plane.SetCurrentSpeed(takeOffSpeed);
    
       ///Assert - test the state of the object
       Assert.IsTrue(plane.CanTakeOff);
    
      }
    
      [Test]
      public void SetCurrentSpeed_NewSpeedOfThePlaneIsLessThenMinimumTakeOffSpeed_PlaneCanNotTakeOff()
      {
       ///Arrange - prepare object that is going to be tested
       ...
       Plane plane = PlanesFactory.CreatePlane(moqWings.Object, _enginesForTestCollection[1]);
       int takeOffSpeed = 120;
    
       ///Action - execute method that's going to be tested
       plane.SetCurrentSpeed(takeOffSpeed);
    
       ///Assert - test the state of the object
       Assert.IsFalse(plane.CanTakeOff);
    
      }
    
     }
    
    As you may see, I doing the thing that should not - initializing engines in the setup variable.
    I'm expecting, that my _enginesForTestCollection will have an engine for each test.
    Then, when I'm writing test, I'll use an appropriate engine.
    First problem with this approach is that when new guy, or even you, will read this code in the future, he will have to find, where is _enginesForTestCollection[1] is initializing and check the initial values of it. When your test class contains dozen of tests, it may be difficult.
    The second problem may come when you will want to write new test. In this case you will have a temptation to use one of existing engines. Then, if requirements will change and you will need to change the parameters of the engine, this change will affect two or more tests, depends of how many times you used the same engine. As result, some tests may not working or, what's more dangerous, some tests will remain success but they will not test things that were expected at the beginning.
    That's why its better to create each engine in its own test method and don't create unique moq for all tests.

Tuesday, February 22, 2011

How to make Moq object to return different values on each invocation

Today I stacked with the issue how to make Moq function to return different values when its calling by testing unit.

Let's see on example:
[Test]
public void Value_should_be_assigned_on_property_value()
{
///Arrange
...
DrugAgreement agreement = new DrugAgreement();

agreementsManager.Setup(f => f.Create()).Returns(agreement);

///Action
testingUnit.AssignPropertyOnNewlyCreatedObject("propertyValue");

///Assert
Assert.AreEqual("propertyValue", agreement.TestingProperty);
}

The code above expecting that the testing unit will create new instance of the object by calling Create, and change its TestingProperty value to propertyValue

Now, let's implement the code for it:
public DrugAgreement AssignPropertyOnNewlyCreatedObject(string newValue) {
    var obj = manager.Create();
    obj.TestingProperty = newValue;
    return obj;
}

The code above will work as expected.
Now imagine that we mistakenly called Create for the second time after the property was set:
public DrugAgreement AssignPropertyOnNewlyCreatedObject(string newValue) {
    var obj = manager.Create();
    obj.TestingProperty = newValue;
    obj = manager.Create();
    return obj;
}

For the first look, the test above should fail, but it is not!
The test says that TestingProperty is equal to propertyValue, but the object is different. We called Create for the second time and expecting that manager is stateless and don't remember previously returned instance.
The answer is simple - our mock manager returns the same instance of object every time when Create is calling.

So, how to test this ?
How to make sure that Create method is stateless and always returns different objects?

Here is the corrected test:

[Test]
public void Value_should_be_assigned_on_property_value()
{
    ///Arrange
    ...
    DrugAgreement agreement = new DrugAgreement();

    agreementsManager.Setup(f => f.Create()).Returns(agreement).Callback(()=> agreement = new DrugAgreement());

    ///Action
    testingUnit.AssignPropertyOnNewlyCreatedObject("propertyValue");

    ///Assert
    Assert.AreEqual("propertyValue", agreement.TestingProperty);
}

If we test our code now it will fail as it should.
As you can see, the difference in the test is in calling Callback function by moq manager . That function instantiates new instance of DrugAgreement class after each call.

In this case our manager is really stateless and always return different instances

Thursday, January 20, 2011

WatiN UI testing of autocomplete textbox created with jquery.autocomplete

While writing UI tests for one web project, I were faced with the trouble.
There is a textbox on the page where user can type first letters and the system shows all possible values that can be selected by the user.
On the client side it was created with jquery.autocomplete:


I'm using WatiN library for writing UI tests and the regular approach, that I tried to use was not working.
Below is the code that emulates inserting of character 'a' then waits for autocomplete textbox appears and select first item:

IE _ie = new IE("URL-of-the-page-with-autocompleter");

//Typing letter 'a' and emulates keyboard
_ie.TextField("VendorName").TypeText("a");
_ie.TextField("VendorName").KeyDown();

//Wait while autocomplete making AJAX call
//and open the results
_ie.Div(f => !string.IsNullOrEmpty(f.ClassName) 
    && f.ClassName == "ac_results").WaitUntilExists(6);

//Selecting first item
_ie.Div(f => !string.IsNullOrEmpty(f.ClassName) 
    && f.ClassName == "ac_results")
    .ElementsWithTag("ul")
    .FirstOrDefault()
    .Click();

_ie.WaitForComplete();
The second line of code is important. KeyDown method for the textfield should be called to make autocompleter show search results.

Wednesday, December 1, 2010

How to write unit test for DateTime.Now

Yesterday I tried to use test driven development (TDD) to create logic for the application I'm working on.

One of requirements was to make the module to set the date when the object was modified.
The object has a property UpdatedOn and i needed to write a test that checks setting of DateTime.Now value for it.

The problem is, regular solution like the one below, will not work:


Assert.AreEqual(DateTime.Now, someObject.UpdatedOn);

The reason of why that example will always failed, is because the result of execution of DateTime.Now in Assert and DateTime.Now in business logic will be always different.
There will be few miliseconds between them and the test will always failed.

Here is what i used instead:


Assert.That(someObject.UpdatedOn, Is.EqualTo(DateTime.Now).Within(1).Seconds);