Unit Testing

Unit tests provide a way to validate that code functions correctly and to detect errors that might be introduced as code is modified. A Unit Test Module contains a list of unit tests. Unit tests can be run individually, all of the tests in a unit test module can be executed at the same time, or using the Unit Test Runner, unit tests from multiple unit test modules can be run simultaneously.

Unit tests modules available to the current document are listed in the Document Explorer. Unit tests modules are created and listed in the Document Explorer and are designated by the U icon. New unit tests can be added to libraries, folders, or to the current document under the Objects node.

For unit tests to execute correctly, the libraries containing the corresponding functionality must be referenced. For example, unit tests that execute integrals will fail if the Calc.eql library is not referenced. For unit tests organized into libraries, the unit test library would typically contain references to the required libraries.

The unit test expression is executed in much the same way as clauses in functions. In order for a unit test to pass, execution of the unit test expression must return a UnitTestResult object (in the Code namespace) with three parameters. The first parameter is True or False to indicate whether the test passed, the second parameter is the actual result and the third parameter is the expected result.

The unit test object (UnitTest) itself is a built-in function. The UnitTest function executes the expression in the first parameter and then compares the result to the expression in the second parameter. The UnitTest function then returns a UnitTestResult object with three parameters. The first parameter is either True or False and indicates whether or not the test passed. The second parameter is the result from executing the first parameter of the UnitTest function. The third parameter is just a copy of the second parameter passed into the UnitTest function.

Though the unit test expression must build to a UnitTestResult object for the test to be valid, it is not required that unit test expressions contain the UnitTest object. Other expressions that return a UnitTestResult object when executed would also be valid as unit tests. As a trivial example, a unit test expression like UnitTestResult[True, x, x] is valid and would pass. UnitTestResult[False, expr, b] would fail and the expression expr would be displayed to the right of the unit test.

Generally, there is no need to use the UnitTestResult object directly. It's usually simpler to just construct the unit test using the standard UnitTest object.

Typically, a unit test module consists of one or more tests and each test is an expression that has the UnitTest object at the top of the expression tree, but Unit Test Modules can contain expressions other than just unit tests. Any expression that returns a UnitTestResult is a valid unit test. For example, an expression like

is a valid unit test but doesn't have the UnitTest object at the top of the expression tree.

In addition to the UnitTest object, the Let object in the Core namespace is also used during the processing of the unit tests in a module. The Let object is useful in a unit test module where an expression is used repeatedly in multiple unit tests. Rather than having repeated occurrences of the expression, you can use a Let expression to assign a variable name to the repeated expression and just use the variable in the unit tests. The Let object has two parameters, the first must be a variable, the second is an expression that will be bound to the variable. For example, a Unit Test Module might contain:

The Let object is applied to all of the unit tests in a module regardless of where it's positioned in the module and there can be more than one Let object in a module. The variable binding created by a Let object is only used in the Unit Test Module that contains the Let expression.

Any expression that is not a valid unit test will be ignored when the tests are run. You can add expressions that aren't unit tests to Unit Test Modules as comments and documentation.