How to test a class

The best development practices include the design of test cases. For every persistent class, the development partner must create a test case to check that everything is functioning correctly, while invoking standard or additional methods used in the class declaration.

The purpose of this test case is not only to verify that all methods work well with the correct data, but also to examine various error cases and make sure that errors are handled correctly. Before reading this document, it is recommended that you read the How to use AXUNIT document.

A test case consists of a normalized script. A specific chart for naming the test scripts is described in the How to Naming Rule document. For example, a test script on a given persistent class called 'MYCLASS' in the functional domain 'FDO' could be called 'QLF_FDO_MYCLASS'.

The different sections of the scripts and the main considerations about how they must be defined are explained in this document.

Establish the data used by the test

Main data required

Minimum data is necessary to execute the test. For example, customers, items, and currencies might be a prerequisite for the test of methods associated with the sales order.

Two alternatives are available to provide necessary:

  • Data description is documented (as comments). In this case, the development partner must ensure the presence of the right data set in the different environments where the test must be conducted. There might be some data present in the SEED folder that will be copied in all the environments where non-regression tests must be executed.
  • Data must be created during the test. This can be part of the automated test for the corresponding data as a sub-program in the test case. If a customer is required, a good practice is to call at the beginning of the test case the 'SETUP' sub-program of the test data script associated with the customer class.

Cleaning the data before starting the test

In the 'SETUP' sub-program, a procedure that cleans the data should be written. Because an automated test is likely to fail, this cleaning sub-program:

  • Must delete the data created during the test.
  • Must be called at the beginning and not at the end. A cleaning at the end of test could not be performed in case of test failure.
  • Must not consider that a cleaning error (remaining data) is a failure of the cleaning procedure.

Write the test execution lines

Test execution lines are written using the 'TESTSUITE' function. It is called by the 'AXUNIT' tool from every 'QLF*' script to execute the test.

In the 'TESTSUITE' function, the following sub-programs are called:

  • 'TESTSUITE_START' From 'AXUNIT' to describe the test suite.
  • 'ADD_TESTCASE' Fom 'AXUNIT' to add the list of test cases to be initiated.
  • 'RUN_TESTSUITE' From 'AXUNIT' to run the test.

Every test sub-program added by 'ADD_TESTCASE' has a name. For a persistent class, the name of the test sub-program can be:

Test Case sub-program name Use
MYCLASS_CREATE Creation of a class instance
MYCLASS_READ Read operation on a class instance
MYCLASS_UPDATE Update of a class instance
MYCLASS_MYMETHOD Test of the Method 'MYMETHOD'
MYCLASS_MYPROP_PROPAGATE Test of the propagation rule on 'MYPROP' property

When complex documents with headers and lines are created, it is important to test all the operations on the child classes, including the insertion and deletion of lines.

The beginning of the test script looks like the example below:

CODECODE CODEsh
#**
#* The main entry point of the unit test suite
#*
#*!
Funprog TESTSUITE()
# Start the test suite
Call TESTSUITE_START("MYCLASS", "MYCLASS test") From AXUNIT
# Call the different test cases
Call ADD_TESTCASE("MYCLASS_CREATION","Creation of MYCLASS with errors check",0) From AXUNIT
Call ADD_TESTCASE("MYCLASS_READ","Read MYCLASS",0) From AXUNIT
Call ADD_TESTCASE("MYCLASS_UPDATE","Update MYCLASS",0) From AXUNIT
Call ADD_TESTCASE("MYCLASS_DELETE","Deletion MYCLASS",0) From AXUNIT
# Run the test and return the result
Local Clbfile RESULT_SUITE
  RESULT_SUITE=func AXUNIT.RUN_TESTSUITE("MYCLASS","MYCLASS test")
End RESULT_SUITE

