Lesson Wednesday

In the next few lessons, we'll develop our to do list with the "Red, Green, Refactor" workflow. We'll also learn about a helpful way to organize tests called arrange, act, assert.

"Red, Green, Refactor" Workflow


Once again, we'll follow the "Red, Green, Refactor" workflow.

1. Identify the Simplest Behavior

What's the simplest possible behavior our program should exhibit? What should a to do list actually do and how will we create it programmatically?

At its most basic, our to do list only needs to record a list of items. Just as we had Car objects with a MakeModel property, we need to have Item objects with a Description property. This field will describe the user's tasks.

With this approach in mind, the simplest behavior our program can exhibit is to create an Item object regardless of its specific properties. Let's start with a test.

2. Write a Coded Test

Our test will confirm Item objects of the Item type can be created successfully.

ToDoList.Solution/ToDoList.Tests/ModelTests/ItemTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ToDoList.Models;

namespace ToDoList.Tests
{
  [TestClass]
  public class ItemTests
  {

    [TestMethod]
    public void ItemConstructor_CreatesInstanceOfItem_Item()
    {
      Item newItem = new Item();
      Assert.AreEqual(typeof(Item), newItem.GetType());
    }

  }
}

We call our test method ItemConstructor_CreatesInstanceOfItem_Item.

  • ItemConstructor is the method we're testing.
  • CreatesInstanceOfItem describes the behavior we want our method to have.
  • Item is the expected return value of the method we're testing.

We're also using two new built-in methods here:

  • typeof returns the data type of a class.
  • GetType() returns the data type of a specific object.

In other words, we simply want to confirm that the newItem object we create is of the Item data type.

Let's run $ dotnet test:

Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 0.8208 Seconds

Our test passes because we already have an Item class declared in ToDoList/Models/Item.cs. Let's go ahead and move on to our next test.

1. Identify the Simplest Behavior

Now that our program successfully creates empty Items, let's ensure these Items can hold a basic description like "wash the car" or "do the dishes". The test will be failing until next lesson, since we won't define a property for the class until after we've written our desired behavior.

2. Write a Coded Test

We'll add another test for this behavior:

ToDoList.Solution/ToDoList.Tests/ModelTests/ItemTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ToDoList.Models;

namespace ToDoList.Tests
{
  [TestClass]
  public class ItemTests
  {

    [TestMethod]
    public void ItemConstructor_CreatesInstanceOfItem_Item()
    {
      Item newItem = new Item();
      Assert.AreEqual(typeof(Item), newItem.GetType());
    }

    [TestMethod]
    public void GetDescription_ReturnsDescription_String()
    {
      string description = "Walk the dog.";
      Item newItem = new Item(description);
      string result = newItem.Description;
      Assert.AreEqual(description, result);
    }

  }
}

We've created a new test method called GetDescription_ReturnsDescription_String. Getting the value of a property on an Item may seem trivial. However, in order to get this test to pass, we need to create an auto-implemented property in the Item class. It makes sense to test our property and getter method so we know it's working properly, especially if we utilize custom get logic.

Within the test method we do the following:

  1. Create a new string called description.

  2. Create a new Item object, passing in the description.

  3. Record the result of retrieving the Description property of newItem.

  4. Confirm the description retrieved from the Item object matches the description string provided to the constructor.

Arrange, Act, Assert

This test is more complex than our previous tests. Thankfully, there's an easy organizational trick that helps demystify this process and keep our tests clean. It's called "Arrange, Act, Assert". With this organizational method, we break our tests down into three stages:

  1. Arrange: We gather, declare and create all necessary components for the test. In the test above, we create description and newItem.

  2. Act: We invoke the functionality we're testing, often by calling a method or retrieving a property. In the test above, we call newItem.Description;.

  3. Assert: We confirm the functionality works as anticipated by comparing its actual output with the anticipated output. This is when we call Assert.AreEqual().

Let's take one more look at our test. This time, we add comments to show how we use "Arrange, Act, Assert."

ToDoList.Solution/ToDoList.Tests/ModelTests/ItemTests.cs
...

[TestMethod]
public void GetDescription_ReturnsDescription_String()
{
  //Arrange
  string description = "Walk the dog.";
  Item newItem = new Item(description);

  //Act
  string result = newItem.Description;

  //Assert
  Assert.AreEqual(description, result);
}

...

We recommend following this same organizational process in your own tests throughout the course.

In the next lesson, we'll continue using the "Red, Green, Refactor" workflow to create our To Do List.

Lesson 14 of 20
Last updated April 14, 2022