Simple example of how to write unit tests in Matlab
A unit test is a little program that checks if some part (or unit) of your code works as expected. What arguments are there for bothering to write such tests?
- They make it less likely that bugs go unnoticed.
- It’s reassuring to first run your tests when you haven’t touched your codes for a while to check if things still work.
- After changing something in the code, it’s good to see if anything’s broken.
- Writing test also nudges you to keep functions small, as it’s more difficult to test functions when they have many input argument.
I didn’t find the existing examples of how to use it easy to follow, so I’m putting here an explanation of how to test one individual function.
You can find all codes here.
Say we have a function
add_one.m we want to test:
For our unit test, we then write an additional script which we have to name with either
test_ at the beginning or
_test at the end. So here’s the new script
The first three lines are always required and we only need to change the function name to match the name of the file.
The following function
test_normal1 is our first test case. We will pass in the value
x = 1 and check that the result is indeed 2.
So now go to the Matlab command line and run:
There’ll be a dot for every test case for this function. In this case everything worked fine, but there would be an extensive message if an error had occured.
So let’s add some more tests:
It’s a good idea to give the functions meaningful names so that when there’s an error, we know where things went wrong. Don’t worry if the names get really long, they’ll only live in this script anyway.
The tricky thing is to think of the irregular ways the function might be used. For example, the following tests check that we get the right output even if we pass in an empty matrix or an
Now let’s give the function something where would expect an error. If we pass the function a string
'Hello world' it returns a numerical vector. That’s not what we want, so let’s add
add_one.m function. So now it fails if the input is not a number.
The following test case then checks if indeed an error is returned:
I use try-catch here to check if the function returns an error. There might be better ways to do this, but this works for me.
But we don’t always just have to check that results are equal, as sometimes we want to make sure that the difference is below some numerical threshold. In this case, calculate the absolute or relative error as
actDiff and check that it’s less than some acceptable error like this:
One thing I lack so far is a way to test local functions, so functions that you define within some other function and which only that function can use.
So that’s it. If somebody has ideas for improvements, please let me know!