Question

What is the best way of implementing assertions using Progress 4GL or WebSpeed?

Was it helpful?

Solution

After some consideration here is my solution to the problem. It works based on the assumption that development environment propath is different from test and production environments and code is always re-compiled for test or production use:

&IF PROPATH MATCHES '*development*' &THEN 
&SCOPED-DEFINE ASSERTION   {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} ~
{11} {12} {13} {14} {15} {16} {17} {18} {19} {20} ~
{21} {22} {23} {24} {25} {26} {27} {28} {29} {30} ~
{31} {32} {33} {34} {35} {36} {37} {38} {39} {40} ~
{41} {42} {43} {44} {45} {46} {47} {48} {49} {50} ~
{51} {52} {53} {54} {55} {56} {57} {58} {59} {60} ~
{61} {62} {63} {64} {65} {66} {67} {68} {69} {70} ~
{71} {72} {73} {74} {75} {76} {77} {78} {79} {80} 


 IF NOT ({&ASSERTION}) THEN 
     MESSAGE "Failed assertion {&ASSERTION} in" PROGRAM-NAME(1).

 IF ({&ASSERTION}) = ? THEN 
     MESSAGE "Unknown value as a result of assertion {&ASSERTION} in" 
              PROGRAM-NAME(1).

&ENDIF

The code is designed to avoid any side effects and works equally well in any execution environment (GUI or ChUI, WebSpeed, AppServer, batch and so on).

1) Save the code as a file called “assert” (without any extension).

2) Place the file into a directory pointed to by PROPATH.

3) Sample usage:

{assert valid-handle(hProc)}
{assert i > 0 and i <= 100}
{assert cExtra begins ‘opt’}  /* note the single quotes */
{assert dtEnd > = dtStart}

As a variation it’s possible to avoid relying on propath altogether by having just an empty include file in test and production environment, the development version will become just:

&SCOPED-DEFINE ASSERTION   {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} ~
{11} {12} {13} {14} {15} {16} {17} {18} {19} {20} ~
{21} {22} {23} {24} {25} {26} {27} {28} {29} {30} ~
{31} {32} {33} {34} {35} {36} {37} {38} {39} {40} ~
{41} {42} {43} {44} {45} {46} {47} {48} {49} {50} ~
{51} {52} {53} {54} {55} {56} {57} {58} {59} {60} ~
{61} {62} {63} {64} {65} {66} {67} {68} {69} {70} ~
{71} {72} {73} {74} {75} {76} {77} {78} {79} {80} 


 IF NOT ({&ASSERTION}) THEN 
     MESSAGE "Failed assertion {&ASSERTION} in" PROGRAM-NAME(1).

 IF ({&ASSERTION}) = ? THEN 
     MESSAGE "Unknown value as a result of assertion {&ASSERTION} in" 
              PROGRAM-NAME(1).

An extra tip is to add an auto-text macro to your editor of choice that will automatically expand into {assert }.

OTHER TIPS

Since Progress doesn't have native handling for assertions, but best I've come up with is:

IF NOT <assertion> THEN
RUN assertionFailed.p.

assertionFailed.p can email the programmer, or log the conditions and also exit gracefully.

Given that assertions are generally omitted from the final code I'd suggest the preprocessor route. You might do something like the following set it up as two include files. When you are compiling it to production ensure that the debugalert.i is empty. assert.i could be edited to do whatever you like message, stop, email etc...

To setup an assertion you would just follow the format {assert.i &condition=}


/* assert.i */ {debugalert.i}

&IF DEFINED( DEBUGALERT ) <> 0 &THEN

IF NOT {&CONDITION} THEN DO:

MESSAGE THIS-PROCEDURE:FILENAME "ERROR...{&CONDITION}" 
    VIEW-AS ALERT-BOX.
/* add code to email message etc.. or stop */

END.

&ENDIF


/* debugalert.i on test or development environments to turn off the assertions remove this statement */

&GLOBAL-DEFINE DEBUGALERT


/* In your test code you would just do the following: / / testing assertion */

DEF VAR h_ct AS INT NO-UNDO INIT 10.

{assert.i &CONDITION="h_ct = 8"}

OpenEdge 11.6 introduced Unit Testing to the world of ABL. It's loosely based on JUnit principals. Assertions are therefore now part of the package. More info is in the documentation: https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/pdsoe/overview-of-ablunit-testing-framework.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top