In the different test cases, to check if the result expected is the right one, the 'CHECK_EQUAL', 'CHECK_NOTEQUAL', 'CHECK_TRUE', 'CHECK_FALSE'... sub-programs from "AXUNIT" must be used. The 'MYCLASS_CREATE' sub-program should look like the example below:
CODECODE CODEsh
# Creation subprogram
Subprog MYCLASS_CREATION()
Local Integer ASTATUS
Local Instance MYINST01 Using C_MYCLASS
# Instantiate the class
MYINST01 = NewInstance C_MYCLASS AllocGroup Null
# Assign all the properties but with some errors (repeat it several times with various error cases)
  MYINST01.PROP1 = ...
  MYINST01.PROP2 = ...
  ...
  MYINST01.PROPN = ...
  [L]ASTATUS = fmet MYINST01.AINSERT()
  Call CHECK_EQUAL([L]ASTATUS,[V]CST_AERROR) From AXUNIT
...
# Assign correctly the elements to have successful creations
  MYINST01.PROP1 = ...
  MYINST01.PROP2 = ...
  ...
  MYINST01.PROPN = ...
  [L]ASTATUS = fmet MYINST01.AINSERT()
  Call CHECK_EQUAL([L]ASTATUS,[V]CST_AOK) From AXUNIT
# Check also if necessary the values of some properties if they are computed at insertion
  Call CHECK_EQUAL(MYINST01.PROP1,"EXPECTED_VALUE") From AXUNIT
# Repeat other creation cases if necessary
...
# End of test
  FreeGroup MYINSTA01
End

Complete example

A complete example of a test program for the classes created in the CRUD example is provided below.

The Main routine

The code for the main routine is shown below. This routine starts the job and calls the different test cases, which are:

  • An Insertion of an entity (54 unit tests)
  • A Read operation on the entity (77 unit tests)
  • An Update operation on the entity (11 unit tests)
  • An execution of an operation (2 unit tests)
  • An execution of a Delete operation (5 unit tests).
The lines are as follows:
CODECODE CODEsh
#**
#* The main entry point of the unit test suite
#*
#*!
Call TESTSUITE
End
Funprog TESTSUITE()
# Start the test suite
  Call TESTSUITE_START("YORDER", "YORDER test") From AXUNIT
# Call the different test cases
  Call ADD_TESTCASE("YORDER_AINSERT","Creation of YORDER with errors check",54) From AXUNIT
  Call ADD_TESTCASE("YORDER_AREAD","Check YORDER previously created",77) From AXUNIT
  Call ADD_TESTCASE("YORDER_AUPDATE","Check YORDER update",11) From AXUNIT
  Call ADD_TESTCASE("YORDER_YVALIDATE","Check YORDER validation operation",2) From AXUNIT
  Call ADD_TESTCASE("YORDER_ADELETE","Check YORDER deletion",5) From AXUNIT
# Run the test and return the result
Local Clbfile RESULT_SUITE
  RESULT_SUITE=func AXUNIT.RUN_TESTSUITE("YORDER","YORDER test")
End RESULT_SUITE

The Insertion test

This routine creates an order of several steps:

  • The instance is created. At this point, a temporary hack has been added because the mandatory constraints are not updated by the class constructor, but this will evolve in the near future.
  • Lines and sub-lines are added by using the 'ADDLINE' method at different levels.
  • A first insertion is tried but it fails due to an unfilled mandatory information. A detailed log provides a list of all the detected errors.
  • A call to an internal method is done to cancel all the errors (this will also change in the future). Otherwise, it would be necessary to re-instantiate a class and fill all the properties again.
  • The order number is updated at the header level, a test is done to verify that the lines and sub-lines values have been propagated.
  • A second unsuccessful insertion attempt is performed (still some mandatory values missing).
  • Errors are written in the log again, and then cancelled. The missing values are filled and a final successful insertion is performed.
  • The computation price is verified.
The code for the Insertion routine is as follows:
CODECODE CODEsh
# Create an order
Subprog YORDER_AINSERT
Local Instance MYORDER Using C_YORDER
Local Integer I,J,K,L,OK
Local Decimal TOTAL_PRICE
  MYORDER=NewInstance C_YORDER AllocGroup Null
