Zebra Game Kata Part 4 - Doors

The second part of the first statement in the Zebra Problem says, "each [house] with a front door of a different colour".

Let's write a test for that.

But how? When I get stuck, I use a whiteboard.

House
Id DoorColor
1 Yellow
2 Green
3 Yellow

So, it looks like our houses need an ID as a way to identify them. Next, they need a DoorColor property.

Let's select the house ID of the homes with the same DoorColor using LINQ.

ZebraGameTest/ZebraProblemTest.cs
private ZebraProblem zebraProblem;

[SetUp]
public void Setup()
{
    zebraProblem = new ZebraProblem();
}

[Test]
public void Unique_Front_Doors()
{
    zebraProblem.Houses.ForEach( house =>
        Assert.That( 
            zebraProblem.Houses.Count( h => h.DoorColor == house.DoorColor ),
            Is.EqualTo( 1 ),
            "A house was found with the same color door as house {0}.",
            house.Id ) );
}

Since both tests need an instance of ZebraProblem, I made it a private property and instantiated it in a SetUp method.

LINQ is a great query language to use get information from a collection. Let's talk about the LINQ statement.

For each house in the Zebra Problem, grab a house and assert that all the other houses in the Zebra Problem don't have the same color door.

If you find a house with the same color, stop, and write out a helpful message with the ID.

We can't compile because our House object does not have an Id or a DoorColor property. Let's add them.

ZebraGameProblem/House.cs
namespace ZebraGameProblem
{
    public class House
    {
        public int Id { get; set; }

        public DoorColor DoorColor { get; set; }
    }
}

You could make DoorColor a string, but then you have to deal with "Gray" vs. "Grey". It would be better if it was an enumeration.

ZebraGameProblem/DoorColor.cs
namespace ZebraGameProblem
{
    public enum DoorColor
    {
    }
}

We can compile, let's run the test.

1 test failed "A house was found with the same color door as house 0. Expected: 1 But was: 5"

There's a house with the same color door as house 0. We only expected 1 house to have the door color, but there was 5.

As soon as the test encounters a house door color count of more than 1, it stops. We have not assigned ID's to the homes yet, so the first house is ID 0. We have not given the homes a door color yet, so all 5 have the same color.

Let's read ahead in the problem and identify all the possible door colors. Then we can add them to our enumeration.

ZebraGameProblem/DoorColor.cs
namespace ZebraGameProblem
{
    public enum DoorColor
    {
        Blue,
        Green,
        Ivory,
        Red,
        Yellow
    }
}

To get the test to pass we need to assign each house a unique door color.

ZebraGameProblem/ZebraProblem.cs
using System.Collections.Generic;

namespace ZebraGameProblem
{
    public class ZebraProblem
    {
        public ZebraProblem()
        {
            const int houseMax = 5;

            Houses = new List<House>( houseMax )
             {
                 new House
                     {
                         DoorColor = DoorColor.Blue
                     },
                 new House
                     {
                         DoorColor = DoorColor.Green
                     },
                 new House
                     {
                         DoorColor = DoorColor.Ivory
                     },
                 new House
                     {
                         DoorColor = DoorColor.Red
                     },
                 new House
                     {
                         DoorColor = DoorColor.Yellow
                     }
             };
        }

        public List<House> Houses { get; }
    }
}

Let's run the tests again.

2 tests passed

All of the homes have an ID of 0. Let's write a test and fix this.

ZebraGameTest/ZebraProblemTest.cs
[Test]
public void Unique_House_Id()
{
    zebraProblem.Houses.ForEach(
        house => Assert.That( zebraProblem.Houses.Count( h => h.Id == house.Id ),
            Is.EqualTo( 1 ),
            "A house was found with the same ID as house {0}.",
            house.Id ) );
}

Let's run the test.

1 test failed "A house was found with the same ID as house 0. Expected: 1 But was: 5"

Now we assign each house a unique ID.

ZebraGameProblem/ZebraProblem.cs
public ZebraProblem()
{
    const int houseMax = 5;

    Houses = new List<House>( houseMax )
     {
         new House
             {
                 Id = 1,
                 DoorColor = DoorColor.Blue
             },
         new House
             {
                 Id = 2,
                 DoorColor = DoorColor.Green
             },
         new House
             {
                 Id = 3,
                 DoorColor = DoorColor.Ivory
             },
         new House
             {
                 Id = 4,
                 DoorColor = DoorColor.Red
             },
         new House
             {
                 Id = 5,
                 DoorColor = DoorColor.Yellow
             }
     };
}

Let's run the tests.

3 tests passed