Hans Dockter wrote:
I would like to start discussing how to integrate reports into Gradle.
I see two kind of reports:
1.) Reports which belong to the domain of a certain task and possibly
depend on the execution of this task. For example junit reports and
cobertura or emma are related to the test task.
Some things I'd like to be able to do with these kinds of reports:
Generally, these reports really only depend on the output of the task,
rather than the execution as such. For example, I can run the junit
report if I have some test result xml files, regardless of how they got
there (they may have been generated in a previous build, or maybe run on
a bunch of different machines, etc). Ditto the cobertura and emma
reports. So, sometimes I'd like to be able to run the reports without
running the associated task.
In the case of reporting on tests, I'd like to be able to replace how
the testing actually gets run, but leave all the reporting in place. The
'how to run the tests' and the 'what to do with the results' should be
fairly independent things.
For test coverage reports, for a given build, I only want to use one out
of the available ones at any given time, so I'd like to have a simple
way to choose which one (if any). When a coverage report is to be
included in the build, it needs to instrument the classes to be used for
testing, and so the report (or something) is going to need a way to
modify the inputs to the test task.
For these kind of reports, I'd like the report to be generated whenever
the associated task is included in the build, and to be generated
regardless of whether the task succeeds or fails, or any of the other
reports succeed or fail.
Finally, I'd want to be able to decorate the tests with my own reports.
2.) Reports which do not belong to a certain task. For example
checkstyle.
Would a report that summaries the build fit into this category? For
example, a report which summaries all the reports for the build. Or a
report which summaries the timing for each task. I'd like to be able to
add a report like this, and have it be generated whenever the build does
a certain type of thing (generates a report, runs a task, etc)
How to implement 1.):
a.)For any test related report task the test task may provide 2
properties. For example enableJunitReport and junitReport. The first
is a boolean, the second is an instance of the JUnitReport task. But
this instance has not been added to the project tasks yet. The test
task registers a project.addAfterEvaluateListener(). This listener
checks the value of for example enableJunitReports. If it is true, it
adds its JUnitReport task instance to the project task.
b.) An alternative implementation would be to for the test task, to
just provide one property, the JUnitReport task. This task is directly
added to the project tasks. If a user does not want it, it can be
disabled, via setting the enabled property any task has to false. The
disadvantage of this approach is, that the JUnitReport task is added
to the task execution graph and makes it bigger and harder to read
(e.g. by using gradle -t) without any purpose. Setting enabled to
false just prevents that any action gets executed. It is the same as
setting a skip property.
c.) Another option is do things as in b.) but to change the behavior
of the 'enabled' property of tasks. If a task is not enabled, it is
not added to the task execution graph. If another task has a dependsOn
relation to a disabled task an exception is thrown. An possibly
alternative to an exception would be not to add the dependsOn task as
well.
I don't think that the Test task should know about which reports could
be generated from its output. Instead, I think we should go with
independent reusable chunks of behaviour as Tasks, let the plugins
provide the domain model and do the wiring, with some stuff in the core
to let us express the things we need.
So, I think we should, for the short term:
- Implement each report as a Task. We should also add a Report
interface to provide some generic config and meta-info.
- Split a JunitReport task out of the Test task
- Add a way to declare that a task must be included in the execution
graph if a given other task (or matching set of tasks) is included in
the execution graph.
- Use the enabled flag and/or skip properties to include/exclude the report.
- Change the java plugin to always add the junitReport and a coverage
task (we just pick one of coberatura or emma)
- Add the jars required for the above tasks to gradle home lib directory.
There'd still be some things to tidy-up, but we can figure that out later:
- Better ways of including/excluding reports. This isn't a problem
specific to reports - any sizable build has tasks that are wired up for
a 'full' build, but which are optional in some cases (eg the docs and
tests when running gradle's 'install' task)
- Better ways of bundling/downloading/locating the dependencies for the
reports. Again, this isn't specific to reports - each plugin and group
of tasks is going to need a number of dependencies which we don't want
to include in the core distribution.
How to implement 2.):
We could provide a reports tasks which bundles all independent reports.
This is a good idea.
Adam
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email