Skip to content

Commit bc91512

Browse files
authored
Merge pull request #162 from gradle/tt/test-suites-for-kmp
Setup static JVM test suites for KMP `kotlinApplication` projects
2 parents d842a3a + 8252540 commit bc91512

File tree

11 files changed

+451
-14
lines changed

11 files changed

+451
-14
lines changed

unified-prototype/unified-plugin/internal-testing-utils/src/main/groovy/org/gradle/test/fixtures/AbstractSpecification.groovy

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class AbstractSpecification extends Specification {
4545
.withProjectDir(getTestDirectory())
4646
.withArguments(tasks)
4747
.withPluginClasspath()
48+
.withDebug(true)
49+
.forwardOutput()
4850
.build()
4951
tasks.each { task ->
5052
assert result.task(task).outcome == SUCCESS
@@ -56,9 +58,8 @@ class AbstractSpecification extends Specification {
5658
.withProjectDir(getTestDirectory())
5759
.withArguments(tasks)
5860
.withPluginClasspath()
59-
.run()
60-
tasks.each { task ->
61-
assert result.task(task).outcome == FAILED
62-
}
61+
.withDebug(true)
62+
.forwardOutput()
63+
.buildAndFail()
6364
}
6465
}

unified-prototype/unified-plugin/plugin-kmp/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies {
1313
implementation(project(":plugin-jvm"))
1414
implementation(libs.kotlin.multiplatform)
1515
implementation(libs.kotlin.jvm)
16+
implementation(libs.apache.commons.text)
1617
}
1718

1819
testing {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
package org.gradle.api.experimental.kmp
2+
3+
import org.gradle.test.fixtures.AbstractSpecification
4+
import org.gradle.testkit.runner.TaskOutcome
5+
6+
/**
7+
* Integration tests for the KMP ecosystem plugin's {@code kotlinApplication} project type.
8+
*/
9+
class KotlinApplicationSpec extends AbstractSpecification {
10+
def 'kmp jvm application with a jvmTest missing a dep fails to compile'() {
11+
given:
12+
buildFile << """
13+
kotlinApplication {
14+
targets {
15+
jvm {
16+
jdkVersion = 17
17+
18+
testing {
19+
dependencies {
20+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
21+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
22+
}
23+
}
24+
}
25+
}
26+
}
27+
"""
28+
29+
file("src/jvmTest/kotlin/org/example/Test.kt") << customGuavaTest(true)
30+
31+
expect:
32+
fails("build")
33+
34+
result.task(":compileTestKotlinJvm").outcome == TaskOutcome.FAILED
35+
!result.output.contains("This test should fail")
36+
}
37+
38+
def 'kmp jvm application with a failing jvmTest fails at runtime'() {
39+
given:
40+
buildFile << """
41+
kotlinApplication {
42+
targets {
43+
jvm {
44+
jdkVersion = 17
45+
46+
testing {
47+
dependencies {
48+
implementation("com.google.guava:guava:33.4.0-jre")
49+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
50+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
51+
}
52+
}
53+
}
54+
}
55+
}
56+
"""
57+
58+
file("src/jvmTest/kotlin/org/example/Test.kt") << customGuavaTest(true)
59+
60+
expect:
61+
fails("build")
62+
63+
result.task(":allTests").outcome == TaskOutcome.FAILED
64+
}
65+
66+
def 'kmp jvm application with a passing jvmTest passes'() {
67+
given:
68+
buildFile << """
69+
kotlinApplication {
70+
targets {
71+
jvm {
72+
jdkVersion = 17
73+
74+
testing {
75+
dependencies {
76+
implementation("com.google.guava:guava:33.4.0-jre")
77+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
78+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
79+
}
80+
}
81+
}
82+
}
83+
}
84+
"""
85+
86+
file("src/jvmTest/kotlin/org/example/Test.kt") << customGuavaTest(false)
87+
88+
expect:
89+
succeeds(":allTests")
90+
}
91+
92+
def 'kmp jvm application with a custom test JVM test suite missing a dep fails to compile'() {
93+
given:
94+
buildFile << """
95+
kotlinApplication {
96+
targets {
97+
jvm {
98+
jdkVersion = 17
99+
100+
testing {
101+
functionalTest {
102+
dependencies {
103+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
104+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
105+
}
106+
}
107+
}
108+
}
109+
}
110+
}
111+
"""
112+
113+
file("src/jvmFunctionalTest/kotlin/org/example/Test.kt") << customGuavaTest()
114+
115+
expect:
116+
fails(":compileSuiteFunctionalTestCompilationKotlinJvm")
117+
}
118+
119+
def 'kmp jvm application with a failing custom test JVM test suite fails at runtime'() {
120+
given:
121+
buildFile << """
122+
kotlinApplication {
123+
targets {
124+
jvm {
125+
jdkVersion = 17
126+
127+
testing {
128+
functionalTest {
129+
dependencies {
130+
implementation("com.google.guava:guava:33.4.0-jre")
131+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
132+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
133+
}
134+
}
135+
}
136+
}
137+
}
138+
}
139+
"""
140+
141+
file("src/jvmFunctionalTest/kotlin/org/example/Test.kt") << customGuavaTest(true)
142+
143+
expect:
144+
fails(":suiteFunctionalTestTest")
145+
}
146+
147+
def 'kmp jvm application with a passing custom test JVM test suite passes'() {
148+
given:
149+
buildFile << """
150+
kotlinApplication {
151+
targets {
152+
jvm {
153+
jdkVersion = 17
154+
155+
testing {
156+
functionalTest {
157+
dependencies {
158+
implementation("com.google.guava:guava:33.4.0-jre")
159+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
160+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
161+
}
162+
}
163+
}
164+
}
165+
}
166+
}
167+
"""
168+
169+
file("src/jvmFunctionalTest/kotlin/org/example/Test.kt") << customGuavaTest(false)
170+
171+
expect:
172+
succeeds(":suiteFunctionalTestTest")
173+
}
174+
175+
def 'kmp jvm application with a passing custom test JVM test suite inherits dependencies from common deps'() {
176+
given:
177+
buildFile << """
178+
kotlinApplication {
179+
targets {
180+
jvm {
181+
jdkVersion = 17
182+
183+
dependencies {
184+
implementation("com.google.guava:guava:33.4.0-jre")
185+
}
186+
187+
testing {
188+
functionalTest {
189+
dependencies {
190+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
191+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
192+
}
193+
}
194+
}
195+
}
196+
}
197+
}
198+
"""
199+
200+
file("src/jvmFunctionalTest/kotlin/org/example/Test.kt") << customGuavaTest(false)
201+
202+
expect:
203+
succeeds(":suiteFunctionalTestTest")
204+
}
205+
206+
def 'kmp jvm application with a passing custom test JVM test suite inherits dependencies from common test deps'() {
207+
given:
208+
buildFile << """
209+
kotlinApplication {
210+
targets {
211+
jvm {
212+
jdkVersion = 17
213+
214+
testing {
215+
dependencies {
216+
implementation("com.google.guava:guava:33.4.0-jre")
217+
}
218+
219+
functionalTest {
220+
dependencies {
221+
implementation("org.junit.jupiter:junit-jupiter:5.11.4")
222+
runtimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
223+
}
224+
}
225+
}
226+
}
227+
}
228+
}
229+
"""
230+
231+
file("src/jvmFunctionalTest/kotlin/org/example/Test.kt") << customGuavaTest(false)
232+
233+
expect:
234+
succeeds(":suiteFunctionalTestTest")
235+
}
236+
237+
def setup() {
238+
settingsFile << """
239+
plugins {
240+
id("org.gradle.experimental.kmp-ecosystem")
241+
}
242+
243+
dependencyResolutionManagement {
244+
repositories {
245+
mavenCentral()
246+
}
247+
}
248+
249+
rootProject.name = "example"
250+
"""
251+
}
252+
253+
private String customGuavaTest(boolean fails = false) {
254+
return """
255+
package org.example
256+
257+
import com.google.common.base.Preconditions
258+
import org.junit.jupiter.api.Test
259+
260+
class Test {
261+
@Test
262+
fun test() {
263+
${ fails ? 'Preconditions.checkState(false, "This test should fail")' : ''}
264+
}
265+
}
266+
"""
267+
}
268+
}

unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kmp/KmpApplicationTarget.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
import org.gradle.api.Action;
44
import org.gradle.api.Named;
55
import org.gradle.api.experimental.common.ApplicationDependencies;
6+
import org.gradle.api.experimental.kmp.testing.TestingExtension;
67
import org.gradle.api.tasks.Nested;
78
import org.gradle.declarative.dsl.model.annotations.Configuring;
89
import org.gradle.declarative.dsl.model.annotations.Restricted;
910

11+
/**
12+
* Represents a target platform in a KMP application.
13+
*/
1014
@Restricted
1115
public interface KmpApplicationTarget extends Named {
1216
@Nested
@@ -16,4 +20,12 @@ public interface KmpApplicationTarget extends Named {
1620
default void dependencies(Action<? super ApplicationDependencies> action) {
1721
action.execute(getDependencies());
1822
}
23+
24+
@Nested
25+
TestingExtension getTesting();
26+
27+
@Configuring
28+
default void testing(Action<? super TestingExtension> action) {
29+
action.execute(getTesting());
30+
}
1931
}

unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kmp/KmpLibraryTarget.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.gradle.api.Action;
44
import org.gradle.api.Named;
55
import org.gradle.api.experimental.common.LibraryDependencies;
6+
import org.gradle.api.experimental.kmp.testing.TestingExtension;
67
import org.gradle.api.tasks.Nested;
78
import org.gradle.declarative.dsl.model.annotations.Configuring;
89
import org.gradle.declarative.dsl.model.annotations.Restricted;
@@ -16,4 +17,12 @@ public interface KmpLibraryTarget extends Named {
1617
default void dependencies(Action<? super LibraryDependencies> action) {
1718
action.execute(getDependencies());
1819
}
20+
21+
@Nested
22+
TestingExtension getTesting();
23+
24+
@Configuring
25+
default void testing(Action<? super TestingExtension> action) {
26+
action.execute(getTesting());
27+
}
1928
}

0 commit comments

Comments
 (0)