Testing the Macro
Writing a macro, or any computer language program or script, is not just writing code and figuring out algorithms. It is testing. No matter how elegant the coding or ingenuous the concept, if the macro does not run then it is not of any value.
Verifying that a macro works is called testing. Fixing any problems in the macro, found during testing, is called debugging.
Testing and Debugging are huge topics; many whole books have been written on just a few aspects of each. As such, the goal here is simply to give the reader an idea of the types of items to consider while testing and some simple tips on how to resolve certain issues.
Testing
The first and most simple test for a macro is: Does it compile? If the macro is getting unaccounted for errors or warnings, when using the Check Macro button on the Macro Execute panel or when trying to simply run the macro, then it needs to be debugged. It is not finished.
The sorts of problems reported this way are called Syntactic errors. They represent
an incorrect language syntax. These errors are usually typographical errors, incorrect function or
command parameters, incorrect variable declarations, or missing END
blocks (ENDIF, ENDW).
Once the syntax issues are resolved, the next level is semantic errors or logical errors. This is where the macro script is properly constructed, but the results are not correct. These issues are due to incorrect algorithms - as mentioned before the computer does exactly what you tell it to do ... not what you want it to do.
Testing for semantic problems is a case of running multiple permutations. First, when the macro was being designed, some issues to be aware of were covered in the pseudocode. These issues need to be tested first.
For the example macro in this tutorial, these cases were: Process Model with no Data, and Read-only Output file. In the first case, run the macro after using File - New. This should trigger the appropriate error message and exit the macro.
In the second case, enter an invalid path for the #OUTFILE
. Then run the macro and see if the
expected error message is displayed. There are other cases that can trigger this as well, such as an existing
file, an existing file that is read-only, invalid path but good filename, valid path but invalid filename, etc.
During testing the idea is to think of the weird and unexpected issues that might be run across and make sure they are addressed.
Again, relating back to the macro in this tutorial, some of the issues that need to be tested include: process models with only layer geometry, process models with only Step geometry, process models with both step and layer geometry, models with one step, models with two or more steps, models where all the step geometry is sequential (Step 1, then Step 2 with no intermixing), models where the step geometry is mixed together (step 1, then step 2, then more step 1, then more step 2, etc). Even a case where the model has only a single element - one test where the element is a step and one where it is a layer.
An important term to learn is "Branch Testing." Branching was explained in the Fundamentals section of this tutorial. When testing, it is important to test both conditions on a branch. For example:
IF (#I > 0)
do something
ELSE
do something
ENDIF
Testing needs to check what happens with #I
is greater than zero as well as when it is
less than or equal to zero. The IF/ENDIF
is a branch statement and branch testing is making
sure each conditional branch is checked.
Debugging
Debugging is closely related to testing. Testing finds problems, debugging fixes them.
One popular technique is called tracing. Similar in idea to tracing a phone call, the goal is to follow a piece of data through the entire macro. At various points along the path, check and see what the traced variable contains and compare the traced value against a calculated value. The calculated value being the value the programmer thinks it should be based on how they think the macro is supposed to work.
The PAUSE[]
command is commonly used in tracing. Simply insert PAUSE[] commands at
appropriate locations within the macro to check the value of variables.
PAUSE[]
is also used to chart the general flow of a macro. For example:
PAUSE[TX="Starting WHILE Loop"]
WHILE(#COUNTER < #MAXVALUE)
PAUSE[TX="Inside WHILE Loop: COUNTER is [" + FMT(#COUNTER, "T3.0")]
... other macro commands
ENDW
PAUSE[TX="Outside of WHILE Loop. COUNTER ended up being [" + FMT(#COUNTER, "T3.0")]
If the above fragment were a complete macro, running it would show when the loop was entered, the value of the counter as it moves through the loop, and when the loop is exited. As well as the value of the counter when the loop exits. These sorts of status messages allow the programmer to track the progress of the macro and the value of variables.
Often times, especially when working with large complex macros or macros that take awhile to run to
completion, it is helpful to stop macro execution at certain spots. This is easily handled with the
HALT
macro command.
The HALT
command ends the running macro. It takes no parameters and differs from other
macro commands and functions in that it does not include the "[]
" or "()
"
parameter brackets.
// Do check one
... MCL for check one
// Do check two
... MCL for check two
Imagine the "check two" takes a long time to process, so when debugging "check one" you would not want the macro to continue on and run the code for "check two." In this instance, make the following change.
// Do check one
... MCL for check one
HALT
// Do check two
... MCL for check two
Now, as soon as "check one" is complete, the HALT
command it run and the macro ends.
Performance
SmartCAM's macro system incorporates an interesting performance feature. SmartCAM supports an UNDO/REDO system that is really only limited by available system resources. However, the ability to walk an UNDO tree back to the very first modification to a process model, incurs some performance overhead.
While the performance of the UNDO system is very fast, it is not instantaneous. And if your macro includes a number of looping operations which create or modify the process model, the UNDO system will be called a large number of times, and the slight performance requirements for the UNDO system will accumulate, adding execution time when the macro is run.
To handle this, when SmartCAM compiles a macro it checks for UNDO related macro commands: UNDO[]
,
UNDO_MULTI[]
, and REDO_MULTI[]
. If none of these macro commands are in the compiled macro,
the UNDO system is disabled while the macro is running. This allows the macro to loop and modify the process model
without incurring the additional time needed to manage the UNDO transaction database. If any UNDO related macro
statement is in the compiled macro, the UNDO system is left running - so that the macro statements will work.
When the macro is complete, the UNDO system is re-enabled and an UNDO transaction is created. This transaction allows the users of the macro to UNDO and REDO the effects of the macro as a whole.
A well written macro will not include any UNDO related macro commands. The macro should track all its own changes and add/remove them as needed on its own - it does not need and should not use the UNDO commands.
Related Topics