Justin: Interesting approach - thank you for posting that.
Lacking "callers" and C_Object, I've been using On outside call + ObjectTools + IP messaging based on the ITK message queuing system. I'm not sure if this is germane to Call form/worker but I include a "reply to ID" in the message that's sent. Most of the time, if the called code needs to reply, the reply is directed to the calling process but there are times when I've wanted the called code to pass the result to another process. My projects are just moving to 15.x now so Call worker/call form are still a bit out of reach for me but I'm glad to see that these have been added to the language. They're a natural outgrowth of OOC, Call subform container, etc., and we *finally* have a way to communicate with those windows opened in the asterisk. -- Douglas von Roeder 949-336-2902 On Fri, Mar 17, 2017 at 12:22 AM, Justin Carr via 4D_Tech < [email protected]> wrote: > OK, so it's Friday afternoon and I've got a few moments while I sup on a > cold bevvy. David & I kind of got the fervour about CALL FORM/WORKER at the > same time and this is one of the things about them that really captured our > imagination. > > We are using CALL FORM and CALL WORKER to automate unit testing of our > forms. This has been something we've been wanting to do for a very long > time but has been impossible or at the very least impractical prior to the > introduction of these two commands. > > There is very little cost to setting it up if you implement your form and > object methods as separate project methods, and if you use meaningful names > for the objects on the form. > > The beauty of this system is that the forms and their associated methods > are driven completely externally, so they need to have absolutely no extra > logic built in to handle the messaging. Furthermore, the control methods > for driving it are completely generic. The only thing that needs any > knowledge of the form interactions is the method that's describing the unit > tests. > > We have a small number of message types that can be sent to the form. > These are things like: > - set a value (could apply to any object on the form, e.g. field, button, > checkbox, listbox, etc.) > - delay for a number of ticks > - trigger a form or object event > > These messages are created as C_OBJECTs, e.g. we have a method > UT_UIMessageSetTextValue. This takes an object name and a text value as > parameters and returns a C_OBJECT representing that message. We have > methods to set different data types, trigger a form or object event, delay, > etc. We can then create a queue of these messages and send them to a worker > process for delivery to the form (window). We have a generic method to do > all of this, which takes one or more of the C_OBJECT messages, creates > another C_OBJECT containing the current process number and an OBJECT ARRAY > of the supplied messages, and then passes that object (using CALL WORKER) > to a worker process. > > So a simple example of driving a wrapper for the Request dialog might look > like this: > > > $vT_ExpectedResult:="Some Value" > UT_UIMessageQueue(\ > UT_UIMessageSetTextValue ("Response_Fld";$vT_ExpectedResult);\ > UT_UIMessageDelay (30);\ > UT_UIMessageSetLongintValue ("OK_Btn";1);\ > UT_UIMessageTriggerEvent ("DLG_RequestFM";On Clicked)) > > $vT_ActualResult:=WRAP_Request ("Enter a value") > > ASSERT($vT_ActualResult=$vT_ExpectedResult;"Unexpected response") > > > The worker process determines the correct window reference (the frontmost > window for the process contained in the C_OBJECT it receives), waits for > that window to load, and iterates through the queue of C_OBJECTS. If it's a > delay message, the delay is actually performed in the worker. If it's an > event, the form or object's project method is called using CALL FORM, > passing the event to be triggered. Otherwise the message is sent to a > "broker" method using CALL FORM which sets the requested object value. > > It sounds complicated, trying to write it all out, but the framework is > actually beautifully simple. It just consists of a handful generic methods, > none of which extends to more than about 40 lines of code: > > - UT_UIMessageSet<XXX>Value > - UT_UIMessageDelay > - UT_UIMessageTriggerEvent > - UT_UIMessageQueue > - UT_UIWorker > - UT_UIBroker > > And strictly speaking the delay capability is probably not necessary, but > it's kinda cool watching the form objects update as if by magic in front of > your eyes. > > Oh and +1 for the proposed command name changes - definitely clarifies the > functions of these two commands. > > Regards > Justin Carr > Genie Solutions > ********************************************************************** > 4D Internet Users Group (4D iNUG) > FAQ: http://lists.4d.com/faqnug.html > Archive: http://lists.4d.com/archives.html > Options: http://lists.4d.com/mailman/options/4d_tech > Unsub: mailto:[email protected] > ********************************************************************** > ********************************************************************** 4D Internet Users Group (4D iNUG) FAQ: http://lists.4d.com/faqnug.html Archive: http://lists.4d.com/archives.html Options: http://lists.4d.com/mailman/options/4d_tech Unsub: mailto:[email protected] **********************************************************************

