Appendix A. Complete examples

This appendix gathers all examples that are either too long for the main text or are referenced (but not defined in) the main text.

A.1. Unit-test

A.1.1. unit_init.m

function unit_init(verbosity, global_vars)
    ## Initialize the global structure unittest_results, which is needed
    ## in all functions of the *unittest module.  Debugging information
    ## is printed if verbosity==1.  global_vars is a cell array of the
    ## names of the global variables used in the tests.
    ##
    ## e.g. unit_init(1, {"g", "a", "x"})
                                                                                                                            
    global unittest_results;
                                                                                                                            
    unittest_results.verbose = 0;
    unittest_results.eval_globals = {};
    if (nargin > 0)
        if (!isscalar(verbosity) || verbosity < 0 || verbosity > 1)
            warning("unit_init: verbose must be 0 or 1");
        else
            unittest_results.verbose = verbosity;
        endif
                                                                                                                            
        if (nargin == 2 && iscell(global_vars))
            for i = 1:length(global_vars)
                unittest_results.eval_globals{i} = strcat("global ", global_vars{i}, ";");
            endfor
        else
            error("global_vars must be a cell array");
        endif
                                                                                                                            
        if (nargin > 2)
            usage("expecting 2 arguments only");
        end
    endif
                                                                                                                            
    unittest_results.total = 0; # number of testcases attempted
    unittest_results.pass = 0;  # number of expected passed
    unittest_results.fail = 0;  # number of unexpected failures
    unittest_results.upass = 0; # number of unexpected passes
    unittest_results.xfail = 0; # number of expected failures
    unittest_results.unresolved = 0; # number of unresolved testcases
                                                                                                                            
    default_eval_print_flag = 0;
endfunction

A.1.2. unit_test.m

function result = unit_test(test_title, expect_pass, actual_result)
     ## Function unittest compares the ACTUAL_RESULT of running
     ## a test (either  0 for failure, or 1 for success) with the
     ## expected outcome of the test EXPECT_PASS (either 0 for expecting
     ## a failure, or 1 for expecting pass).  TEST_TITLE is the name of
     ## the test.  All test results will be accompanied by the test's
     ## title.
     ##
     ## The result of unittest is on of the following: UNRESOLVED: The
     ## test did neither return 0 nor 1.  PASS: expected pass, got pass.
     ## FAIL: expected pass, got fail.  UPASS: expected fail, got pass.
     ## XFAIL: expected fail, got fail.
     ##
     ## A call to unittest typically looks like this:
     ##
     ## unittest("scalar integer addition", 1, eval("1 + 1 == 2;"));
                                                                                                                            
     global unittest_results;
                                                                                                                            
     ## Sanity check input parameters
     if ( nargin < 3 | nargin > 4 )
         error("Function run_rest expects 3 or 4 parameters.");
     endif
                                                                                                                            
     if (!isstr(test_title))
         error("Expecting TEST_TITLE (arg 1) to be a string.");
     endif
                                                                                                                            
     if (expect_pass != 0 & expect_pass != 1)
         error("Expecting EXPECT_PASS (arg 2) to be 0 or 1.");
     endif
                                                                                                                            
     unittest_results.total++;

     ## Take actions depending on what test result we expect
     ## (expect_pass), and what we actually got (actual_result).
     if (actual_result != 0 & actual_result != 1)
         result = "UNRESOLVED";
         unittest_results.unresolved++;
         if (actual_result == 2)
             printf("SYNTAX ERROR: %s\n", test_title);
         endif
         return;
     endif
                                                                                                                            
     if (expect_pass == 1 & actual_result == 1)
         result = "PASS";
         if (unittest_results.verbose != 0)
             printf("PASS: %s\n", test_title);
         else
             printf('.');
         endif
         unittest_results.pass++;
     elseif (expect_pass == 1 & actual_result == 0)
         result = "FAIL";
         printf("FAIL: %s\n\n", test_title);
         unittest_results.fail++;
     elseif (expect_pass == 0 & actual_result == 0)
         result = "XFAIL";
         printf("XFAIL: %s\n", test_title);
         unittest_results.xfail++;
     elseif (expect_pass == 0 & actual_result == 1)
         result = "UPASS";
         printf("UPASS: %s\n", test_title);
         unittest_results.upass++;
     endif
 endfunction

A.1.3. unit_test_equals.m

function unit_test_equals(test_title, result_A, result_B)
                                                                                                                            
    unit_test(test_title, 1, all(all(result_A == result_B)));
                                                                                                                            
endfunction

A.1.4. unit_test_err.m

function unit_test_err(test_title, expected_error_prefix, evaluated_string)
                                                                                                                            
    unit_test(test_title, 1, erreval(expected_error_prefix, evaluated_string));
                                                                                                                            
endfunction

A.1.5. errcheck.m

function e = errcheck(error_prefix)
                                                                                                                            
    e = 1;
    if (index(__error_text__, error_prefix) != 1)
        e = 0;
        printf("\nUNEXPECTED ERROR: %s", __error_text__);
    endif
                                                                                                                            
end

A.1.6. erreval.m

function rv = erreval(error_prefix, try_str, catch_str)
    ## erreval() extends the built-in function eval().  Return 0 if
    ## try_str does not raise the error of type error_prefix, return 1
    ## otherwise.
                                                                                                                            
    global unittest_results;
    for k = 1:length(unittest_results.eval_globals)
        eval(unittest_results.eval_globals{k});
    end
                                                                                                                            
    rv = 0;
    try
        eval(try_str);
    catch
        rv = errcheck(error_prefix);
    end
                                                                                                                            
endfunction

A.1.7. unit_results.m

function unit_results()
     ## Print the results from previous unittest calls in pretty format.
                                                                                                                            
     global unittest_results;
                                                                                                                            
     printf("\n");
     printf("# of testcases attempted   %d\n", unittest_results.total);
     printf("# of expected passes       %d\n", unittest_results.pass);
     printf("# of expected failures     %d\n", unittest_results.xfail);
     printf("# of unexpected passes     %d\n", unittest_results.upass);
     printf("# of unexpected failures   %d\n", unittest_results.fail);
     printf("# of unresolved testcases  %d\n", unittest_results.unresolved);
     printf("\n");
                                                                                                                            
     if (unittest_results.total == unittest_results.pass + unittest_results.xfail)
         printf("Unit testing completed successfully!\n");
     else
         printf("One or more tests failed!\n");
     endif
 endfunction