How can I extend the behavior of a Gradle issue for a new issue type?
I would like to ask several things for several test problems. Specifically, I would like to add a few environment variables and a few system properties, perhaps a few other things like "dependencies" or "worker". With an ordinary task, Test
I can do this,
task test1(type:Test, dependsOn:[testPrep,testPrep1]){
workingDir testWorkingPath
systemProperty 'property','abs'
environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + myLibPath)
environment.LD_LIBRARY_PATH = "/usr/lib64:/lib64:${myLibPath}:" + environment.LD_LIBRARY_PATH
}
task test2(type:Test, dependsOn:[testPrep]){
workingDir testWorkingPath
systemProperty 'property','abs'
environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + myLibPath)
environment.LD_LIBRARY_PATH = "/usr/lib64:/lib64:${myLibPath}:" + environment.LD_LIBRARY_PATH
systemPropety 'newProperty','fdsjfkd'
}
It would be nice to have a new problem type MyTestType
that extends the usual test problem type where a common definition is defined.
task test1(type:MyTestType){
dependsOn testPrep1
}
task test2(type:MyTestType){
systemPropety 'newProperty','fdsjfkd'
}
What would be the best way to do this? It looks like the method execute()
is final and cannot be extended. I will need to do something like doFirst
to set these properties. Should I add any additional values โโto the constructor? Is there any other hook I can use? Thank you.
source to share
In general, you can extend the "Test" task and implement your own settings
task test1(type:MyTestType){
}
task test2(type:MyTestType){
systemProperty 'newProperty','fdsjfkd'
}
class MyTestType extends Test {
public MyTestType(){
systemProperty 'property','abs'
}
}
Alternatively, you can set up all type tasks Test
with fewer templates:
// will apply to all tasks of type test.
// regardless the task was created before this snippet or after
tasks.withType(Test) {
systemProperty 'newProperty','fdsjfkd'
}
source to share
You can also specify the behavior of a specific parameter of the superclass. Let's say for example you want to centralize a block environment.find
, but allow customization myLibPath
for each task like this:
task test1(type: MyTestType) {
}
task test2(type: MyTestType) {
libPath = '/foo/bar'
}
You can do this by overriding the method configure
:
class MyTestType {
@Input def String libPath
@Override
public Task configure(Closure configureClosure) {
return super.configure(configureClosure >> {
environment.find { it.key ==~ /(?i)PATH/ }.value += (System.properties['path.separator'] + (libPath ?: myLibPath))
})
}
}
Here we are using the close operator < to combine a closed connection with our overridden behavior. The custom one configureClosure
will be launched first, perhaps by setting a property libPath
, and then running the block environment.find
. This can also be combined with soft defaults in the constructor, as in Rene Grรถschke's answer
Note that this particular use case might break if you configure more than one task, as the statement environment.find
transforms the existing state instead of replacing it.
source to share