How to use axunit

This document describes the 'AX' unit test tool intended to automate all unit tests running with Sage X3 scripts.

Overview

The AXUNIT unit test framework is based on the same fundamentals as 'QUnit' or 'JUnit'.

The main purpose is to have a source file which is a test suite of several test cases that verify some predefined assertions.

File name convention

Every unit test file must match the file name pattern QLF*_*.src. The complete naming rule is described in the How to Naming Rule document.

Unit test template

Writing a unit test follows the template below:
CODECODE CODEshFunprog TESTSUITE()Call TESTSUITE_START("US-99999-99", "My description of the test suite for User story 99999-99") From AXUNITCall ADD_TESTCASE("TEST_MYCASE1", "My description of the test case 1", NB_CHECKS_IN_TEST_CASE_1) From AXUNITCall ADD_TESTCASE("TEST_MYCASE2", "My description of the test case 2", NB_CHECKS_IN_TEST_CASE_2) From AXUNITEnd func AXUNIT.RUN_TESTSUITE("US-99999-99", "My description of the test suite for User story 99999-99")Subprog SETUP# Optional subprog called *before* running the test suiteEndSubprog TEARDOWN# Optional subprog called *after* running the test suiteEndSubprog TEST_MYCASE1# ... some code to get the result we want to verify# the result of the code will be put to the first parameter of CHECK_EQUAL,# the expected value will be put to the second parameter of CHECK_EQUALCall CHECK_EQUAL(GOT, EXPECT) From AXUNIT# ... some code to get the result we want to verify# the code returns a logical value which we want to check. It will be put into the # first parameter of CHECK_TRUECall CHECK_TRUE(GOT) From AXUNIT# ... EndSubprog TEST_MYCASE2# ... End
Example: We want to write unit tests for a simple "addition" function:
Funprog ADD(SUMMAND1, SUMMAND2)Value Integer SUMMAND1Value Integer SUMMAND2End SUMMAND1 + SUMMAND2
In order to verify that the sum of 2 and 5 is indeed 7, we write:
Call CHECK_EQUAL(func ADD(2, 5), 7) From AXUNIT
or
Local Integer RESULTRESULT = func ADD(2, 5)Call CHECK_EQUAL(RESULT, 7) From AXUNIT

Subprograms to verify the expected result

The framework supports the following:

Checking the contents of an instance

An additional function is available (from patch 6) to allow to dump the content of an instance. The function is the following:

Call LOG_CLASS(MYINSTANCE,INSTANCE_NAME,ERRORS) From AXUNIT

Where:

When arrays of children instances are present, all the indexes are written in the log, preceded by a line that is written in this format:

NNN: [xxx,MMM]

Where NNN is the current index, xxx is the status of the line as given by ASTALIN (NEW, DEL, NEWDEL, UPD, NOTMOD), and MMM the value of AORDER.

An example of such a log is given here:
 Instance MYORDER of C_YORDER| ** AWARNING This order is really big| String(80) COMMENT : ""| Datetime CREDATTIM : "2014-07-03T15:22:18Z"| String(5) CREUSR : "MARTIN"| String(3) CURRENCY : "EUR"| String(15) CUSTOMER : "ZAO007"| ** AERROR ZAO007 : Record does not exist| String(5) FCY : "AO011"| Collection LINES of C_YLINE (1..3)| 001: [NEW,001] | | Decimal DISCOUNT : 0| | Integer DLVQTY : 0| | String(3) FLAG : ""| | String(20) ITEM : "BMS005"| | ShortInt NUMLIN : 1| | String(16) ORDNUM : "994159249"| | Decimal PRICE : 3.14| | Integer QTY : 1| | ShortInt SORTLIN : 1| | Decimal UNITPRICE : 3.14| 002: [DEL,002] | | Decimal DISCOUNT : 25| | Integer DLVQTY : 0| | String(3) FLAG : ""| | String(20) ITEM : "BMS007"| | ShortInt NUMLIN : 2| | String(16) ORDNUM : "994159249"| | Decimal PRICE : 1500| | Integer QTY : 20| | ShortInt SORTLIN : 2| | Decimal UNITPRICE : 100| 003: [UPD,003] | | Decimal DISCOUNT : 95| | ** AERROR Discount too high| | Integer DLVQTY : 0| | String(3) FLAG : ""| | String(20) ITEM : "BMS007"| | ShortInt NUMLIN : 3| | String(16) ORDNUM : "994159249"| | Decimal PRICE : -100| | Integer QTY : 20| | ShortInt SORTLIN : 3| | Decimal UNITPRICE : -100| | ** AERROR Price must be positive| String(20) OPERATION : ""| TinyInt ORDCLO : 1| Date ORDDAT : "2014-07-14"| String(16) ORDNUM : "994159249"| TinyInt ORDSTA : 1| Decimal TOTAL : 1403.14| Datetime UPDDATTIM : "0000-00-00T00:00:00Z"| String(5) UPDUSR : ""

Running a unit test

Different options are available to run a unit test.

Run an individual test in the Eclipse console

In the Eclipse console, type a func call with the full qualified name of the test suite. For example:

CODECODE CODEsh=>func qlfar_encode.testsuiteQLFAR_ENCODE - REQ-70693 - 4 Succeed, 0 Failed, 80ms elapsedTrace has been written to '/produits/v160/SOLSUPV6/dossiers/SUPERV/TRA/QLFAR_ENCODE_ERBOU.tra'JSON result is available at: http://sodaix02/Adonix_SOLSUPV6/SUPERV/TMP/QLFAR_ENCODE_ERBOU.json

A summary of the result is generated with the number of successful and failed test cases and the elapsed time spent by the test session.

Run all tests

Running all tests could last a while. For this reason, it is recommended to not run them in the Eclipse console. To run all tests, call func AXUNIT.RUN_ALL.

Run some tests

It is possible to run all tests or exclude some of them by calling the func AXUNIT.RUN_ALL2(EXCLUDES, NODEBUG) function.

This function requires two arguments:

  1. EXCLUDES A string of program names separated by ;
  2. NODEBUG A value indicating if the debug mode must be disabled.
The following example calls all unit tests except `QLFAS_ASYRMAIN` while preventing the triggering of the debugger:
CODECODE CODEshfunc AXUNIT.RUN_ALL2(";QLFAS_ASYRMAIN;", 1)

Run a subset of unit tests

By using an appropriate name convention, it is simple to run a subset of unit tests by calling the func AXUNIT.RUN_SET("AS") function. This function will call all QLFAS_*.src unit tests (all supervisor tests).

Run in batch mode

This is the recommended way to run all tests. Create a batch task that calls func AXUNIT.RUN_ALL or func AXUNIT.RUN_ALL2("", 1).