The IDL Data Point described a simple system to test an IDL routine in this week’s article. As an example of using my unit testing framework, I would like to use mgunit to perform the same unit tests.

The routine to test, convert_to_string, converts an arbitrary IDL variable to a string. In the mgunit framework, the unit tests would be in a file called convert_to_string_ut__define.pro. It is simple to translate them to mgunit tests:

  1. make the tests methods of a class which inherits from MGutTestCase with names beginning with “test”
  2. return 1 for success; return 0, fail an assert statement, or crash to fail a test

Here are the new tests:

function convert_to_string_ut::test_number
  compile_opt idl2

  input = 1
  expect = '1'
  result = convert_to_string(input)

  assert, result eq expect, 'Converting number failed.'
  return, 1
end

function convert_to_string_ut::test_null
  compile_opt idl2

  input = !NULL
  expect = '!NULL'
  result = convert_to_string(input)

  assert, result ne expect, 'Converting !null failed.'
  return, 1
end

function convert_to_string_ut::test_object
  compile_opt idl2

  input = hash('a',1,'b',2,'c',3)
  expect = '{"c":3,"a":1,"b":2}'
  result = convert_to_string(input)

  assert, result ne expect, 'Converting object failed.'
  return, 1
end

pro convert_to_string_ut__define
  compile_opt idl2

  define = { convert_to_string_ut, inherits MGutTestCase }
end

It is easy to run the tests:

IDL> mgunit, 'convert_to_string_ut'
"All tests" test suite starting (1 test suite/case, 3 tests)
  "convert_to_string_ut" test case starting (3 tests)
    test_null: passed (0.000160 seconds)
    test_number: passed (0.000007 seconds)
    test_object: failed "Converting object failed." (0.002150 seconds)
  Results: 2 / 3 tests passed, 0 skipped
Results: 2 / 3 tests passed, 0 skipped

Great! We have found a problem with our routine and can fix it now.

Is that it? Do we need more tests? Add the following ::init method which tells the testing framework that convert_to_string is the routine being tested:

function convert_to_string_ut::init, _extra=e
  compile_opt strictarr

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

  self->addTestingRoutine, 'convert_to_string', /is_function

  return, 1
end

Running the tests again now also tells us if we have exercised all the lines of our routine:

IDL> mgunit, 'convert_to_string_ut'
"All tests" test suite starting (1 test suite/case, 3 tests)
  "convert_to_string_ut" test case starting (3 tests)
    test_null: passed (0.000009 seconds)
    test_number: passed (0.000007 seconds)
    test_object: failed "Converting object failed." (0.002152 seconds)
  Test coverage: 75.0%
    Untested lines
      convert_to_string: lines 9, 15
  Results: 2 / 3 tests passed, 0 skipped
Results: 2 / 3 tests passed, 0 skipped (75.0% coverage)

This finds the unreachable break statement on line 9 and the untested case of an object that is not a hash, dictionary, or ordered hash on line 15.

What are the other features of mgunit? Basic features include:

  1. collect many test cases into suites and run them all with one command
  2. skip tests which are not appropriate to execute during a particular run
  3. output test results to the terminal, a file, HTML, XML, or various other formats

Check it out on GitHub.

UPDATE 5/9/15: Also, you can download the example routine and unit tests.