Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ We use [semantic versioning](http://semver.org/):
- [fix] _agent_: With `duplicates=FAIL`, the error for a duplicate, non-identical class now names the class and how to resolve the problem.
- [fix] _agent_, _teamscale-gradle-plugin_, _teamscale-maven-plugin_: A corrupt class file whose class name cannot be read is skipped with a warning instead of failing the coverage report.
- [fix] _impacted-test-engine_: A test that a failing assumption aborts is reported as skipped instead of as an error.
- [fix] _teamscale-gradle-plugin_: The plugin now works when the build sets `jacoco.excludes` or the JUnit Platform `excludeEngines` of a test task to a read-only collection (for example, `listOf(...)` or `setOf(...)` in the Kotlin DSL). Previously, applying the plugin or running the test task failed with an `UnsupportedOperationException`.
- [fix] _teamscale-gradle-plugin_: The default excludes now match Mockito mocks (e.g. `com.company.IFoo$MockitoMock$123`) and Guice fast classes (e.g. `com.company.Foo$$FastClassByGuice$$abc`). Previously the profiler instrumented them, and the testwise coverage report warned that it found coverage for classes that were not provided.

# 39.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class TeamscalePlugin : Plugin<Project> {
AgentPortGenerator::class.java
) {}
project.tasks.withType<Test> {
jacoco.excludes?.addAll(DEFAULT_EXCLUDES)
jacoco.excludes?.let { buildExcludes -> jacoco.excludes = buildExcludes + DEFAULT_EXCLUDES }

val extension = this.extensions.create<TeamscaleTaskExtension>(
TEAMSCALE_EXTENSION_NAME, teamscaleJacocoAgentConfiguration, jacoco
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class TestImpactConfigurationAction(
writeProperty("excludedEngines", testFrameworkOptions.excludeEngines.joinToString(","))
testFrameworkOptions.includeEngines = setOf(IMPACTED_TEST_ENGINE_ID)
} else {
testFrameworkOptions.excludeEngines.add(IMPACTED_TEST_ENGINE_ID)
testFrameworkOptions.excludeEngines = testFrameworkOptions.excludeEngines + IMPACTED_TEST_ENGINE_ID
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.teamscale

import org.assertj.core.api.Assertions.assertThat
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.testing.Test as TestTask
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.gradle.testing.jacoco.plugins.JacocoPlugin
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
import org.junit.jupiter.api.Test

/** Tests how the plugin combines its default excludes with the JaCoCo excludes that the build sets. */
class TeamscalePluginBuildExcludesTest {

private val buildExclude = "*\$MockitoMock\$*"

@Test
fun `plugin appends its default excludes to read-only excludes of the build`() {
val excludes = testTaskExcludesAfterApplyingPlugin(listOf(buildExclude))

assertThat(excludes)
.`as`("The excludes should be the excludes of the build followed by the default excludes")
.containsExactlyElementsOf(listOf(buildExclude) + defaultExcludes())
}

@Test
fun `plugin appends its default excludes to mutable excludes of the build`() {
val excludes = testTaskExcludesAfterApplyingPlugin(mutableListOf(buildExclude))

assertThat(excludes)
.`as`("The excludes should be the excludes of the build followed by the default excludes")
.containsExactlyElementsOf(listOf(buildExclude) + defaultExcludes())
}

private fun testTaskExcludesAfterApplyingPlugin(buildExcludes: List<String>): List<String>? {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply(JavaPlugin::class.java)
project.pluginManager.apply(JacocoPlugin::class.java)
project.tasks.withType<TestTask>().configureEach {
extensions.configure<JacocoTaskExtension> { excludes = buildExcludes }
}

project.pluginManager.apply(TeamscalePlugin::class.java)
return testTaskExcludesOf(project)
}

private fun defaultExcludes(): List<String> {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply(TeamscalePlugin::class.java)
val defaultExcludes = testTaskExcludesOf(project).orEmpty()

assertThat(defaultExcludes)
.`as`("The plugin should add default excludes to a test task without excludes of the build")
.isNotEmpty()
return defaultExcludes
}

private fun testTaskExcludesOf(project: Project) =
project.tasks.named<TestTask>("test").get().extensions.getByType<JacocoTaskExtension>().excludes
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.teamscale

import com.teamscale.extension.TeamscalePluginExtension
import com.teamscale.extension.TeamscaleTaskExtension
import org.assertj.core.api.Assertions.assertThat
import org.gradle.api.tasks.testing.Test as TestTask
import org.gradle.api.tasks.testing.junitplatform.JUnitPlatformOptions
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.gradle.testfixtures.ProjectBuilder
import org.junit.jupiter.api.Test

/** Tests how [TestImpactConfigurationAction] configures the JUnit Platform engines of a test task. */
class TestImpactConfigurationActionTest {

@Test
fun `plugin adds the impacted test engine to read-only engine excludes of the build`() {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply(TeamscalePlugin::class.java)
val testTask = project.tasks.named<TestTask>("test").get()
testTask.useJUnitPlatform { excludeEngines = setOf("junit-vintage") }

runTestImpactConfigurationAction(testTask)

assertThat((testTask.options as JUnitPlatformOptions).excludeEngines)
.`as`("The test task should exclude the engine of the build and the impacted test engine")
.containsExactlyInAnyOrder("junit-vintage", "teamscale-test-impacted")
}

private fun runTestImpactConfigurationAction(testTask: TestTask) {
val pluginExtension = testTask.project.extensions.getByType<TeamscalePluginExtension>()
val taskExtension = testTask.extensions.getByType<TeamscaleTaskExtension>()
TestImpactConfigurationAction(pluginExtension, taskExtension).execute(testTask)
}
}
Loading