Runner plus…: A hybrid approach
Just as a combination of testing techniques will net you a higher bug count, I feel a combination of automated testing techniques can help you cover all the bases.
I've written a VFP autorunning object I call " Runner" , which you can add to VFP applications or the VFP environment quite easily. Runner has both autotesting and self-running demo applications. It is a " smart" timer object, which works by scanning through a DBF of script actions that you prepare. For each type of action (and Runner's scripting action types encompass most of what you can do in VFP), Runner disables itself until the action completes and then re-enables to execute its next script action.
Allowable Runner script actions run the gamut from mouse-handling through execution of entire programs you indicate. Runner understands the grouping of actions into something I call " phases" , and you can designate phases, or single action records, to be repeated as required. Special provisions are made for logging, both of errors encountered or of messages you designate as the script progresses. I'd also suggest you think about running some of Steven Black's state-snapshot-dumping methods via a Runner action at various points in your script.
In view of Runner's timer implementation, the most problematic actions are actions that return to Runner before the action completes. These actions include both native PLAY MACRO statements and actions that run an external Macro or scripting facility.
Briefly, you need to provide Runner with some help to wait until extensive macros complete, whether they're external or internal. I've got a few suggestions for you that will help. (You can actually see one of the suggestions under construction in the figure showing MacroScheduler above. See RUNNER.TXT in the \RUNNER folder for more information.) Although these suggestions work, it's also best to set your Runner Interval high enough to allow for these actions to " proceed naturally" if possible. You can even temporarily adjust Runner's Interval just before and after any macro-running script action.
I've made provisions to integrate Macro Scheduler into the Runner set of allowable action types. I think that this hybrid approach allows me to handle OLE objects, mouse menu objects, and other " tricky" actions with the greatest flexibility, while still allowing me VFP's full range of abilities in other respects. I would like to integrate other external tools into Runner scenarios as well.
There is very little else you have to know, to use Runner. I've prepared a demo application (in the \DEMORUN folder) with a demo Runner script table, so you can see how Runner works. Since the addition of a Runner object is really the only change I've made to a generated VFP 6 Framework app for this demo, I haven't bothered giving you the source. You'll only find the APP, its data, the Runner script table, and a macro file the Runner script loads.
There is no necessary connection between Runner and the framework used to create this demo application. Still, the small additions to the app_application object in this project will give you some extra help on integration of a Runner object into any type of application. Here are all the changes I made to the generated app_applicatio
n object in the demo framework project:
LPARAMETERS nerror,cmethod,nline IF nError # 1540 * I know there is going to be an error of * this type on the way out, and in * this context the error is meaningless THIS.Parent.Error(nerror,cmethod,nline) DODEFAULT(nerror,cmethod,nline) ENDIF
LPARAMETERS nerror,cmethod,nline DODEFAULT(nerror,cmethod,nline) THIS.cusRunner.lError = .T.
RETURN THIS.iAutoRunInterval > 0 ; AND VARTYPE(THIS.cRunnerDBF) = " C" AND ; (FILE(THIS.cRunnerDBF) OR ; FILE(THIS.cRunnerDBF+" .DBF" ))
LOCAL llReturn llReturn = DODEFAULT() IF llReturn AND THIS.lInAutoRunMode THIS.cusError.lServer = .T. * the above is a convenient way * to make sure that the app * keeps running after logging app errors -- not strictly * necessary but it helps make sure that * Runner goes on to the next phase smoothly if * an error occurs in the app. * I've also augmented the Error * event of this app's Runner member to call * the app's error method, so that error logging occurs * even if a Runner method causes the error. * The lServer mode of the cusError object will * make sure we don't get " stuck" in error dialogs if * this happens. WITH THIS.cusRunner * here you could make an evaluation -- * is this an autotest (set the interval fairly * low) or is it a Demo run (set it higher, * so people can see what's going on) .cTable = THIS.cRunnerDBF .Interval = THIS.iAutoRunInterval .StartRun() ENDWITH ENDIF RETURN THIS.IsErrorFree() AND llReturn
IF THIS.lInAutoRunMode THIS.lStartupForm = .F. * It just seems like a reasonable thing * to do! ENDIF RETURN DODEFAULT()
As a general rule, integration of Runner with your application -- however your application is organized --consists of these factors, consistent with the changes I've just listed:
In the DEMORUN example script table, an error is deliberately caused so that you can see how Runner exits an error-causing phase and attempts to continue on with the rest of its script. After the error, part of the script shows off some of the framework's capabilities, by bringing forward the error log viewer and dynamically changing its font using the options dialog.
Watch your VFP status bar at the end of the Demorun. If you have the status bar on, you should see Runner continuing to go through some additional records before it finally finishes. Afterwards you can examine its *.RUN log, to see what happened.
During the run, WAIT WINDOWs also show up to describe what's going on - these are INFO instructions in the demo script itself. Runner's INFO action type, which creates these WAIT WINDOWs, is very useful for both testing and demo purposes.
The hard part of using Runner is not its simple API. You'll find this documented in RUNNER.TXT. (Runner is very much a work-in-progress, and RUNNER.TXT is " it" for the moment, and it's not pretty. But it is thorough!)
The hard part of properly testing with Runner is the same as it is for any automated testing: you have to devise appropriate testing scenarios and then write the scripts to automate these procedures.
FRONTRUN.SCX (Front Runner) is a tool to help you write Runner scripts.
For this reason, I'm delivering a simple front end to Runner script writing, which I call Front Runner. If you DO FORM FRONTRUN (in the \RUNNER folder), you'll find that it examines and creates Runner scripts without much validation for your " script action" entries but with a table-driven approach to allowable action types, and information on each type available. In the figure above , you can see the DEMORUN\DEMORUN.DBF script table under edit.
You'll need more help…
Well, it's a start.
This article and the tools represented herein are only a beginning. COVERAGE.APP facilities in VFP 6 are a big help, but as you've already seen you'll need to interpret and use the results before your applications will benefit.
Luckily, as I hope you've also already seen, VFP is such a brilliant environment in which to write tools, and in which to analyze results, that you are a leg up on the competition before you begin!
It can truly be said that testing is not quality assurance. Use of what you learn from tests, deployment of testing information accurately and with constructive care, results in quality.
When used properly, testing becomes an important part of a full quality-assurance process. You'll need a practical plan to encourage testing, and testers, in your organization. I've enjoyed writing these notes to give you some ideas.
Be sure to drop by http://www.softspoken.co.nz/lisa_fox.htm, or write a message on the msnews.microsoft.com public fox groups, to share more ideas with me and with the Fox community.