fredag 27 augusti 2010

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, there it 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 at will by EUnit. More or less you can put yourself in EUnit's shoes (cool) and the user gives you a "black box", which you simply execute. No need to care about other stuff. Just execute it.
nullarySTO1() -> fun() -> ?assertEqual(6,mylist:sum([1,2,3])) end. 
nullarySTO2() -> fun nullarySTO1/0 
nullarySTO3() -> fun mylists_tests:nullarySTO1/0


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. Remember that all erlang functions are uniquely determined by M,F,Arity.
tupleSTO1() -> { mylist_tests, nullarySTO1 }
tupleSTO2() -> { mylist_tests, nullarySTO2 }
tupleSTO3() -> { mylist_tests, nullarySTO3 } 


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.


tupleSTO4() -> ?_test( fun() -> ?assertEqual(6,mylist:sum([1,2,3])) end )
tupleSTO5() -> ?_test( begin ?assertEqual(6,mylist:sum([1,2,3])) end )
tupleSTO6() -> ?_test( nullarySTO2() ) 


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. So, any of these are Test Sets

nullarySTO1() 
[ tupleSTO4() ] 
[ [ nullarySTO1() , nullarySTO2() ] , [ tupleSTO1(), tupleSTO2() ] ]


Also, a Test Generator is a function that ends with _test_() and returns a TestSet. End of story. Like this


my_generator1_test_() ->  nullarySTO1().
my_generator2_test_() -> [ nullarySTO1(), tupleSTO4() ]


What we have seen are all valid erlang EUnit STO statements. To prove it, I shall place it in a gran EUnit file, compile and run. Below follows the example STO mylists_tests.erl module, with compilation and running as usual.


Simple Test Object Example File
-module(mylist_tests).
-include_lib("eunit/include/eunit.hrl").
-compile(export_all).
nullarySTO1() -> fun() -> ?assertEqual(6,mylist:sum([1,2,3])) end. 
nullarySTO2() -> fun nullarySTO1/0.
nullarySTO3() -> fun mylist_tests:nullarySTO1/0.
tupleSTO1() -> { mylist_tests, nullarySTO1 }.
tupleSTO2() -> { mylist_tests, nullarySTO2 }.
tupleSTO3() -> { mylist_tests, nullarySTO3 }.
tupleSTO4() -> ?_test( fun() -> ?assertEqual(6,mylist:sum([1,2,3])) end ).
tupleSTO5() -> ?_test( begin ?assertEqual(6,mylist:sum([1,2,3])) end ).
tupleSTO6() -> ?_test( nullarySTO2() ).
tupleSTO7() -> { 16, nullarySTO3() }.
generator_test_() ->    
    [
     nullarySTO1(),
     nullarySTO2(),
     nullarySTO3(),
     tupleSTO1(),
     tupleSTO2(),
     tupleSTO3(),
     tupleSTO4(),
     tupleSTO5(),
     tupleSTO6(),
     tupleSTO7()
    ].
That is the end of the module, next is the compilation and running.

zen:EunitBasic3 zenon$ erlc -o ebin/ src/*.erl test/*.erl
zen:EunitBasic3 zenon$ erl -pa ebin/
Erlang R13B04 (erts-5.7.5) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.5  (abort with ^G)
1> eunit:test(mylist,[verbose]).
======================== EUnit ========================
module 'mylist'
  module 'mylist_tests'
    mylist_tests: nullarySTO1...ok
    mylist_tests: nullarySTO2...ok
    mylist_tests: nullarySTO1...ok
    mylist_tests: nullarySTO1...ok
    mylist_tests: nullarySTO2...ok
    mylist_tests: nullarySTO3...ok
    mylist_tests:13: tupleSTO4...ok
    mylist_tests:14: tupleSTO5...ok
    mylist_tests:15: tupleSTO6...ok
    mylist_tests:16: nullarySTO1...ok
    [done in 0.030 s]
  [done in 0.030 s]
=======================================================
  All 10 tests passed.
ok
2> 

Great! Now, as we know how to write, set up and clean STO's and TestSets. The next lesson is on Test Control!

Inga kommentarer:

Skicka en kommentar