We are evaluating the impact of a Gradle 5 upgrade in our plugin suite and projects. Our plugins have a lot of tests, many of them written with ProjectBuilder. Just an example:
@Test
public void test() throws Exception {
// create ProjectBuilder instance
// create the sutTask object (extends AbstractTask) on the ProjectBuilder instance (or apply a plugin which creates it)
sutTask.execute(); // compilation error in Gradle 5.0
assertEquals(TaskExecutionOutcome.EXECUTED, sutTask.getState().getOutcome());
// check output, e.g., files
}
Is there any way to fix our tests without having to migrate to Gradle TestKit? Currently we have 200+ compilation errors - it would be nice if we could replace all if them with one helper method call.
So, to cut it short, how can we execute tasks in tests with Gradle 5.0 ProjectBuilder? It is not a problem, if we have to build a task graph and build a problem, but could you please give us pointers how to do it?
Regards,
Lajos
PS: We use ProjectBuilder in many cases over Gradle TestKit mainly because it is sufficent to test one task. It is much easier to write many tests in this way. I would like to emphasise that we are only using execute() in tests, not in plugin implementation. Many of our tests test task customisation, e.g., calls the customized Jar task.
while there is a way to still execute the tasks with ProjectBuilder using quite a lot of internal APIs, I wonder why you just don’t call the task action? Do you use ProjectBuilder tests for checking up-to-date as well?
It is not a big issue to use internal APIs (we already do it in a few places). For now, we would like to see an impact of a possible upgrade, which means that we need to make all tests and builds pass first (even with hacky solutions).
Calling the @TaskAction is not always easy - for example, for the Jar -> Zip -> AbstractArchive task it is a protected method. However, my plan B is that we write our little reflection code which detects the @TaskAction and calls it (we use the execute() method in too many places and for several task types).
UP-TO-DATE and task caching is tested with TestKit.
To a talk little about the meta level: what is the current purpose of ProjectBuilder? Will it stay or do you plan to remove it? Anyway, if we need to make a bigger investment when we do the real upgrade (e.g., refactor/rewrite tests), then we would like to go for the most future proof solution.
ProjectBuilder will not go away. It is there to unit-test tasks and plugins. So you can create a task, configure it and call some methods on it, etc… You can also apply your plugins to a project and then do some assertions on the state. It becomes more difficult when you actually want to run things, like when calling the former execute method. Then a TestKit bet is better suited.
Why would you want to call the task action of a built-in task like Jar? If you want to create a Jar for your test you probably should use something else. If you want to copy things around, use Project.copy. I would love to know what your use-case is.
Sorry for the delayed answer. In the end, I have replaced all the usages to execute() in tests for the custom tasks.
We also had a special variant of a Jar task - basically we extended Jar, to create the special distribution - so to keep our ProjectBuilder tests for this tasks, we should have called the protected AbstractCopyTask.copy() method. However, in the end we removed this feature completely, since it was a compatbility feature with an old build tool we used years ago.
Thanks again for the tip, I used it in the meantime and it boosted our ongoing Gradle 5 evaluation process.