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 @@ -5,6 +5,7 @@ We use [semantic versioning](http://semver.org/):
- PATCH version when you make backwards compatible bug fixes.

# Next version
- [fix] _teamscale-maven-plugin_: `prepare-tia-unit-test` and `prepare-tia-integration-test` no longer require a commit or revision when `runImpacted` is `false`.
- [fix] _teamscale-gradle-plugin_, _teamscale-maven-plugin_: Testwise coverage reports no longer drop a class directory that contains an archive (JAR, WAR, EAR, ZIP) that contains a JAR.

# 39.0.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.teamscale.test.commons

import com.teamscale.client.FileSystemUtils
import com.teamscale.client.SystemUtils
import com.teamscale.report.testwise.model.TestInfo
import okhttp3.MediaType.Companion.toMediaTypeOrNull
Expand Down Expand Up @@ -48,24 +49,37 @@ object SystemTestUtils {
/**
* Runs the clean and verify goal of the Maven project at the given path with the provided arguments
*
* @param removeEnvironmentVariables names of environment variables that Maven does not inherit.
* @throws IOException if running Maven fails.
*/
@Throws(IOException::class)
fun runMavenTests(mavenProjectPath: String, vararg args: String) {
fun runMavenTests(
mavenProjectPath: String,
vararg args: String,
removeEnvironmentVariables: List<String> = emptyList()
): ProcessUtils.ProcessResult {
val allArguments = mutableListOf("clean", "verify").apply {
addAll(args)
}
runMaven(mavenProjectPath, *allArguments.toTypedArray())
return runMaven(mavenProjectPath, *allArguments.toTypedArray(), removeEnvironmentVariables = removeEnvironmentVariables)
}

/**
* Runs Maven in the given Maven project path with the given arguments.
* Runs Maven in the given Maven project path with the given arguments. A build that fails does not throw, so the
* caller must check the exit code of the returned result if it expects the build to succeed.
*
* @param removeEnvironmentVariables names of environment variables that Maven does not inherit.
* @throws IOException if running Maven fails.
*/
@Throws(IOException::class)
fun runMaven(mavenProjectPath: String, vararg mavenArguments: String) {
val result = buildMavenProcess(mavenProjectPath, *mavenArguments).execute()
fun runMaven(
mavenProjectPath: String,
vararg mavenArguments: String,
removeEnvironmentVariables: List<String> = emptyList()
): ProcessUtils.ProcessResult {
val result = buildMavenProcess(mavenProjectPath, *mavenArguments)
.removeEnvironmentVariables(removeEnvironmentVariables)
.execute()

// in case the process succeeded, we still log stdout and stderr in case later assertions fail. This helps
// debug test failures
Expand All @@ -75,6 +89,20 @@ object SystemTestUtils {
if (result.wasTerminatedByTimeoutOrInterruption) {
throw IOException("Running Maven failed: ${result.stdout}\n${result.stderr}")
}
return result
}

/**
* Copies the Maven project at the given path into the given directory and makes its Maven wrapper executable.
* Tests use this to run a Maven project outside of this repository's Git checkout.
*
* @return the absolute path of the copied project.
*/
@Throws(IOException::class)
fun copyMavenProject(mavenProjectPath: String, targetDirectory: Path): String {
FileSystemUtils.copyFiles(File(mavenProjectPath), targetDirectory.toFile()) { true }
targetDirectory.resolve("mvnw").toFile().setExecutable(true)
return targetDirectory.toAbsolutePath().toString()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package com.teamscale.upload

import com.teamscale.client.EReportFormat
import com.teamscale.client.EnvironmentVariableChecker
import com.teamscale.client.FileSystemUtils
import com.teamscale.client.SystemUtils
import com.teamscale.test.commons.ProcessUtils
import com.teamscale.test.commons.SystemTestUtils
import com.teamscale.test.commons.SystemTestUtils.copyMavenProject
import com.teamscale.test.commons.SystemTestUtils.runMavenTests
import com.teamscale.test.commons.TeamscaleMockServer
import org.assertj.core.api.Assertions
Expand Down Expand Up @@ -108,9 +108,7 @@ class MavenExternalUploadSystemTest {
@Throws(IOException::class)
fun testCiEnvironmentVariableCommitResolution(@TempDir tmpDir: Path) {
val fakeCommit = "abc123def456abc123def456abc123def456abc1"
FileSystemUtils.copyFiles(File("missing-commit-project"), tmpDir.toFile()) { true }
tmpDir.resolve("mvnw").toFile().setExecutable(true)
val projectPath = tmpDir.toAbsolutePath().toString()
val projectPath = copyMavenProject("missing-commit-project", tmpDir)
runMavenTests(projectPath)
val result = runCoverageUploadGoal(
projectPath,
Expand All @@ -131,9 +129,7 @@ class MavenExternalUploadSystemTest {
@Test
@Throws(IOException::class)
fun testErrorMessageOnMissingCommit(@TempDir tmpDir: Path) {
FileSystemUtils.copyFiles(File("missing-commit-project"), tmpDir.toFile()) { true }
tmpDir.resolve("mvnw").toFile().setExecutable(true)
val projectPath = tmpDir.toAbsolutePath().toString()
val projectPath = copyMavenProject("missing-commit-project", tmpDir)
runMavenTests(projectPath)
val result = runCoverageUploadGoal(projectPath, removeEnvironmentVariables = EnvironmentVariableChecker.COMMIT_ENVIRONMENT_VARIABLES)
assertThat(result).isNotNull()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.teamscale.tia

import com.teamscale.client.EnvironmentVariableChecker
import com.teamscale.client.JsonUtils
import com.teamscale.report.testwise.model.ETestExecutionResult
import com.teamscale.report.testwise.model.TestwiseCoverageReport
import com.teamscale.test.commons.SystemTestUtils
import com.teamscale.test.commons.SystemTestUtils.copyMavenProject
import com.teamscale.test.commons.SystemTestUtils.coverage
import com.teamscale.test.commons.SystemTestUtils.getReportFileNames
import com.teamscale.test.commons.SystemTestUtils.runMavenTests
Expand All @@ -13,8 +15,10 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import org.junit.jupiter.api.io.TempDir
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path

/**
* Runs several Maven projects' Surefire tests that have the agent attached and one of our JUnit run listeners enabled.
Expand All @@ -39,7 +43,31 @@ class TiaMavenDumpToFileSystemTest {
fun testMavenTia() {
runMavenTests(MAVEN_PROJECT_NAME)

val unitTestReport = parseDumpedCoverageReport("tia")
assertCoverageReportsDumped(MAVEN_PROJECT_NAME)
}

/**
* With `runImpacted=false`, the plugin must not require a commit or revision. So the build must succeed outside of
* a Git checkout and without CI environment variables (TS-48002).
*/
@Test
@Throws(Exception::class)
fun testMavenTiaWithoutCommit(@TempDir tmpDir: Path) {
val projectPath = copyMavenProject(MAVEN_PROJECT_NAME, tmpDir)

val result = runMavenTests(
projectPath,
removeEnvironmentVariables = EnvironmentVariableChecker.COMMIT_ENVIRONMENT_VARIABLES
)

assertThat(result.exitCode)
.withFailMessage { "Maven failed:\n${result.stdout}\n${result.stderr}" }
.isEqualTo(0)
assertCoverageReportsDumped(projectPath)
}

private fun assertCoverageReportsDumped(projectPath: String) {
val unitTestReport = parseDumpedCoverageReport(projectPath, "tia")
assertThat(unitTestReport.tests).hasSize(2)
assertThat(unitTestReport.partial).isFalse()
assertAll({
Expand All @@ -54,7 +82,7 @@ class TiaMavenDumpToFileSystemTest {
.containsExactly("SUT.java:3,6-7", "SUT.java:3,10-11")
})

val integrationTestReport = parseDumpedCoverageReport("tia-integration")
val integrationTestReport = parseDumpedCoverageReport(projectPath, "tia-integration")
assertThat(integrationTestReport.tests).hasSize(2)
assertAll({
assertThat(integrationTestReport.tests)
Expand All @@ -70,8 +98,8 @@ class TiaMavenDumpToFileSystemTest {
}

@Throws(IOException::class)
private fun parseDumpedCoverageReport(folderName: String): TestwiseCoverageReport {
val files = getReportFileNames(MAVEN_PROJECT_NAME, folderName)
private fun parseDumpedCoverageReport(projectPath: String, folderName: String): TestwiseCoverageReport {
val files = getReportFileNames(projectPath, folderName)
return JsonUtils.deserialize<TestwiseCoverageReport>(
String(Files.readAllBytes(files.first()))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ public abstract class TiaMojoBase extends TeamscaleMojoBase {

/**
* Executes only impacted tests, not all ones if set. Defaults to true.
* <p>
* The commit or revision of the code under test is only resolved, and therefore only required, if this is set.
*/
@Parameter(defaultValue = "true", property = "runImpacted")
public boolean runImpacted;
Expand Down Expand Up @@ -180,7 +182,10 @@ public void execute() throws MojoFailureException, MojoExecutionException {
targetDirectory = Paths.get(projectBuildDir, getOutputDirectoryName()).toAbsolutePath();
createTargetDirectory();

resolveCommitOrRevision();
// The impacted test engine only needs the commit to query Teamscale for the impacted tests
if (runImpacted) {
resolveCommitOrRevision();
}

setTiaProperties();

Expand Down
Loading