In my last post on Nim, I discussed modules a bit. This time around, I want to figure out the answer to “How do I test in Nim?”
First, very little comes up in basic searches. Mostly you get reference to using the when
statement (compile-time if) along with assert
and company, but that is fairly primitive.
Doing some more digging, I found that a unittest library does actually exist in the standard libs, but it is not linked to from anywhere becase it requires better documentation. If you do a search on the Nimrod repository, though, you can find that there are some examples of the libraries use! However, there’s probably a reason for it not being listed in the documentation besides a lack of documentation for itself.
So, another way to do tests, if you look at the Nim compiler source itself, is to just create a directory with individual modules that contain nothing but code for performing tests.
I decided to use a small vector math library for motivation to explore the testing facilities (that are not unittest), and to see how I might incorporate testing into a larger project.
Here’s just a small part of the library that covers only a convenient way to initialize a TVec3
value:
type
TVec3* = array[0..2, int]
proc init*(vec: var TVec3; x, y, z: int) =
vec[0] = x
vec[1] = y
vec[2] = z
And here’s my testing code:
import vectors
var vec: TVec3
vec.init 1, 2, 3
assert(vec[0] == 1)
assert(vec[1] == 2)
assert(vec[2] == 3)
echo "OK"
Simple: create a TVec3
, initialize it, assert values are what are expected, then give the “OK” if all the asserts pass.
The key to this approach is in the command used to build and execute the tests, since I use a make file, this test (and every other test) are, are in a test
target that executes commands similar to:
This command does several things:
- sets
--verbosity
to0
so that a bunch of mostly unimportant info isn’t printed to stdout - adds the
src
directory to thepath
that Nim uses to search for modules - sets the
-o
output file to a generic exe name - specifies the test to build (
tests/tvectors.nim
in this case) - and after a successful build, runs the tests with
&& ./bin/tests
With my above tvectors.nim
tests, I get a simple OK
printed to the console after each test is built and run. Otherwise I either get a compilation error message, or something more akin to:
Traceback (most recent call last)
tvectors.nim(6) tvectors
system.nim(2908) failedAssertImpl
system.nim(2136) raiseAssert
Error: unhandled exception: vec[0] == 2 [EAssertionFailed]
Which is what gets displayed when an assertion fails.
Next time I talk about Nim, I tentitively plan on building out this vector library a little more and seeing how the tests scale. But I think a more pressing need might be the ability to specify the TVec3
type more generically so that I don’t have to re-declare types for integers, floats, etc.
Until next time!