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


Reply via email to