MGunit is a unit testing framework modeled on other unit testing frameworks such as JUnit. The goal is to allow easy creation and reporting of results of tests, but still allow for all needed flexibility. More details and examples after the jump.

The structure of tests created for this framework is straightforward. Individual tests are methods of an class that subclasses MGtestCase. Each method returns 1 for success or 0 for failure (or throws an error). Each test method’s name must start with “test”. Test cases may be (but are not required to be) grouped into test suites.

The examples (FINDGENTEST, INDGENTEST, and INDGENSUITE) of MGunit discussed are available for download.

To create a test, subclass MGtestCase like:

pro findgentest__define
  define = { findgentest, inherits MGtestCase }
end

A test is just a method whose name starts with “test”. MGunit will find the tests automatically (make sure they are either already compiled or above FINDGENTEST__DEFINE in the same file). A test case may have as many tests as necessary. For example, a simple test:

function findgentest::test2
  a = findgen(5)
  assert, array_equal(a, [0.0, 1.0, 2.0, 3.0, 4.0]), 'Correct elements'

  return, 1
end

Return 1 for success. For failure, either return 0 or throw an error. Here the helper routine ASSERT will throw an error using the given message if its condition is not met. This will be reported as a failure along with the message. To run this test, use:

IDL> mgunit, 'findgentest'

Results can be sent to a log file with the LOG_FILE:

IDL> mgunit, 'findgentest', log_file='results.log'

This should produce the output:

Starting test suite MGTESTSUITE (1 test case, 4 tests)
   Starting FINDGENTEST (4 tests)
      TEST1: failed "Wrong number of elements"
      TEST2: passed
      TEST3: passed
      TEST4: failed "Type conversion error: Unable to convert..."
      Results: 2 / 4 tests passed
   Results: 2 / 4 tests passed

One tricky situation is that sometimes invalid input must be tested to make sure the routine fails. In this case, throwing an error should indicate a success of the test, not a failure. In this case use the provided batch file error_is_pass at the beginning of the routine, like:

function findgentest::test3
  @error_is_pass

  a = findgen('string')

  return, 1
end

Multiple test cases can be specified as an array

IDL> mgunit, ['findgentest', 'indgentest']

or by creating a test suite. Test suites are very simple; they are just collections of test cases. To make a suite, subclass MGtestSuite and use the add method to add test classes. For example,

function indgensuite::init, _extra=e
  compile_opt strictarr

  if (~self->mgtestsuite::init(_extra=e)) then return, 0

  self->add, ['indgentest', 'findgentest']

  return, 1
end

pro indgensuite__define
  define = { indgensuite, inherits MGtestSuite }
end

This test suite is available for download (source / docs). MGUNIT can run test suites also,

IDL> mgunit, 'indgensuite'

MGUNIT will also accept a mixed array of test suites and test cases.