# Double loop on lines and sub-lines
# The total price is computed on the fly to be able to perform a consistency check
  TOTAL_PRICE=0
# 5 lines inserted
  For I=1 To 5
    J=fmet MYORDER.ADDLINE("YOD",[V]CST_ALASTPOS)
    Call LOG_LINE("Result of ADDLIN I="+num$(I)) From AXUNIT
    Call CHECK_TRUE(J>=0) From AXUNIT
    # We use existing items coded "BMSMN0020x" where x varies from 3 to 8
    MYORDER.YOD(J).YITM="BMSMN0020"+num$(2+I)
#   4 sub-lines inserted for every line
    For L=1 To 4
      K=fmet MYORDER.YOD(J).ADDLINE("YOL",[V]CST_ALASTPOS)
      Call LOG_LINE("Result of ADDLIN L="+num$(L)) From AXUNIT
      Call CHECK_TRUE(K>=0) From AXUNIT
      # We use successively the units "UN","TEN","CAR","PAC"
      MYORDER.YOD(J).YOL(K).YUNIT=vireblc(mid$("UN TENCARPAC",3*L-2,3),2)
      MYORDER.YOD(J).YOL(K).YQTY=I*L
      MYORDER.YOD(J).YOL(K).YUNITPRICE=5+L
      TOTAL_PRICE+=(I*L)*(5+L)
    Next L
  Next I
# A lot of mandatory properties have no value : LOG_ERRORS will dump them
  OK=fmet MYORDER.AINSERT
  Call LOG_LINE("Result of AINSERT") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AERROR) From AXUNIT
  Call LOG_ERRORS(MYORDER)
# Assigning the order number here will propagate
  MYORDER.YORDNUM="314159"
# Check the propagation
  Call LOG_LINE("Propagate checks") From AXUNIT
  For I=1 To 5
    For J=1 To 4
      Call CHECK_EQUAL(MYORDER.YOD(I).YOL(J).YORDNUM,MYORDER.YORDNUM) From AXUNIT
    Next J
    Call CHECK_EQUAL(MYORDER.YOD(I).YORDNUM,MYORDER.YORDNUM) From AXUNIT
  Next I
# Still a lot of mandatory properties have no value
  OK=fmet MYORDER.AINSERT
  Call LOG_LINE("Result of AINSERT") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AERROR) From AXUNIT
  Call LOG_ERRORS(MYORDER)
# Now let's assign the missing mandatory values
# Customer code, sales rep code and currency code are supposed to exist
  MYORDER.YBPC="BPC-000003"
  MYORDER.YREP="REPRE004"
  MYORDER.YORDDAT=[09/05/2002]
  MYORDER.YCUR='EUR'
  MYORDER.YSTATUS=1
  OK=fmet MYORDER.AINSERT
# Check if the creation is OK
  Call LOG_LINE("Checks the insertion when everything is OK") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
  Call LOG_LINE("Checks the total price computation") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YTOTAL,TOTAL_PRICE) From AXUNIT
  FreeGroup MYORDER
End

The Read test

This routine reads the previous order and performs the following verifications:

  • The return value of 'AREAD' is OK.
  • The header properties have the expected values.
  • The lines and sub-lines properties have the right values.
  • The total price is verified.
