Automatic test data generation

Proper unit testing requires covering all program paths. This is difficult without deep program knowledge and analysis. The automatic test data generation (TDG) feature in IBM Test Accelerator for Z utilizes symbolic execution and generates data for hard-to-reach program paths, accelerating unit test code coverage.

Automatic test data generation overview

Symbolic execution is a powerful technique used in software testing and analysis. Instead of executing a program with concrete input values, symbolic execution operates on symbolic values, which represent all possible values that a variable can take. During symbolic execution, the program's control flow and data dependencies are tracked symbolically, allowing for the exploration of multiple execution paths simultaneously.

Automatic test data generation uses symbolic execution to update the possible values in the form of constraints for all relevant variables on the semantics.
Test data generation: Program paths
In the program CHKREC(See Figure 1), X and Y are input parameters, and Figure 2 is a Control Flow Graph for CHKREC. There are four possible execution paths in the program.
  • IF X<Y THEN and IF X>30 THEN
  • IF X<Y THEN and IF X>30 ELSE
  • IF X<Y ELSE and IF X>30 THEN
  • IF X<Y ELSE and IF X>30 ELSE
When TDG generates test data of the execution path(2), the total conditional expression is X<Y and NOT(Y-X+10>30), and X=10 and Y=20 is a satisfiable solution. There are alternative satisfiable solutions like X=5 and Y=18, X=25 and Y=36. Therefore, you might get different values each TDG action.
Figure 1. Program CHKREC

Unit testing: Program CHKREC
Figure 2. Control Flow Graph for CHKREC

Unit testing: Control Flow Graph for CHKREC

Test data generation based on a recorded test

You can generate test data for hard-to-reach paths after recording a happy path through the program. In this example, assume that TEST1 was created from a recording. After running TEST1, you can see the code that is not covered. In Figure 3, you’ll see three branches of EVALUATE are not covered.
Figure 3. Three branches of EVALUATE are not covered

Unit testing: Three branches of EVALUATE are not covered
Also, “WRITE-ERROR-MESSAGE” paragraph to write an error message is not covered by TEST1. (See Figure 4)
Figure 4. WRITE-ERROR-MESSAGE paragraph to write an error message is not covered by TEST1

Unit testing: WRITE-ERROR-MESSAGE paragraph to write an error message is not covered by TEST1
Now we assume that you want to create test data for the “When Other” alternative path shown in Figure 3. Open the test case (.tc) file, Select Start Test Data Generation from the context menu of TEST1 to generate PathInfo0, and change the value of SQLCODE in the SQL SELECT statement to guide Automatic Test Data Generation to “WHEN OTHER” branch. (See Figure 5).
Figure 5. Change the value of SQLCODE

Unit testing: Change the value of SQLCODE

Rules of generated test data

See Generating test data for steps to generate test data.

Automatic Test Data Generation generates a new test for the alternate path guided by user input data. In this program, when SQLCODE is not 0, “WRITE-ERROR-MESSAGE” paragraph will be executed. Automatic Test Data Generation will generate test data for these three CICS statements(ASKTIME, FORMATTIME, and LINK).

The generated data is affected by the variable referenced in conditional branch and recorded data. Here, the value of DFHEIBLK in EXEC CICS LINK comes from the recorded data of DFHEIBLK in PROCEDURE DIVISION. (See Figure 6)
Figure 6. Value of DFHEIBLK

Unit testing: Value of DFHEIBLK
WS-TIME and WS-DATE are not referenced in any conditional branch. Random values are generated complying with the data attribute for these parameters.
Figure 7. Random values are generated

Unit testing: Random values are generated by automatic test data generation

Limitations

For limitations, see the Test data generation limitations section in Limitations of Early Development Testing for z/OS.