DEFTEST


General Form:

[PUBLIC|PRIVATE|FILE PRIVATE] DEFSUB | } 'label([[BYREF] dim_element [, [BYREF] dim_element] ...]) [[ attribute ] ...]
...
DEFTEST [DEPRECATED]
...
END TEST
END SUB

The DEFTEST statement defines a subroutine nested inside a top-level DEFSUB to act as a unit test for the DEFSUB. Because they are nested, they require a minimum $COMPLIANCE level of 1. DEFTESTs behave, in most respects, like DEFSUBs, with the following caveats:

DEFSUB 'AddNumbers(a, b)
    RETURN a + b
    
    DEFTEST
        ASSERT 'AddNumbers(1, 1) == 2, "1 + 1 does not equal 2"
    END TEST
END SUB

Running DEFTESTs

DEFTESTs can be run via the KCML workbench or using the 'KCML_Test_EnumerateDefTests internal function. Tests may be temporarily disabled by adding DEPRECATED to the DEFTEST line; these will show up as skipped when running library DEFTESTs from the workbench.

Loading and Saving

When saving a source file with DEFTESTs, the saved .src file will not contain the DEFTESTs. These will instead be saved in a corresponding .tst file - if the TESTPROGRAMS environment variable is set, this file will go to the corresponding path in PROGRAMS (so saving a file in $PROGRAMS/library/code.src would also create $TESTPROGRAMS/library/code.tst). If $TESTPROGRAMS is unset, the .tst file will be saved in the same directory as the .src file. A .code.mrg (note the leading dot) containing the combined contents will also be saved next to the .src file; this can be used to recover code in the event of errors.

When loading a source file in the new ASCII format, this process is reversed, and the DEFTESTs are restored.

Pre- and post-test hooks

If a group of tests all require the same initialization and cleanup code - for example, setting up a database table with test input - the common code can be put into one DEFSUB in the file and registered with 'KCML_Hook_SetCallbacks. The post-hook will be called even if the test fails.

For example, with the program:

$COMPLIANCE 3

'ReadyDefTests()

DEFSUB 'ReadyDefTests()
    LOCAL DIM callbacks$_KCML_Hook
    FLD(callbacks$.KCML_Hook_PreDefTest) = SYM('PreDefTest)
    FLD(callbacks$.KCML_Hook_PostDefTest) = SYM('PostDefTest)
    FLD($OPTIONS RUN.OPTIONS_RUN_Asserts) = _KCML_ASSERT_TEST
    'KCML_Hook_SetCallbacks(BYREF callbacks$)
END SUB

DEFSUB 'PreDefTest(info$_KCML_Test_DefTestInfo)
    PRINT $PRINTF("Entering test: %s", FLD(info$.KCML_Test_DefTestInfo_Name$))
END SUB

DEFSUB 'PostDefTest(info$_KCML_Test_DefTestInfo)
    PRINT $PRINTF("Exiting test: %s", FLD(info$.KCML_Test_DefTestInfo_Name$))
END SUB

DEFSUB 'HelloWorldString$()
    RETURN "hello world"
    DEFTEST
        LOCAL DIM result$
        result$ = 'HelloWorldString$()
        PRINT "Testing"
        ASSERT result$ == "hello world", $PRINTF("Returning incorrect string %s", result$)
    END TEST
END SUB

running the rest will give the output:

Entering test: 'HelloWorldString$
Testing
Exiting test: 'HelloWorldString$

Compatibility

DEFTEST was introduced in KCML 7.08. DEFTEST DEPRECATED was introduced in KCML 7.10.

See also:

DEFTESTSECTION, DEFSUB, LOCAL DIM, PANIC, ASSERT, THROW