The code for the Read routine is as follows:
CODECODE CODEsh
Subprog YORDER_AREAD
Local Instance MYORDER Using C_YORDER
Local Integer I,J,K,L,M,N,OK
Local Decimal TOTAL_PRICE
  MYORDER=NewInstance C_YORDER AllocGroup Null
  OK=fmet MYORDER.AREAD("314159")
  Call LOG_LINE("Checks the AREAD method") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
  Call LOG_LINE("Verify the values read") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YBPC,"BPC-000003") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YREP,"REPRE004") From AXUNIT
  Call CHECK_EQUAL(num$(MYORDER.YORDDAT),"09/05/2002") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YCUR,'EUR') From AXUNIT
  Call CHECK_EQUAL(MYORDER.YSTATUS,1) From AXUNIT
  Call LOG_LINE("Verify the lines and sub-lines values read") From AXUNIT
  K=0
  For I=1 To maxtab(MYORDER.YOD)
    If MYORDER.YOD(I)<>null
      J+=1
      K=MYORDER.YOD(I).AORDER
      Call CHECK_EQUAL(MYORDER.YOD(I).YITM,"BMSMN0020"+num$(2+K)) From AXUNIT
      Call CHECK_EQUAL(MYORDER.YOD(I).YPRICE,sigma(1,4,K*indcum*(5+indcum))) From AXUNIT
      For L=1 To maxtab(MYORDER.YOD(I).YOL)
        M=0
        If MYORDER.YOD(I).YOL(L)<>null
          M+=1
          N=MYORDER.YOD(I).YOL(L).AORDER
          Call CHECK_EQUAL(MYORDER.YOD(I).YOL(L).YUNIT,vireblc(mid$("UN TENCARPAC",3*N-2,3),2)) From AXUNIT
          Call CHECK_EQUAL(MYORDER.YOD(I).YOL(L).YQTY,K*N) From AXUNIT
          Call CHECK_EQUAL(MYORDER.YOD(I).YOL(L).YUNITPRICE,5+N) From AXUNIT
          TOTAL_PRICE+=(5+N)*K*N
        Endif
      Next L
    Endif
  Next I
  Call LOG_LINE("Verify the total price read") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YTOTAL,TOTAL_PRICE) From AXUNIT
  FreeGroup MYORDER
End

The Update test

This routine reads the previous order and performs the following updates:

  • Deletion of a sub-line
  • Insertion of a sub-line
  • Modification of a line
  • Deletion of a line
  • Update of the document
  • Verification of the total (lines and header)
The code of the Update routine is as follows:
CODECODE CODEsh
# The update test
Subprog YORDER_AUPDATE
Local Instance MYORDER Using C_YORDER
Local Integer I,J,K,L,M,N,OK
Local Decimal TOTAL_PRICE, LINE_PRICE
  MYORDER=NewInstance C_YORDER AllocGroup Null
  OK=fmet MYORDER.AREAD("314159")
  Call LOG_LINE("Checks the AREAD method") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Different modifications will be done here:
# Get the 2nd line, then the 2nd sub-line of this line, and delete it
  Call LOG_LINE("Checks an insertion at level 2") From AXUNIT
  I=fmet MYORDER.AGETINDBYLINE("YOD",2)
  OK=fmet MYORDER.YOD(I).ADELLINE("YOL",2)
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Get the 4th line, then insert a line at the third position of the sub-lines
  Call LOG_LINE("Checks an insertion of a sub-line") From AXUNIT
  I=fmet MYORDER.AGETINDBYLINE("YOD",4)
  J=fmet MYORDER.YOD(I).ADDLINE("YOL",3)
  Call LOG_LINE("Checks an insertion of a sub-line"-num$(J)) From AXUNIT
  Call CHECK_NOTEQUAL(J,[V]CST_ANOTDEFINED) From AXUNIT
  MYORDER.YOD(I).YOL(J).YUNIT="TEN"
  MYORDER.YOD(I).YOL(J).YQTY=3
  MYORDER.YOD(I).YOL(J).YUNITPRICE=16
# Get the 5th line, then modify the 4th sub-line
  Call LOG_LINE("Checks a modification of a sub-line") From AXUNIT
  I=fmet MYORDER.AGETINDBYLINE("YOD",5)
  J=fmet MYORDER.YOD(I).AGETINDBYLINE("YOL",4)
  Call CHECK_NOTEQUAL(J,[V]CST_ANOTDEFINED) From AXUNIT
  MYORDER.YOD(I).YOL(J).YUNIT="TEN"
  MYORDER.YOD(I).YOL(J).YQTY=10
  MYORDER.YOD(I).YOL(J).YUNITPRICE=43
