What is a Closure? A Groovy closure is like a "code block" or a method
pointer. It is a piece of code that is defined and then executed at a
later point. The main feature of Closures is that it "bound" to
variables within the scope where they are defined. For more details,
please see
http://groovy.codehaus.org/Closures
Tellurium uses Groovy Closure pretty heavily. For example, in the
DslContext class, you may see methods similar to the following click
method,
def click(String uid){
WorkflowContext context = WorkflowContext.getDefaultContext()
ui.walkTo(context, uid)?.click(){ loc, String[] events ->
String locator = locatorMapping(context, loc)
eventHandler.click(locator, events)
}
}
and in the Button object, you have the method
def click(Closure c) {
c(locator, respondToEvents)
}
You may got confused at the first sight. Let us elaborate more on it.
First we can clearly define the closure as
Closure c = { loc, String[] events ->
String locator = locatorMapping(context, loc)
eventHandler.click(locator, events)
}
Note, the block of code "c" will carry the variables "context",
eventHandler, and method locatorMapping in DslContext class to other
classes where the closure is executed, for example, the Button class.
Also, be aware that the Closure "c" needs input parameters "loc" and
"events", which should be provided by the class that executes the
Closure.
With that, we can write the method more clearly as
def click(String uid){
WorkflowContext context = WorkflowContext.getDefaultContext()
Closure c = { loc, String[] events ->
String locator = locatorMapping(context, loc)
eventHandler.click(locator, events)
}
UiObject object = ui.walkTo(context, uid)
if(object != null)
object.click(c)
}
Here assume the object is Button, then the click method in Button is
called, which is equals to
def click(Closure c) {
loc = this.locator
String[] events = this.respondToEvents
String locator = locatorMapping(context, loc)
eventHandler.click(locator, events)
}
As you see, the actual call flow is as follows,
call click(uid) in DslContext
|
find the Button object by calling the "walkTo" method
|
call click(Closure c) in Button
|
call locatorMapping() method in DslContext to get runtime
locator
|
call click(locator, events) in eventHandler
You may be surprised to see that the Closure c in the Button object
can
access variables and methods defined in DslContext class, i.e, where
the Closure c
is defined. That is a feature of Closure.
The benefit of this is that we have a center place DslContext to deal
with locator processing and
event handling. Otherwise, you have to scatter the same things in each
Ui object,
which is really not elegant.
Hope this can help you understand the framework better.
Thanks,
Jian