Erlang EUnit – continuation 2 – Test Representation

Having passed through basics and some setup / teardown, it’s time to discuss test representation, a very broad subject which invites for misconceptions.

Basics of Representation

As always, the foundation for the discussion is the EUnit manual pages, where it is stated that a test can be defined in many different ways, and to keep the discussion very short, I shall supply some common examples of what is often seen/used.

Simple Test Objects

Each representation form will be shown with examples based on the mylist module defined in the first post. So, each Simple Test Object (STO) can be defined by

Any nullary function (function with zero arguments)

What this implies is that your STO is encapsulated within a functional object and may be executed by EUnit. More or less you can put yourself in EUnit’s shoes (some very special shoes) and the user gives you a “black box”, which you simply execute. No need to care about other stuff. Just execute it. Examples of STO’s

A Module Function Tuple

This is just a different way of reaching the nullary function by the module and function name. Here it is implicit that the functionname is a nullary function. This will not work with {mylist_tests, nullarySTO2 } which will be seen below. Why? Because nullarySTO2() RETURNS a nullary functional object.

tupleSTO1() -> { mylist_tests, nullarySTO1 }.

A Linenumber / STO Tuple (generated by _test(Expr) macro)

According do our best friend, (the user’s guide) “LineNumber is a nonnegative integer …. LineNumber should indicate the source line of the test”. Wow, so it’s the linenumber in the sourcecode for where the tests is. For some reason, this can be written by hand, but luckily the _test(Expr) macro does it for us.

Test Sets and Test Generator Basics

One last thing on the basics of representation is that EUnit does not make any “type”-difference between a deep list of STO’s and single STO, that is.

TestSet := [ TestSet ] | STO

So, a Test-Set can be a so called deep list of Test-Sets, to any level, or just a single STO. Also, a Test Generator is a function that ends with _test_() and returns a TestSet. End of story. Like this

What we have seen is all valid erlang EUnit. To prove it, let us place it in a grand EUnit file, compile and run. Below follows the example mylists_tests.erl module, with compilation and running as usual.

3 Comments

Try changing tupleSTO4/0 so that it should fail. For example:
tupleSTO4() -> ?_test( fun() -> ?assertEqual(1,2) end ).

Run the tests and you’ll notice that it still passes!

?_test returns its argument wrapped in a fun. So when you give it a fun to start with you get a fun that returns a fun, which is the same thing as a test object that can never fail.

Now break nullarySTO1 in the same way so that it fails and you’ll see that the other tests that should call it – nullarySTO2, nullarySTO3, tupleSTO1, tupleSTO2, tupleSTO3, tupleSTO6 and tupleSTO7 – all still pass. It is pretty much the same problem here; a test generator can return one or more funs, but you return funs that return funs, and that is one level too deep.