# Delete the 3rd line
  Call LOG_LINE("Checks a deletion on a line") From AXUNIT
  OK=fmet MYORDER.ADELLINE("YOD",3)
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Update the order
  Call LOG_LINE("Checks the update") From AXUNIT
  OK=fmet MYORDER.AUPDATE
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
  Call LOG_LINE("Verify the lines and sub-lines values after update") From AXUNIT
  # K is the grand total, and L the total of every line (cumulated sub-lines)
  TOTAL_PRICE=0
  For I=1 To maxtab(MYORDER.YOD)
    If MYORDER.YOD(I)<>null
      If find(MYORDER.YOD(I).ASTALIN,[V]CST_ADEL, [V]CST_ANEWDEL)=0
        LINE_PRICE=0
        For J=1 To maxtab(MYORDER.YOD(I).YOL)
          If MYORDER.YOD(I).YOL(J)<>null
            If find(MYORDER.YOD(I).YOL(J).ASTALIN,[V]CST_ADEL, [V]CST_ANEWDEL)=0
              LINE_PRICE+=MYORDER.YOD(I).YOL(J).YQTY*MYORDER.YOD(I).YOL(J).YUNITPRICE
            Endif
          Endif
        Next J
        TOTAL_PRICE+=LINE_PRICE
        Call LOG_LINE("Verify the total price of line"-num$(I)) From AXUNIT
        Call CHECK_EQUAL(MYORDER.YOD(I).YPRICE,LINE_PRICE) From AXUNIT
      Endif
    Endif
  Next I
  Call LOG_LINE("Verify the total price read") From AXUNIT
  Call CHECK_EQUAL(MYORDER.YTOTAL,TOTAL_PRICE) From AXUNIT
  FreeGroup MYORDER
End

The Operation test

This routine performs an operation (YVALIDATE) that can return a warning if it has already been performed.

  • A first call is performed and the return status is checked.
  • A second call is performed and the return must be a warning.
The code of the operation routine is as follows:
CODECODE CODEsh
# Validate an order
Subprog YORDER_YVALIDATE
Local Instance MYORDER Using C_YORDER
Local Integer OK
# Instantiate the order
  MYORDER=NewInstance C_YORDER AllocGroup Null
# First time, it will work
  Call LOG_LINE("Verify the order validation result") From AXUNIT
  OK=fmet MYORDER.YVALIDATE("314159")
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Do it again : a warning is expected
  Call LOG_LINE("Verify the order validation result with warning") From AXUNIT
  OK=fmet MYORDER.YVALIDATE("314159")
  Call CHECK_EQUAL(OK,[V]CST_AWARNING) From AXUNIT
  FreeGroup MYORDER
 End

The Deletion test

This routine performs a deletion:

  • First, the instance is read.
  • Then a first attempt is done: it fails because the order has been validated by the previous test.
  • The validation flag is updated by a direct database update.
  • A second call is done that must succeed.
  • A call is done to the cleaning function that returns the number of deleted databases (must be 0).
The code for the Operation routine is as follows:
CODECODE CODEsh
# Delete an order
Subprog YORDER_ADELETE
Local Instance MYORDER Using C_YORDER
Local Integer OK
# Instantiate the order
  MYORDER=NewInstance C_YORDER AllocGroup Null
# Read the order
  OK=fmet MYORDER.AREAD("314159")
  Call LOG_LINE("Verify the order exists") From AXUNIT
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# As this order is validated, it cannot be deleted
  Call LOG_LINE("Verify the order cannot be deleted") From AXUNIT
  OK=fmet MYORDER.ADELETE
  Call CHECK_EQUAL(OK,[V]CST_AERROR) From AXUNIT
# Clean up the class
  FreeGroup MYORDER
  MYORDER=NewInstance C_YORDER AllocGroup Null
# Now let's invalidate the order
  Local File YORDER
  Trbegin [YOH]
  Update [YOH] Where YORDNUM="314159" With YSTATUS=1
  Commit
# Read the order again
  Call LOG_LINE("Read the order again") From AXUNIT
  OK=fmet MYORDER.AREAD("314159")
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Do it again : it should be OK
  Call LOG_LINE("Verify the order has been deleted") From AXUNIT
  OK=fmet MYORDER.ADELETE
  Call CHECK_EQUAL(OK,[V]CST_AOK) From AXUNIT
# Verify that nothing remains
  Call LOG_LINE("Verify that the lines in the database have been deleted") From AXUNIT
  OK=func CLEANUP("314159")
  Call CHECK_EQUAL(OK,0) From AXUNIT
  FreeGroup MYORDER
 End

The clean-up function

This function deletes the header, lines, and sub-lines associated with a key value and returns the number of lines deleted. It is called in the previous test and in the 'SETUP' sub-program. This 'SETUP' sub-program is automatically called by the unit test framework at the beginning of a test to ensure that no remaining data is likely to hinder the normal test operation.

The code for the Operation routine is as follows:
CODECODE CODEsh
# Delete the order and count the number of deleted lines
Funprog CLEANUP(NUMYOH)
Value Char NUMYOH
Local Integer I
Local File YORDER,YORDERLINE,YORDERSUBLIN
Trbegin [YOH],[YOD],[YOL]
  Delete [YOH] Where YORDNUM=NUMYOH
  I+=adxdlrec
  Delete [YOD] Where YORDNUM=NUMYOH
  I+=adxdlrec
  Delete [YOL] Where YORDNUM=NUMYOH
  I+=adxdlrec
  Commit
End I
Subprog SETUP
Local Integer I
I=func CLEANUP("314159")
End

Additional sub-programs

Some routines have been added at the end of the test. The following routines are available:

  • A function "ADELERRORS" deletes the errors by using an internal routine. This is temporary, a permanent method will be supplied later.
  • A "LOG_ERROR" sub-program goes through the error hierarchy to get the errors. A standard method exists for this task, but the generated standard log is not detailed enough.
  • A "LINE_LOG" sub-program handles an error line in the log.
The code for the Operation routine is as follows:
CODECODE CODEsh
# Will be replaced later
Funprog ADELERRORS(MYCLASS)
Value Instance MYCLASS Using C_YORDER
End MYCLASS._ADELERRORS("+")
Subprog LOG_ERRORS(MYORDER)
Value Instance MYORDER Using C_YORDER
Local Integer IFERROR,I,J
# Errors on the header
  For I=1 To maxtab(MYORDER.AERROR)
    If MYORDER.AERROR(I)<>null
      Call LINE_LOG("Header",MYORDER.AERROR(I),IFERROR)
    Endif
  Next I
# Errors on the lines
  For I=1 To maxtab(MYORDER.YOD)
    If MYORDER.YOD(I)<>null
      For J=1 To maxtab(MYORDER.YOD(I).AERROR)
        If MYORDER.YOD(I).AERROR(J)<>null
          Call LINE_LOG("Line"-num$(MYORDER.YOD(I).AORDER),MYORDER.YOD(I).AERROR(J),IFERROR)
        Endif
      Next J
      For K=1 To maxtab(MYORDER.YOD(I).YOL)
        If MYORDER.YOD(I).YOL(K)<>null
          For J=1 To maxtab(MYORDER.YOD(I).YOL(K).AERROR)
            If MYORDER.YOD(I).YOL(K).AERROR(J)<>null
              Call LINE_LOG("Sub-Line ("+num$(MYORDER.YOD(I).AORDER)+","+num$(MYORDER.YOD(I).YOL(K).AORDER)+")",
&                           MYORDER.YOD(I).YOL(K).AERROR(J),IFERROR)
            Endif
          Next J
        Endif
      Next K
    Endif
  Next I
