Being able to say that I have confidence in something I programmed is a great feeling. To build this confidence, I’m using unit testing. Unit testing is a method of verifying that individual pieces of code work as expected. I will not get into all the benefits of unit testing, I’ll just say why I am doing it: to check my work since no one else is doing so.
I began work on unit testing this afternoon. I installed NUnit and the Visual Studio extension to run unit tests directly:Then I added a new project to the solution called “Test”I started with the easy file to test. Vector2i is all integer math, the expected results should be easy to reason about. To test Vector2i I made a new file with the same name and added a suffix “Test” in the new project. I read up on a quickstart with NUnit and F# and I wrote some code:
module Morgemil.Test.Vector2iTest open Morgemil.Math open NUnit.Framework [<Test>] let ``Vector2i add zero Vector2i``() = let identity = Vector2i(5, 5) Assert.AreEqual(Vector2i() + identity, identity) Assert.AreEqual(identity + Vector2i(), identity) [<Test>] let ``Vector2i subtract zero Vector2i``() = let identity = Vector2i(5, 5) Assert.AreEqual(identity - Vector2i(), identity) Assert.AreNotEqual(Vector2i() - identity, identity) [<Test>] let ``Vector2i add zero scalar``() = let identity = Vector2i(5, 5) Assert.AreEqual(0 + identity, identity) Assert.AreEqual(identity + 0, identity) [<Test>] let ``Vector2i subtract zero scalar``() = let identity = Vector2i(5, 5) Assert.AreEqual(identity - 0, identity) Assert.AreNotEqual(0 - identity, identity) |
The .NET attribute [<Test>] comes from the NUnit.Framework namespace and is how the test runner finds these functions to run. I’ve named each function descriptively using “ as a way to create long names which is a pretty cool feature. So someday, if I ever break a functional piece of code I will get an informative message that test “Vector2i subtract zero scalar” failed. That will instantly give me the basic info instead of having to find the function and read documentation that may possibily not exist.
I’m reasonably sure that good unit tests only have one Assert per function so that if the function breaks, you know the exact Assert that failed. Now I have a reason why I’m not doing that: too many unit tests can make future changes prohibitive through sheer quantity of unit tests to change. Everything I’m doing right now is in flux so I don’t want to bury myself too deeply in things that might have to be rewritten later.
Visual Studio has this fantastic built-in tool to run tests. So as I add tests, I can just run them quickly and see what passed and what failed. With this, I am better equipped to continue developing functionality from the bottom-up.