On Aug 30, 2008, at 7:10 AM, Adam Murdoch wrote:
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.
Agreed.
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)
I'd say it fits into this category. Anyway, it is good idea for a
report.
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.
I agree.
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.
Here is how I understand this requirement:
With the current dependsOn declaration we can only define
prerequisites of a task. Something I have always liked were the
postGoal's of Maven 1. We could offer a method to a task like
'postRequisite' which takes tasks as an argument. This tasks need to
be executed after the source task has been executed. The question is
how to fit this into a directed acyclic graph. My rough idea is to
create dependsOn relations from the postRequisite tasks to the source
task. If the build is started with: 'gradle sourceTask' we need to
translate this into an execution of the postRequisite tasks. If a
task has postRequisite its name is rather an alias for the
postRequisite tasks.
- 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)
With the above terminology junitReport and coverage would be
postRequisites of the test task, right? (I don't think that
postRequisite is a very good name, but for now I don't know anything
better).
- 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.
This is important as we have discussed in another thread.
How to implement 2.):
We could provide a reports tasks which bundles all independent
reports.
This is a good idea.
We might change this to: 'which bundles all reports'.
- Hans
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email