F# and Unit Testing

Consider this code snippet in F#

  1. module Board =
  2.     let tiles = [|0 .. 39|]
  3.     let random = System.Random()
  4.  
  5.     let communityChest x =
  6.         let communityChestDraw = random.Next(1,17)
  7.         if communityChestDraw = 1 then
  8.             0
  9.         else if communityChestDraw = 2 then
  10.             10
  11.          else
  12.             x

 

I then went to create a unit test for the communityChest function when it hit me that I will get unpredictable behavior because I am getting a random number within the method body.  I made this same mistake when I created my windows phone 7 game where there combat engine was using a Random.Next() result.

Basically, I am repeating my mistakes across two languages.  The good news is that the solution is the same for both languages: I need to inject the result from Random.Next() into community chest.

  1. let communityChest x y =
  2.     if y = 1 then
  3.         0
  4.     else if y = 2 then
  5.         10
  6.      else
  7.         x

 

And then

  1. let move x y =
  2.     let communityChestDraw = random.Next(1,17)
  3.  
  4.     if x + y > 39 then
  5.         x + y – 40
  6.     else if x + y = 30 then
  7.         10
  8.     else if x + y = 2 then
  9.         communityChest 2 communityChestDraw
  10.     else if x + y = 7 then
  11.         chance 7
  12.     else if x + y = 17 then
  13.         communityChest 2 communityChestDraw
  14.     else if x + y = 22 then
  15.         chance 22
  16.     else if x + y = 33 then
  17.         communityChest 2 communityChestDraw
  18.     else if x + y = 36 then
  19.         chance 36
  20.     else
  21.         x + y

 

The other nice thing is I found the bug that was, well, bugging me.  The reason that 2 showed up the most was that I had copied and pasted 2 to be the results of all community chest runs.  I then changed the code to reflect the actual position of community chest:

  1. let move x y =
  2.     let communityChestDraw = random.Next(1,17)
  3.  
  4.     if x + y > 39 then
  5.         x + y – 40
  6.     else if x + y = 30 then
  7.         10
  8.     else if x + y = 2 then
  9.         communityChest 2 communityChestDraw
  10.     else if x + y = 7 then
  11.         chance 7
  12.     else if x + y = 17 then
  13.         communityChest 17 communityChestDraw
  14.     else if x + y = 22 then
  15.         chance 22
  16.     else if x + y = 33 then
  17.         communityChest 33 communityChestDraw
  18.     else if x + y = 36 then
  19.         chance 36
  20.     else
  21.         x + y

 

So now I can do my unit tests:

  1. [TestClass]
  2. public class SimulatorTests
  3. {
  4.     [TestMethod]
  5.     public void communityChestWithOne_ReturnsZero()
  6.     {
  7.         var result = Simulator.communityChest(2, 1);
  8.         Assert.AreEqual(0, result);
  9.     }
  10.  
  11.     [TestMethod]
  12.     public void communityChestWithTwo_ReturnsTen()
  13.     {
  14.         var result = Simulator.communityChest(2, 2);
  15.         Assert.AreEqual(10, result);
  16.     }
  17.  
  18.     [TestMethod]
  19.     public void communityChestWithThree_ReturnsTwo()
  20.     {
  21.         var result = Simulator.communityChest(2, 3);
  22.         Assert.AreEqual(2, result);
  23.     }
  24. }

 

And the tests run green:

image

I love being able to write C# tests and test F# code…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: