Gaelyk Remote Control
This project is a Gaelyk-compatible version of Groovy Remote Control. It's main usage is to setup a Gaelyk application for functional tests by allowing to execute closures defined in tests on the server. See groovy-remote project pages for general usage and examples not specific to Gaelyk.
Setup
To use the library in your Gaelyk project you first need to add the dependency in your Gradle build file:
repositories {
mavenCentral()
}
dependencies {
runtime "org.gaelyk:gaelyk-remote:0.1"
}
The library provides a servlet that should be used as the endpoint for sending the code to be executed. All you need to do is to register this servlet in web.xml
file of your project typically at the /remote-control
path:
<servlet>
<servlet-name>RemoteControlServlet</servlet-name>
<servlet-class>groovyx.gaelyk.remote.RemoteControlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RemoteControlServlet</servlet-name>
<url-pattern>/remote-control</url-pattern>
</servlet-mapping>
Usage
Given that you've registered groovyx.gaelyk.remote.RemoteControlServlet
at /remote-control
and you run your development server on port 8080
for functional tests the following specification should pass:
import groovyx.remote.client.RemoteControl
import groovyx.remote.transport.http.HttpTransport
import spock.lang.Specification
class RemoteControlSpec extends Specification {
private remote(Closure closure) {
new RemoteControl(new HttpTransport('http://localhost:8080/remote-control')).exec(closure)
}
void "smoke test"() {
expect:
remote { 1 + 1 } == 2
}
}
Gaelyk specific variables in remote context
To make it easier to setup your application for your tests closures passing through groovyx.gaelyk.remote.RemoteControlServlet
get all the GAE-specific variables from this list bound into their context. Thanks to that you can use the same property names to access the variables that are also available in your Gaelyk views and controllers. The only non GAE-specific variable added to the context of the remotely executed closures is context
which points to the ServletContext
instance for the application.
The following example shows how easy it is to clear the datastore after each fixture in a specification thanks to the availability of datastore
variable in the remote closure context.
import groovyx.remote.client.RemoteControl
import groovyx.remote.transport.http.HttpTransport
import spock.lang.Specification
class RemoteControlSpec extends Specification {
@Shared def remote = new RemoteControl(new HttpTransport("http://localhost:8080/remote-control"))
def cleanup() {
remote.exec { datastore.iterate { select keys }.each { it.key.delete() } }
}
}
Security
A posibility to run arbitrary code on server is an obvious security risk. The library is aimed at being used during functional testing and that's why groovyx.gaelyk.remote.RemoteControlServlet
checks if the application is running in development enviroment (SystemProperty.environment.value() == SystemProperty.Environment.Value.Development
) and if that isn't the case always returns HTPP 404
error code and the remote closure is not executed.