Kotlin / kotlinx-kover

Apache License 2.0
1.25k stars 46 forks source link

Create tasks for custom Gradle tasks to generate reports from binary reports #588

Open shanshin opened 1 month ago

shanshin commented 1 month ago

What is your use-case and why do you need this feature? If the testing does not take place in one build run, but is distributed over several builds, for example, at different CI steps.

In this case, it is necessary to generate a binary report in each shard, and later generate a report from them: XML, HTML or verification.

Now user may use:

However, this is inconvenient for use in Gradle, because it does not into the concept of runnable Gradle tasks.

In this case, users need to write their own tasks, set up input and output properties in them, which takes some time and is not very obvious to a person who is not familiar with Gradle.

Describe the solution you'd like Create a set of users tasks to generate report from evaluated earlier binary reports.

public abstract class KoverUserHtmlReport {
    filters(config: Action<KoverReportFiltersConfig>)

    val binaryReports: ListProperty<RegularFile>
    val charset: Property<String>
    val title: Property<String>
    val sourceRoots: ListProperty<Directory>

    val htmlDir: DirectoryProperty
}

public abstract class KoverUserXmlReport {
    filters(config: Action<KoverReportFiltersConfig>)

    val binaryReports: ListProperty<RegularFile>
    val title: Property<String>

    val xmlFile: RegularFileProperty
}

public abstract class KoverUserVerifyReport {
    filters(config: Action<KoverReportFiltersConfig>)
    verify(config: Action<KoverVerificationRulesConfig>)

    val binaryReports: ListProperty<RegularFile>
}

*Manually specifying the root directories with source files is inconvenient, but in the first iteration we can leave it like this, because it is not very clear how to do it better: users need to include all source files, including all Android build variants, or how

mgroth0 commented 1 month ago

I think this is related to https://github.com/Kotlin/kotlinx-kover/issues/443

In my workaround for that, I am currently configuring the koverHtmlReport in a somewhat hack way:

    tasks.withType<KoverHtmlReport>().configureEach {
        val reportDir = layout.buildDirectory.asFile.get().resolve("reports").resolve("kover")
        val htmlReportDir =
            reportDir.resolve(
                when (name) {
                    "koverHtmlReport" -> "html"
                    "koverHtmlReportJvm" -> "htmlJvm"
                    "koverHtmlReportDebug" -> "htmlDebug"
                    "koverHtmlReportRelease" -> "htmlRelease"
                    else -> error("What is the kover html report name for $name?")
                }
            )
        val cssDir = htmlReportDir.resolve("css")
        val coverageCss = cssDir.resolve("coverage.css")
        val ideaMinCss = cssDir.resolve("idea.min.css")
        doLast {
            // here I make rough edits to the CSS files to invert some of the colors
        }
    }

This workaround is sufficient for me to be able to look at the HTML reports without my eyes hurting.

The reason I wanted to bring this up here is to suggest that exposing the report directory for each kover report task could be a nice feature.

Then I could completely eliminate this part:

   tasks.withType<KoverHtmlReport>().configureEach {
        val reportDir = layout.buildDirectory.asFile.get().resolve("reports").resolve("kover")
        val htmlReportDir =
            reportDir.resolve(
                when (name) {
                    "koverHtmlReport" -> "html"
                    "koverHtmlReportJvm" -> "htmlJvm"
                    "koverHtmlReportDebug" -> "htmlDebug"
                    "koverHtmlReportRelease" -> "htmlRelease"
                    else -> error("What is the kover html report name for $name?")
                }
            )

Of course, I could also possibly just simplify my workaround like:

val htmlReportDir = reportDir.resolve("html" + name.substringAfter("koverHtmlReport"))

But in any case, this still requires me as the user to implement some logic related to the variant names.

Also, of course https://github.com/Kotlin/kotlinx-kover/issues/587 would also help with this. But then, still, I need to know to look inside the "reports/kover" directory and I need to know the prefix is "html".

I hope this provides some more context into how users might want to modify reports. For my use case, perhaps the main takeaways are:

  1. In this case, I didn't want to create my own report from the binary data. I just wanted to take the default HTML report and modify it directly. I imagine others also might prefer this over creating their own report for simple cases
  2. The way the kover gradle plugin could help the most would be to expose the report directories and maybe even the specific files (the CSS files for me)
mgroth0 commented 1 month ago

Worth noting that for my specific use case, I technically don't even need the report dir to be exposed as long as the CSS files are. But that's probably too specific of a consideration for my use case since I only needed to edit the CSS

shanshin commented 1 month ago

@mgroth0, it seems that your use-case and https://github.com/Kotlin/kotlinx-kover/issues/443 is not quite related to the current task.

Your problem is that you need to read the directory for the each HTML report task, this is solved by simply exposing property

interface KoverHtmlReprt {
    val reportDir: Provider<Directory>
}

Then you can write something like this

tasks.withType<KoverHtmlReport>().configureEach {
    doLast {
        val dir = reportDir.get().asFile
        // do some changes in dir
    }
}
mgroth0 commented 1 month ago

You're right, it is different. And you are right that exposing reportDir would be a good solution for my use case.

Still, I added my comment here because I thought maybe it would be useful to consider as this API is being designed. Looking at the big picture, I think you would be supporting users in two different ways to make their own reports:

  1. To create their own report from binary data (this task)
  2. To modify default reports (exposing reportDir)
shanshin commented 1 month ago

Relates #590