End
Subprog LINE_LOG(MES1,ERRINS,IFERROR)
Value Char MES1()
Value Instance ERRINS Using C_AERROR
Variable Integer IFERROR
Local Char MESSAGE(250)
  If IFERROR=0
    Call LOG_LINE("*** Errors dump ***") From AXUNIT
    IFERROR=1
  Endif
   MESSAGE=MES1
   If ERRINS.PRO="" : MESSAGE-="(Global)"
   Else               MESSAGE-="["+ERRINS.PRO+"]"
   Endif
   MESSAGE-=":"-ERRINS.MES
   Call LOG_LINE(MESSAGE) From AXUNIT
End

The generated log file

Part of the 285 lines produced by the test are provided below as an example:

```
CODECODE CODE
2013-03-07T16:18:36.983: Start suite - QLFYDOM_Y1 - YORDER - YORDER test

2013-03-07T16:18:36.987: Start test case - Creation of YORDER with errors check
2013-03-07T16:18:36.999: Result of ADDLIN I=1
2013-03-07T16:18:37.027: Result of ADDLIN L=1
2013-03-07T16:18:37.077: Result of ADDLIN L=2
2013-03-07T16:18:37.090: Result of ADDLIN L=3
2013-03-07T16:18:37.103: Result of ADDLIN L=4
2013-03-07T16:18:37.117: Result of ADDLIN I=2
2013-03-07T16:18:37.127: Result of ADDLIN L=1
2013-03-07T16:18:37.138: Result of ADDLIN L=2
.....
2013-03-07T16:18:37.392: Result of ADDLIN L=4
2013-03-07T16:18:37.465: Result of AINSERT
2013-03-07T16:18:37.466: * Errors dump
2013-03-07T16:18:37.466: Header [YORDNUM] : Mandatory field
2013-03-07T16:18:37.467: Header [YBPC] : Mandatory field
2013-03-07T16:18:37.467: Header [YREP] : Mandatory field
2013-03-07T16:18:37.467: Header [YORDDAT] : Mandatory field
2013-03-07T16:18:37.468: Header [YCUR] : Mandatory field
2013-03-07T16:18:37.468: Line 1 [YORDNUM] : Mandatory field
2013-03-07T16:18:37.468: Sub-Line (1,1) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.469: Sub-Line (1,2) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.469: Sub-Line (1,3) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.470: Sub-Line (1,4) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.470: Line 2 [YORDNUM] : Mandatory field
2013-03-07T16:18:37.470: Sub-Line (2,1) [YORDNUM] : Mandatory field
.....
2013-03-07T16:18:37.477: Sub-Line (5,4) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.501: Propagate checks
2013-03-07T16:18:37.512: Result of AINSERT
2013-03-07T16:18:37.512: Errors dump *
2013-03-07T16:18:37.512: Header [YORDNUM] : Mandatory field
2013-03-07T16:18:37.513: Header [YBPC] : Mandatory field
2013-03-07T16:18:37.513: Header [YREP] : Mandatory field
2013-03-07T16:18:37.513: Header [YORDDAT] : Mandatory field
2013-03-07T16:18:37.513: Header [YCUR] : Mandatory field
2013-03-07T16:18:37.514: Line 1 [YORDNUM] : Mandatory field
2013-03-07T16:18:37.514: Sub-Line (1,1) [YORDNUM] : Mandatory field
2013-03-07T16:18:37.514: Sub-Line (1,2) [YORDNUM] : Mandatory field
.....
2013-03-07T16:18:38.029: Checks the total price computation
1.1 - check isTrue - OK
1.2 - check isTrue - OK
1.3 - check isTrue - OK
1.4 - check isTrue - OK
1.5 - check isTrue - OK
1.6 - check isTrue - OK
1.7 - check isTrue - OK
1.8 - check isTrue - OK
1.9 - check isTrue - OK
......
1.24 - check isTrue - OK
1.25 - check isTrue - OK
1.26 - check equal - OK: 4
1.27 - check equal - OK: '314159'
1.28 - check equal - OK: '314159'
1.29 - check equal - OK: '314159'
1.30 - check equal - OK: '314159'
1.31 - check equal - OK: '314159'
1.32 - check equal - OK: '314159'
1.33 - check equal - OK: '314159'
......
1.51 - check equal - OK: '314159'
1.52 - check equal - OK: 4
1.53 - check equal - OK: 0
1.54 - check equal - OK: 1200

0001 success=54, failure=0, elapsed=1044ms

2013-03-07T16:18:38.030: Start test case - Check YORDER previously created
2013-03-07T16:18:38.251: Checks the AREAD method
2013-03-07T16:18:38.251: Verify the values read
2013-03-07T16:18:38.254: Verify the lines and sub-lines values read
2013-03-07T16:18:38.276: Verify the total price read
2.1 - check equal - OK: 0
2.2 - check equal - OK: 'BPC-000003'
2.3 - check equal - OK: 'REPRE004'
2.4 - check equal - OK: '09/05/2002'
2.5 - check equal - OK: 'EUR'
2.6 - check equal - OK: 1
2.7 - check equal - OK: 'BMSMN00203'
2.8 - check equal - OK: 80
......
2.76 - check equal - OK: 9
2.77 - check equal - OK: 1200

0001 success=77, failure=0, elapsed=246ms

2013-03-07T16:18:38.277: Start test case - Check YORDER update
2013-03-07T16:18:38.467: Checks the AREAD method
2013-03-07T16:18:38.468: Checks an insertion at level 2
2013-03-07T16:18:38.470: Checks an insertion of a sub-line
2013-03-07T16:18:38.484: Checks an insertion of a sub-line 5
2013-03-07T16:18:38.487: Checks a modification of a sub-line
2013-03-07T16:18:38.491: Checks a deletion on a line
2013-03-07T16:18:38.493: Checks the update
2013-03-07T16:18:38.758: Verify the lines and sub-lines values after update
2013-03-07T16:18:38.759: Verify the total price of line 1
2013-03-07T16:18:38.759: Verify the total price of line 2
2013-03-07T16:18:38.760: Verify the total price of line 4
2013-03-07T16:18:38.761: Verify the total price of line 5
2013-03-07T16:18:38.761: Verify the total price read
3.1 - check equal - OK: 0
3.2 - check equal - OK: 0
3.3 - check notEqual - OK: 5
3.4 - check notEqual - OK: 4
3.5 - check equal - OK: 0
.......
3.11 - check equal - OK: 1230

0001 success=11, failure=0, elapsed=485ms

2013-03-07T16:18:38.763: Start test case - Check YORDER validation operation
2013-03-07T16:18:38.764: Verify the order validation result
2013-03-07T16:18:38.809: Verify the order validation result with warning
4.1 - check equal - OK: 0
4.2 - check equal - OK: 3

0001 success=2, failure=0, elapsed=50ms

2013-03-07T16:18:38.812: Start test case - Check YORDER deletion
2013-03-07T16:18:38.952: Verify the order exists
2013-03-07T16:18:38.952: Verify the order cannot be deleted
2013-03-07T16:18:38.964: Read the order again
2013-03-07T16:18:39.099: Verify the order has been deleted
2013-03-07T16:18:39.324: Verify that the lines in the database have been deleted
5.1 - check equal - OK: 0
5.2 - check equal - OK: 4
5.3 - check equal - OK: 0
5.4 - check equal - OK: 0
5.5 - check equal - OK: 0

0001 success=5, failure=0, elapsed=516ms
2013-03-07T16:18:39.329: QLFYDOM_Y1 - YORDER - 5 Succeed, 0 Failed, 2354ms elapsed
Trace has been written to '....../TRA/QLFYDOM_Y1_DOM.tra'
JSON result is available at: http://.../TMP/QLFYDOM_Y1_DOM.json
```