问题
I would like to set a few things for a few test tasks. More specifically, I would like to add a few environment variables and a few system properties, maybe a few other things such as "dependencies" or "workingDir". With the regular Test
task 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 task type MyTestType
extending the regular Test task type, where the common definition is defined.
task test1(type:MyTestType){
dependsOn testPrep1
}
task test2(type:MyTestType){
systemPropety 'newProperty','fdsjfkd'
}
What would be best way to do this? It seems that the execute()
method is final and cannot be extended. I will need to do something like the doFirst
to set those properties. Should I add all the extra values in the constructor? Is there any other hook I can use? Thanks.
回答1:
In general you can extend the 'Test' task and implement your customizations
task test1(type:MyTestType){
}
task test2(type:MyTestType){
systemProperty 'newProperty','fdsjfkd'
}
class MyTestType extends Test {
public MyTestType(){
systemProperty 'property','abs'
}
}
Alternatively you can configure all tasks of type Test
with less boilerplate:
// will apply to all tasks of type test.
// regardless the task was created before this snippet or after
tasks.withType(Test) {
systemProperty 'newProperty','fdsjfkd'
}
回答2:
you can do it the following ways
task TestExt{ Test { systemPropety 'newProperty','fdsjfkd' } }
note: this just adds to the configure method of Test source: https://docs.gradle.org/current/dsl/org.gradle.api.Task.html#N18D18
回答3:
It is also possible to specify the behavior of a particular superclass setting. Say for example you want to centralize the environment.find
block, but allow setting myLibPath
per task like this:
task test1(type: MyTestType) {
}
task test2(type: MyTestType) {
libPath = '/foo/bar'
}
You could do that by overriding the configure
method:
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 use the closure composition operator >>
to combine the passed-in closure with our overridden behavior. The user-specified configureClosure
will be run first, possibly setting the libPath
property, and then we run the environment.find
block after that. This can also be combined with soft defaults in the constructor, as in Rene Groeschke's answer
Note that this particular use case might break if you configure the task more than one, since the environment.find
statement transforms existing state instead of replacing it.
来源:https://stackoverflow.com/questions/29948381/how-to-extend-the-behavior-of-a-gradle-task-for-a-new-task-type