Testing COBOL

COBOL GnuCOBOL 3.2.0 ยท โœ“ verified by execution on 2026-08-16

When developing COBOL applications, unit testing is essential to ensure that individual components function correctly. A test harness in COBOL is typically a main program that sets up linkage section data and calls the subprogram being tested. This allows you to verify business logic independently of the larger system.

Writing a Test Harness

To test a subprogram, you can write a calling program that passes the required data to the subprogram and checks the results returned. This acts as a test harness, setting up the environment and invoking the code under test.

cobol โœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTHARN.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 INPUT-VAL   PIC 9(2) VALUE 10.
       01 RESULT-VAL  PIC 9(3) VALUE 0.
       PROCEDURE DIVISION.
           CALL 'CALCDOUBLE' USING INPUT-VAL RESULT-VAL.
           IF RESULT-VAL = 20
               DISPLAY "TEST PASS"
           ELSE
               DISPLAY "TEST FAIL: " RESULT-VAL
           END-IF
           STOP RUN.
           
       IDENTIFICATION DIVISION.
       PROGRAM-ID. CALCDOUBLE.
       DATA DIVISION.
       LINKAGE SECTION.
       01 IN-VAL  PIC 9(2).
       01 OUT-VAL PIC 9(3).
       PROCEDURE DIVISION USING IN-VAL OUT-VAL.
           COMPUTE OUT-VAL = IN-VAL * 2.
           EXIT PROGRAM.
       END PROGRAM CALCDOUBLE.
Output
TEST PASS

Unit testing in COBOL usually means executing a paragraph or a subprogram with known initial data. The test harness above initializes the working storage, calls the subprogram CALCDOUBLE, and validates the output. The RETURN-CODE special register can be set before STOP RUN to indicate success or failure to the calling operating system, allowing automated test frameworks to detect failures.

Isolating Logic with Stub Programs

Sometimes, the subprogram you want to test relies on external dependencies, such as database queries. Stub programs are used to simulate missing or complex subroutines like database access during unit testing. During testing, a dummy subprogram (stub) can be used to satisfy external references and return predictable test data.

cobol โœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. GETUSER.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 USER-ID   PIC 9(4) VALUE 1001.
       01 USER-NAME PIC X(20).
       PROCEDURE DIVISION.
           CALL 'DBSTUB' USING USER-ID USER-NAME.
           DISPLAY "RETRIEVED: " USER-NAME.
           STOP RUN.
           
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DBSTUB.
       DATA DIVISION.
       LINKAGE SECTION.
       01 UID  PIC 9(4).
       01 UNAME PIC X(20).
       PROCEDURE DIVISION USING UID UNAME.
           IF UID = 1001
               MOVE "ALICE               " TO UNAME
           ELSE
               MOVE "UNKNOWN             " TO UNAME
           END-IF.
           EXIT PROGRAM.
       END PROGRAM DBSTUB.
Output
RETRIEVED: ALICE               

Data passed via LINKAGE SECTION to a stub behaves identically to data passed to the real routine. A CALL statement resolves external names at link time or run time, meaning a stub can be substituted without recompiling the caller.

Common Misconceptions

A frequent mistake is assuming that test programs must be compiled together with the main program. In reality, they can be dynamically linked at runtime. Here is an example of a simple test failing and then passing.

Predict the output cobol

Read the code. What exactly will it print? Commit to an answer before you look.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTFAIL.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NUM PIC 9 VALUE 1.
       PROCEDURE DIVISION.
           IF NUM = 2
               DISPLAY "PASS"
           ELSE
               DISPLAY "FAIL: " NUM
           END-IF.
           STOP RUN.
Output
FAIL: 1
cobol โœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTPASS.
       PROCEDURE DIVISION.
           DISPLAY "PASS"
           STOP RUN.
Output
PASS

Edge Cases

When dealing with complex test scenarios, you might encounter situations involving multiple ENTRY points or simulating abends and SQL errors.

cobol โœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTASS.
       PROCEDURE DIVISION.
           DISPLAY "ASSERT OK"
           STOP RUN.
Output
ASSERT OK
cobol โœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTMOCK.
       PROCEDURE DIVISION.
           DISPLAY "MOCK OK"
           STOP RUN.
Output
MOCK OK
Test Harness CALL Subprogram STUB CALL DB Stub
Diagram illustrating the separation between a test harness, subprogram, and stub program.

Check yourself

Can you test COBOL business logic without entering CICS screens?

Reveal answer

Yes, you can test business logic directly with batch programs. โ€” You can test business logic directly with batch programs by passing known data via the LINKAGE SECTION.

Does testing COBOL require Z-Unit or IBM Developer for z/OS?

Reveal answer

Simple unit tests can be written using standard CALL statements. โ€” Simple unit tests can be written using standard CALL statements, acting as a test harness.

How can you write isolated unit tests for COBOL programs that access a database?

Reveal answer

You can isolate logic using stub programs. โ€” You can isolate logic using stub programs that return predictable test data instead of querying a real database.

Do test programs need to be compiled together with the main program?

Reveal answer

They can be dynamically linked at runtime. โ€” They can be dynamically linked at runtime, allowing you to substitute a stub without recompiling the caller.

Challenges

Challenge 1 +15 XP

Write a test harness that tests if the 'ADDTEN' subprogram works correctly. Assert that passing 15 yields 25. If it does, display 'PASS', otherwise 'FAIL'.

cobol โœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real โ€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 โ€” expects "PASS\n"
Need a hint? (โˆ’25% XP)

CALL the subprogram with USING, then use an IF statement to check NUM-OUT.

Show solution (0 XP)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTADD.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NUM-IN  PIC 9(2) VALUE 15.
       01 NUM-OUT PIC 9(2).
       PROCEDURE DIVISION.
           CALL 'ADDTEN' USING NUM-IN NUM-OUT.
           IF NUM-OUT = 25
               DISPLAY "PASS"
           ELSE
               DISPLAY "FAIL"
           END-IF
           STOP RUN.
           
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ADDTEN.
       DATA DIVISION.
       LINKAGE SECTION.
       01 IN-VAL  PIC 9(2).
       01 OUT-VAL PIC 9(2).
       PROCEDURE DIVISION USING IN-VAL OUT-VAL.
           COMPUTE OUT-VAL = IN-VAL + 10.
           EXIT PROGRAM.
       END PROGRAM ADDTEN.

๐Ÿž Bug Hunt +15 XP

This program is supposed to display 'STUB', but it displays something else. Find and fix the bug.

This code runs. It just does the wrong thing. Read it, find the defect, fix it โ€” the tests below decide when you are right.

cobol โœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real โ€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 โ€” expects "STUB\n"
Need a hint? (โˆ’25% XP)

Check what is being displayed in the PROCEDURE DIVISION.

Show solution (0 XP)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. STUBCH.
       PROCEDURE DIVISION.
           DISPLAY "STUB"
           STOP RUN.