diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml new file mode 100644 index 0000000..4258666 --- /dev/null +++ b/.github/workflows/integration-test.yml @@ -0,0 +1,100 @@ +name: Integration tests + +on: + push: + branches: ["**"] + +concurrency: + group: integration-test-${{ github.ref }} + cancel-in-progress: true + +env: + split-total: 4 + +jobs: + generate-split-index-json: + name: Generate split indexes + runs-on: ubuntu-latest + outputs: + json: ${{ steps.generate.outputs.split-index-json }} + steps: + - name: Generate split index list + id: generate + uses: donnerbart/split-tests-java-action/generate-split-index-json@25d52b2bdc694f5077fde78908ee84fb23da4d90 # v1 + with: + split-total: ${{ env.split-total }} + + integration-test: + name: "Test #${{ matrix.split-index }}" + runs-on: ubuntu-latest + needs: + - generate-split-index-json + permissions: + contents: read + checks: write + strategy: + fail-fast: false + matrix: + split-index: ${{ fromjson(needs.generate-split-index-json.outputs.json) }} + env: + DOWNLOAD_JAR: false + JAR_PATH: build/libs/split-tests-java.jar + steps: + - name: Checkout split-test-java + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK 21 + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4 + with: + distribution: temurin + java-version: 21 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4 + + - name: Compile split-tests-java + run: ./gradlew shadowJar + + - name: Split tests + id: split-tests + uses: donnerbart/split-tests-java-action@25d52b2bdc694f5077fde78908ee84fb23da4d90 # v1 + with: + split-index: ${{ matrix.split-index }} + split-total: ${{ env.split-total }} + glob: '**/src/test/resources/tests/*Test.java' + exclude-glob: '**/NoClassNameTest.java' + junit-glob: '**/src/test/resources/reports/*.xml' + format: 'list' + new-test-time: 'average' + calculate-optimal-total-split: true + debug: true + + - name: Assert split tests + env: + SPLIT_INDEX: ${{ matrix.split-index }} + ACTUAL: ${{ steps.split-tests.outputs.test-suite }} + run: | + case "$SPLIT_INDEX" in + "0") + EXPECTED="de.donnerbart.example.SlowestTest" + ;; + "1") + EXPECTED="NoPackageTest de.donnerbart.example.ThirdPartyLibraryTest" + ;; + "2") + EXPECTED="de.donnerbart.example.NoTimingOneTest de.donnerbart.example.WhitespaceClassDefinitionTest" + ;; + "3") + EXPECTED="de.donnerbart.example.NoTimingTwoTest de.donnerbart.example.SlowTest de.donnerbart.example.FastTest" + ;; + *) + echo "Unexpected split index" + exit 1 + ;; + esac + echo "Expected: $EXPECTED" + echo "Actual: $ACTUAL" + if [ "$ACTUAL" != "$EXPECTED" ]; then + echo "The split tests are not matching" + exit 1 + fi diff --git a/.github/workflows/check.yml b/.github/workflows/unit-test.yml similarity index 98% rename from .github/workflows/check.yml rename to .github/workflows/unit-test.yml index 93b6123..dd430c5 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/unit-test.yml @@ -1,4 +1,4 @@ -name: CI Check +name: Unit tests on: push: diff --git a/README.md b/README.md index 3070cb6..855fd71 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![CI Check](https://github.com/Donnerbart/split-tests-java/actions/workflows/check.yml/badge.svg)](https://github.com/Donnerbart/split-tests-java/actions/workflows/check.yml) +[![Unit tests](https://github.com/Donnerbart/split-tests-java/actions/workflows/unit-test.yml/badge.svg)](https://github.com/Donnerbart/split-tests-java/actions/workflows/unit-test.yml) +[![Integration tests](https://github.com/Donnerbart/split-tests-java/actions/workflows/integration-test.yml/badge.svg)](https://github.com/Donnerbart/split-tests-java/actions/workflows/integration-test.yml) [![Release](https://github.com/Donnerbart/split-tests-java/actions/workflows/release.yml/badge.svg)](https://github.com/Donnerbart/split-tests-java/actions/workflows/release.yml) # Split Tests Java diff --git a/build.gradle.kts b/build.gradle.kts index c5bb92b..5459aa6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { application java + alias(libs.plugins.gradle.git.properties) alias(libs.plugins.shadow) } @@ -34,6 +35,7 @@ dependencies { // ********** distribution ********** tasks.shadowJar { + dependsOn(tasks.generateGitProperties) mergeServiceFiles() archiveBaseName = "split-tests-java" archiveClassifier = "" @@ -59,3 +61,16 @@ dependencies { tasks.test { useJUnitPlatform() } + +// ********** git properties ********** + +gitProperties { + dotGitDirectory = project.rootProject.layout.projectDirectory.dir(".git") + gitPropertiesName = "split-tests-java.properties" + keys = listOf("git.branch", "git.commit.id", "git.commit.id.abbrev", "git.commit.time") + customProperty("version", version) + extProperty = "gitProps" +} +tasks.generateGitProperties { + outputs.upToDateWhen { false } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d89d0c..ad25739 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,4 +20,5 @@ junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } [plugins] +gradle-git-properties = { id = "com.gorylenko.gradle-git-properties", version = "2.5.0" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } diff --git a/src/main/java/de/donnerbart/split/TestSplitMain.java b/src/main/java/de/donnerbart/split/TestSplitMain.java index 3530e70..9555e25 100644 --- a/src/main/java/de/donnerbart/split/TestSplitMain.java +++ b/src/main/java/de/donnerbart/split/TestSplitMain.java @@ -12,7 +12,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; import java.util.Objects; +import java.util.Properties; import java.util.function.Consumer; import static de.donnerbart.split.util.FormatUtil.formatTime; @@ -46,6 +50,12 @@ public static void main(final @Nullable String @NotNull [] args) throws Exceptio if (!validateArguments(arguments, workingDirectory)) { exitConsumer.accept(1); } + final var properties = readProperties("split-tests-java.properties"); + LOG.info("split-tests-java {} (commit: {} on branch: {}) built on {}", + properties.getProperty("version", "unknown"), + properties.getProperty("git.commit.id.abbrev", "unknown"), + properties.getProperty("git.branch", "unknown"), + getBuiltTime(properties.getProperty("git.commit.time", "unknown"))); LOG.info("Split index {} (total: {})", arguments.splitIndex, arguments.splitTotal); LOG.info("Working directory: {}", workingDirectory); LOG.info("Glob: {}", arguments.glob); @@ -140,4 +150,24 @@ static int calculateOptimalTotalSplit(final @NotNull Arguments arguments, final lastSlowestSplit = slowestSplit; } } + + @VisibleForTesting + static @NotNull Properties readProperties(final @NotNull String resourceFile) throws Exception { + final var properties = new Properties(); + try (final var inputStream = TestSplitMain.class.getClassLoader().getResourceAsStream(resourceFile)) { + if (inputStream != null) { + properties.load(inputStream); + } + } + return properties; + } + + @VisibleForTesting + static @NotNull Date getBuiltTime(final @NotNull String dateString) { + try { + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(dateString); + } catch (final Exception e) { + return Date.from(Instant.EPOCH); + } + } } diff --git a/src/test/java/de/donnerbart/split/TestSplitMainTest.java b/src/test/java/de/donnerbart/split/TestSplitMainTest.java index 1a2ad7e..a5fb1ad 100644 --- a/src/test/java/de/donnerbart/split/TestSplitMainTest.java +++ b/src/test/java/de/donnerbart/split/TestSplitMainTest.java @@ -9,6 +9,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; +import java.time.Instant; +import java.util.Date; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -128,7 +130,18 @@ void calculateOptimalTotalSplit_withMaxCalculations() throws Exception { copyResourceToTarget(projectFolder, "tests/NoTimingOneTest.java", "NoTimingOneTest.java", PERMISSIONS); copyResourceToTarget(projectFolder, "tests/NoTimingTwoTest.java", "NoTimingTwoTest.java", PERMISSIONS); - jCommander.parse("-i", "0", "-t", "4", "-g", "**/*Test.java", "-j", "**/junit-reports/*.xml", "-n", "max", "-m", "5"); + jCommander.parse("-i", + "0", + "-t", + "4", + "-g", + "**/*Test.java", + "-j", + "**/junit-reports/*.xml", + "-n", + "max", + "-m", + "5"); assertThat(TestSplitMain.calculateOptimalTotalSplit(arguments, tmp)).isEqualTo(4); } @@ -137,7 +150,18 @@ void calculateOptimalTotalSplit_withTooLowMaxCalculations() throws Exception { copyResourceToTarget(projectFolder, "tests/NoTimingOneTest.java", "NoTimingOneTest.java", PERMISSIONS); copyResourceToTarget(projectFolder, "tests/NoTimingTwoTest.java", "NoTimingTwoTest.java", PERMISSIONS); - jCommander.parse("-i", "0", "-t", "1", "-g", "**/*Test.java", "-j", "**/junit-reports/*.xml", "-n", "max", "-m", "4"); + jCommander.parse("-i", + "0", + "-t", + "1", + "-g", + "**/*Test.java", + "-j", + "**/junit-reports/*.xml", + "-n", + "max", + "-m", + "4"); assertThat(TestSplitMain.calculateOptimalTotalSplit(arguments, tmp)).isEqualTo(0); } @@ -158,4 +182,32 @@ void calculateOptimalTotalSplit_withInvalidSplitIndex() throws Exception { jCommander.parse("-i", "1", "-t", "1", "-g", "**/*Test.java", "-j", "**/junit-reports/*.xml"); assertThat(TestSplitMain.calculateOptimalTotalSplit(arguments, tmp)).isEqualTo(0); } + + @Test + void readProperties() throws Exception { + final var properties = TestSplitMain.readProperties("split-tests-java-test.properties"); + assertThat(properties).isNotNull(); + assertThat(properties.getProperty("git.commit.time")).isEqualTo("2023-01-01T00:01:02+0000"); + assertThat(properties.getProperty("git.commit.id")).isEqualTo("4c204731e327bc2e06d2a1b02f46e4195c210d0e"); + assertThat(properties.getProperty("git.commit.id.abbrev")).isEqualTo("4c20473"); + assertThat(properties.getProperty("git.branch")).isEqualTo("master"); + assertThat(properties.getProperty("version")).isEqualTo("1.2.3-SNAPSHOT"); + } + + @Test + void readProperties_whenFileNotFound() throws Exception { + final var properties = TestSplitMain.readProperties("not-found.properties"); + assertThat(properties).isNotNull(); + assertThat(properties).isEmpty(); + } + + @Test + void getBuiltTime() { + assertThat(TestSplitMain.getBuiltTime("2023-01-01T00:01:02+0000")).isEqualTo("2023-01-01T00:01:02+0000"); + } + + @Test + void getBuiltTime_whenTimeNotParseable() { + assertThat(TestSplitMain.getBuiltTime("")).isEqualTo(Date.from(Instant.EPOCH)); + } } diff --git a/src/test/resources/split-tests-java-test.properties b/src/test/resources/split-tests-java-test.properties new file mode 100644 index 0000000..814a719 --- /dev/null +++ b/src/test/resources/split-tests-java-test.properties @@ -0,0 +1,5 @@ +version=1.2.3-SNAPSHOT +git.branch=master +git.commit.id=4c204731e327bc2e06d2a1b02f46e4195c210d0e +git.commit.id.abbrev=4c20473 +git.commit.time=2023-01-01T00\:01\:02+0000