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 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
- [breaking] _agent_: The deprecated Docker image `cqse/teamscale-jacoco-agent` is no longer published. Use `cqse/teamscale-java-profiler` instead, which has replaced it since version 36.5.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class TeamscalePlugin : Plugin<Project> {
"okhttp3.*",
"okio.*",
"retrofit2.*",
"*.MockitoMock.*",
"*.FastClassByGuice.*",
"*\$MockitoMock\$*",
"*\$\$FastClassByGuice\$\$*",
"*.ConstructorAccess"
)

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

import org.assertj.core.api.Assertions.assertThat
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.named
import org.gradle.testfixtures.ProjectBuilder
import org.gradle.testing.jacoco.plugins.JacocoTaskExtension
import org.jacoco.core.runtime.WildcardMatcher
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource

/** Tests which classes the plugin's default excludes match. */
class TeamscalePluginDefaultExcludesTest {

@ParameterizedTest
@ValueSource(strings = ["com/x/IFoo\$MockitoMock\$123", "com/x/Foo\$\$FastClassByGuice\$\$abc"])
fun `default excludes match Mockito mocks and Guice fast classes`(internalClassName: String) {
assertThat(isExcludedByDefault(internalClassName))
.`as`("The default excludes should match the generated class $internalClassName")
.isTrue()
}

@ParameterizedTest
@ValueSource(strings = ["com/x/Foo\$Bar", "com/x/Foo\$1"])
fun `default excludes do not match ordinary nested or anonymous classes`(internalClassName: String) {
assertThat(isExcludedByDefault(internalClassName))
.`as`("The default excludes should not match the ordinary nested or anonymous class $internalClassName")
.isFalse()
}

private fun isExcludedByDefault(internalClassName: String): Boolean {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply(TeamscalePlugin::class.java)
val excludes = project.tasks.named<Test>("test").get().extensions.getByType<JacocoTaskExtension>().excludes

// JaCoCo's agent replaces the dots of each pattern with slashes and matches it against the JVM internal class name.
val excludesMatcher = WildcardMatcher(excludes.orEmpty().joinToString(":").replace('.', '/'))
return excludesMatcher.matches(internalClassName)
}
}
Loading