UnitTest

Usage

use UnitTest;

or

import UnitTest;

The UnitTest module provides support for automated testing in Chapel.

The UnitTest module is intended to be used with the mason test command, which automates execution of any test function.

A unit test function is defined as any function with the following signature:

proc funcName(test: borrowed Test) throws {}

These functions must accept an argument of type borrowed Test, and have a throws.

A program containing tests must execute the UnitTest main() function to run the tests.

Assert Functions

Here are the assert functions available in the UnitTest module:

Test Metadata Functions

UnitTest module also provides multiple methods for specifying test Metadata:

Examples

Basic Usage

Here is a minimal example demonstrating how to use the UnitTest module:

use UnitTest;

proc celsius2fahrenheit(x) {
  // we should be returning "(x: real * 9/5)+32"
  return (x * 9/5)+32;
}

proc test_temperature(test: borrowed Test) throws {
  // we were expecting 98.6 but since we missed typecasting
  // the above function returned 98.
  test.assertFalse(celsius2fahrenheit(37) == 98);
}

UnitTest.main();

Output:

======================================================================
FAIL xyz.chpl: test_temperature()
----------------------------------------------------------------------
AssertionError: assertFalse failed. Given expression is True

----------------------------------------------------------------------
Run 1 test

FAILED failures = 1

Skipping Tests

You can skip tests unconditionally with skip and conditionally with skipIf:

use UnitTest;

/* calculates factorial */
proc factorial(x: int): int {
  return if x == 0 then 1 else x * factorial(x-1);
}

/*Conditional skip*/
proc test1(test: borrowed Test) throws {
  test.skipIf(factorial(0) != 1,"Base condition is wrong in factorial");
  test.assertTrue(factorial(5) == 120);
}

/*Unconditional skip*/
proc test2(test: borrowed Test) throws {
  test.skip("Skipping the test directly");
}

UnitTest.main();

Output:

======================================================================
SKIPPED xyz.chpl: test2()
----------------------------------------------------------------------
TestSkipped: Skipping the test directly

----------------------------------------------------------------------
Run 1 test

OK skipped = 1

Specifying locales

You can specify the num of locales of a test using these method.

addNumLocales maxLocales minLocales

Here is an example demonstrating how to use the addNumLocales

proc test_square(test: borrowed Test) throws {
  test.addNumLocales(5);
  var A: [Locales.domain] int;
  coforall i in 0..numLocales-1 with (ref A) {
    on Locales(i) {
      A[i+1] = (i+1)*(i+1);
    }
  }
  test.assertTrue(A[5]==25);
}

Output:

----------------------------------------------------------------------
Run 1 test

OK

You can also specify multiple locales on which your code can run.

proc test3(test: borrowed Test) throws {
  test.addNumLocales(16,8);
}

You can mention the range of locales using maxLocales and minLocales

proc test4(test: borrowed Test) throws {
  test.maxLocales(4);
  test.minLocales(2);
}

Specifying Dependencies

You can specify the order in which tests should run using dependsOn:

use UnitTest;

var factorials: list(int);

// calculates factorial
proc factorial(x: int): int {
  return if x == 0 then 1 else x * factorial(x-1);
}

proc testFillFact(test: borrowed Test) throws {
  test.skipIf(factorial(0) != 1,"Base condition is wrong in factorial");
  for i in 1..10 do
    factorials.append(factorial(i));
}

proc testSumFact(test: borrowed Test) throws {
  test.dependsOn(testFillFact);
  var s = 0;
  for i in factorials.indices do
    s += factorials[i];
  test.assertGreaterThan(s,0);
}

UnitTest.main();

Output:

----------------------------------------------------------------------
Run 2 tests

OK
class Test
proc skip(reason: string = "") throws

Unconditionally skip a test.

Arguments:reason – the reason for skipping
Throws:TestSkipped – Always
proc skipIf(condition: bool, reason: string = "") throws

Skip a test if the condition is true.

Arguments:
  • condition – the boolean condition
  • reason – the reason for skipping
Throws:

TestSkipped – If the condition is true.

proc assertTrue(test: bool) throws

Assert that test is true.

Arguments:test – the boolean condition
Throws:AssertionError – If the assertion is false.
proc assertFalse(test: bool) throws

Assert that test is false.

Arguments:test – the boolean condition
Throws:AssertionError – If the assertion is true.
proc assertEqual(first, second) throws

Assert that first == second.

Arguments:
  • first – The first object to compare.
  • second – The second object to compare.
Throws:

AssertionError – If both the arguments are not equal.

proc assertNotEqual(first, second) throws

Assert that first != second.

Arguments:
  • first – The first object to compare.
  • second – The second object to compare.
Throws:

AssertionError – If both the arguments are equal.

proc assertGreaterThan(first, second) throws

Assert that first > second.

Arguments:
  • first – The first object to compare.
  • second – The second object to compare.
Throws:

AssertionError – If the first argument is not greater than second argument.

proc assertLessThan(first, second) throws

Assert that first < second.

Arguments:
  • first – The first object to compare.
  • second – The second object to compare.
Throws:

AssertionError – If the first argument is not less than the second argument.

proc maxLocales(value: int) throws

Specify maximum number of locales this test can run on.

Arguments:value – Maximum number of locales with which the test can be run.
Throws:UnexpectedLocales – If value is less than 1 or minNumLocales
proc minLocales(value: int) throws

Specify minimum number of locales required to run the test.

Arguments:value – Minimum number of locales with which the test can be run.
Throws:UnexpectedLocales – If value is more than maxNumLocales
proc addNumLocales(locales: int ...?n) throws

Indicate how many locales to run the test on.

If a test can run on multiple different locale counts, they can be specified using multiple arguments. Only one of the locale counts specified will be run in testing.

Note

To run a single test with multiple locale counts, create multiple tests where each test requires a specific locale count.

Arguments:locales – locale counts
Throws:UnexpectedLocales – If locales are already added.
proc dependsOn(tests: argType ...?n) throws

Adds the tests which must run before this test.

Arguments:tests – First class functions
Throws:DependencyFound – If called for the first time in a function.
proc main() throws

Runs the tests

Call this as

UnitTest.main();