Skip to content

Commit 80c8180

Browse files
Tidy up the TestInterceptor API (#178)
Define a toString() function on TestFunction and use it everywhere. Improve the docs a bit. Co-authored-by: Jesse Wilson <jwilson@squareup.com>
1 parent 1a343a1 commit 80c8180

File tree

8 files changed

+152
-52
lines changed

8 files changed

+152
-52
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class RepeatInterceptor(
114114
) : TestInterceptor {
115115
override fun intercept(testFunction: TestFunction) {
116116
for (i in 0 until attemptCount) {
117-
println("running ${testFunction.functionName} attempt $i")
117+
println("running $testFunction attempt $i")
118118
testFunction()
119119
}
120120
}
@@ -138,11 +138,11 @@ class DrinkSodaTest {
138138
When you execute this test, it is intercepted:
139139

140140
```
141-
running drinkSoda attempt 0
141+
running DrinkSodaTest.drinkSoda attempt 0
142142
drinking a Pepsi
143-
running drinkSoda attempt 1
143+
running DrinkSodaTest.drinkSoda attempt 1
144144
drinking a Pepsi
145-
running drinkSoda attempt 2
145+
running DrinkSodaTest.drinkSoda attempt 2
146146
drinking a Pepsi
147147
```
148148

@@ -155,9 +155,9 @@ class DrinkSodaTest {
155155
@InterceptTest
156156
val loggingInterceptor = object : TestInterceptor {
157157
override fun intercept(testFunction: TestFunction) {
158-
println("intercepting ${testFunction.functionName}")
158+
println("intercepting $testFunction")
159159
testFunction()
160-
println("intercepted ${testFunction.functionName}")
160+
println("intercepted $testFunction")
161161
}
162162
}
163163

@@ -181,11 +181,11 @@ class DrinkSodaTest {
181181
And here’s its output:
182182

183183
```
184-
intercepting drinkSoda
184+
intercepting DrinkSodaTest.drinkSoda
185185
getting ready
186186
drinking a Pepsi
187187
cleaning up
188-
intercepted drinkSoda
188+
intercepted DrinkSodaTest.drinkSoda
189189
```
190190

191191
### Features and Limitations

burst-gradle-plugin/src/test/kotlin/app/cash/burst/gradle/TestInterceptorGradlePluginTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,11 @@ class TestInterceptorGradlePluginTest {
163163
with(tester.readTestSuite("app.cash.burst.tests.KotlinTestTest")) {
164164
assertThat(systemOut).isEqualTo(
165165
"""
166-
|intercepting kotlinTestTest
166+
|intercepting app.cash.burst.tests.KotlinTestTest.kotlinTestTest
167167
|@kotlin.test.BeforeTest before test
168168
|@kotlin.test.Test running
169169
|@kotlin.test.AfterTest after test
170-
|intercepted kotlinTestTest
170+
|intercepted app.cash.burst.tests.KotlinTestTest.kotlinTestTest
171171
|
172172
""".trimMargin(),
173173
)
@@ -182,11 +182,11 @@ class TestInterceptorGradlePluginTest {
182182
with(tester.readTestSuite("app.cash.burst.tests.OrgJunitTest")) {
183183
assertThat(systemOut).isEqualTo(
184184
"""
185-
|intercepting orgJunitTest
185+
|intercepting app.cash.burst.tests.OrgJunitTest.orgJunitTest
186186
|@org.junit.Before before test
187187
|@org.junit.Test running
188188
|@org.junit.After after test
189-
|intercepted orgJunitTest
189+
|intercepted app.cash.burst.tests.OrgJunitTest.orgJunitTest
190190
|
191191
""".trimMargin(),
192192
)
@@ -201,11 +201,11 @@ class TestInterceptorGradlePluginTest {
201201
with(tester.readTestSuite("app.cash.burst.tests.OrgJunitJupiterApiTest")) {
202202
assertThat(systemOut).isEqualTo(
203203
"""
204-
|intercepting orgJunitJupiterApiTest
204+
|intercepting app.cash.burst.tests.OrgJunitJupiterApiTest.orgJunitJupiterApiTest
205205
|@org.junit.jupiter.api.BeforeEach before test
206206
|@org.junit.jupiter.api.Test running
207207
|@org.junit.jupiter.api.AfterEach after test
208-
|intercepted orgJunitJupiterApiTest
208+
|intercepted app.cash.burst.tests.OrgJunitJupiterApiTest.orgJunitJupiterApiTest
209209
|
210210
""".trimMargin(),
211211
)

burst-gradle-plugin/src/test/projects/interceptorJunit5/lib/src/test/kotlin/app/cash/burst/tests/BasicInterceptor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import app.cash.burst.TestInterceptor
55

66
class BasicInterceptor : TestInterceptor {
77
override fun intercept(testFunction: TestFunction) {
8-
println("intercepting ${testFunction.functionName}")
8+
println("intercepting $testFunction")
99
testFunction()
10-
println("intercepted ${testFunction.functionName}")
10+
println("intercepted $testFunction")
1111
}
1212
}

burst-kotlin-plugin-tests/src/test/kotlin/app/cash/burst/kotlin/TestInterceptorKotlinPluginTest.kt

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,7 @@ class TestInterceptorKotlinPluginTest {
4747
@InterceptTest
4848
val interceptor = object : TestInterceptor {
4949
override fun intercept(testFunction: TestFunction) {
50-
log("intercepting")
51-
log(" packageName=${'$'}{testFunction.packageName}")
52-
log(" className=${'$'}{testFunction.className}")
53-
log(" functionName=${'$'}{testFunction.functionName}")
50+
log("intercepting ${'$'}testFunction")
5451
testFunction()
5552
log("intercepted")
5653
}
@@ -70,10 +67,7 @@ class TestInterceptorKotlinPluginTest {
7067
)
7168

7269
assertThat(log).containsExactly(
73-
"intercepting",
74-
" packageName=com.example",
75-
" className=SampleTest",
76-
" functionName=happyPath",
70+
"intercepting com.example.SampleTest.happyPath",
7771
"running happyPath",
7872
"intercepted",
7973
)
@@ -115,7 +109,7 @@ class TestInterceptorKotlinPluginTest {
115109
116110
class LoggingInterceptor(val name: String) : TestInterceptor {
117111
override fun intercept(testFunction: TestFunction) {
118-
log("intercepting ${'$'}name (${'$'}{testFunction.packageName} ${'$'}{testFunction.className} ${'$'}{testFunction.functionName})")
112+
log("intercepting ${'$'}name ${'$'}testFunction")
119113
testFunction()
120114
log("intercepted ${'$'}name")
121115
}
@@ -129,9 +123,9 @@ class TestInterceptorKotlinPluginTest {
129123
)
130124

131125
assertThat(log).containsExactly(
132-
"intercepting red (app.cash.burst.tests MultipleInterceptorsTest passingTest)",
133-
"intercepting blue (app.cash.burst.tests MultipleInterceptorsTest passingTest)",
134-
"intercepting green (app.cash.burst.tests MultipleInterceptorsTest passingTest)",
126+
"intercepting red app.cash.burst.tests.MultipleInterceptorsTest.passingTest",
127+
"intercepting blue app.cash.burst.tests.MultipleInterceptorsTest.passingTest",
128+
"intercepting green app.cash.burst.tests.MultipleInterceptorsTest.passingTest",
135129
"running",
136130
"intercepted green",
137131
"intercepted blue",
@@ -659,7 +653,7 @@ class TestInterceptorKotlinPluginTest {
659653
660654
class LoggingInterceptor(val name: String) : TestInterceptor {
661655
override fun intercept(testFunction: TestFunction) {
662-
log("intercepting ${'$'}name (${'$'}{testFunction.packageName} ${'$'}{testFunction.className} ${'$'}{testFunction.functionName})")
656+
log("intercepting ${'$'}name ${'$'}testFunction")
663657
testFunction()
664658
log("intercepted ${'$'}name")
665659
}
@@ -673,8 +667,8 @@ class TestInterceptorKotlinPluginTest {
673667
)
674668

675669
assertThat(log).containsExactly(
676-
"intercepting shape (app.cash.burst.tests CircleTest passingTest)",
677-
"intercepting circle (app.cash.burst.tests CircleTest passingTest)",
670+
"intercepting shape app.cash.burst.tests.CircleTest.passingTest",
671+
"intercepting circle app.cash.burst.tests.CircleTest.passingTest",
678672
"running",
679673
"intercepted circle",
680674
"intercepted shape",
@@ -717,7 +711,7 @@ class TestInterceptorKotlinPluginTest {
717711
718712
class LoggingInterceptor(val name: String) : TestInterceptor {
719713
override fun intercept(testFunction: TestFunction) {
720-
log("intercepting ${'$'}name (${'$'}{testFunction.packageName} ${'$'}{testFunction.className} ${'$'}{testFunction.functionName})")
714+
log("intercepting ${'$'}name ${'$'}testFunction")
721715
testFunction()
722716
log("intercepted ${'$'}name")
723717
}
@@ -731,8 +725,8 @@ class TestInterceptorKotlinPluginTest {
731725
)
732726

733727
assertThat(log).containsExactly(
734-
"intercepting shape (app.cash.burst.tests CircleTest passingTest)",
735-
"intercepting circle (app.cash.burst.tests CircleTest passingTest)",
728+
"intercepting shape app.cash.burst.tests.CircleTest.passingTest",
729+
"intercepting circle app.cash.burst.tests.CircleTest.passingTest",
736730
"running",
737731
"intercepted circle",
738732
"intercepted shape",
@@ -769,7 +763,7 @@ class TestInterceptorKotlinPluginTest {
769763
770764
class LoggingInterceptor(val name: String) : TestInterceptor {
771765
override fun intercept(testFunction: TestFunction) {
772-
log("intercepting ${'$'}name (${'$'}{testFunction.packageName} ${'$'}{testFunction.className} ${'$'}{testFunction.functionName})")
766+
log("intercepting ${'$'}name ${'$'}testFunction")
773767
testFunction()
774768
log("intercepted ${'$'}name")
775769
}
@@ -783,7 +777,7 @@ class TestInterceptorKotlinPluginTest {
783777
)
784778

785779
assertThat(log).containsExactly(
786-
"intercepting shape (app.cash.burst.tests CircleTest passingTest)",
780+
"intercepting shape app.cash.burst.tests.CircleTest.passingTest",
787781
"running",
788782
"intercepted shape",
789783
)
@@ -1557,7 +1551,7 @@ class TestInterceptorKotlinPluginTest {
15571551
@InterceptTest
15581552
val interceptor = object : TestInterceptor {
15591553
override fun intercept(testFunction: TestFunction) {
1560-
log("intercepting ${'$'}{testFunction.className}.${'$'}{testFunction.functionName}")
1554+
log("intercepting ${'$'}testFunction")
15611555
testFunction()
15621556
}
15631557
}
@@ -1593,11 +1587,11 @@ class TestInterceptorKotlinPluginTest {
15931587
)
15941588

15951589
assertThat(log).containsExactly(
1596-
"intercepting TopTest.testTop",
1590+
"intercepting com.example.TopTest.testTop",
15971591
"top",
1598-
"intercepting MiddleTest.testMiddle",
1592+
"intercepting com.example.MiddleTest.testMiddle",
15991593
"middle",
1600-
"intercepting BottomTest.testBottom",
1594+
"intercepting com.example.BottomTest.testBottom",
16011595
"bottom",
16021596
)
16031597
}

burst-kotlin-plugin/src/main/kotlin/app/cash/burst/kotlin/InterceptorInjector.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,15 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
8686
* @Test
8787
* fun happyPath() {
8888
* intercept(
89-
* TestFunction(
89+
* object : TestFunction(
9090
* packageName = "com.example",
9191
* className = "SampleTest",
9292
* functionName = "happyPath",
93-
* block = {
93+
* ) {
94+
* override fun invoke() {
9495
* assertThat(5 + 5).isEqualTo(10)
9596
* }
96-
* )
97+
* }
9798
* )
9899
* }
99100
* ```
@@ -103,14 +104,15 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
103104
* ```kotlin
104105
* override fun intercept(testFunction: TestFunction) {
105106
* interceptor.intercept(
106-
* TestInterceptor.Test(
107+
* object : TestFunction(
107108
* packageName = testFunction.packageName,
108109
* className = testFunction.className,
109110
* functionName = testFunction.functionName,
110-
* block = {
111+
* ) {
112+
* override fun invoke() {
111113
* testFunction()
112114
* }
113-
* )
115+
* }
114116
* )
115117
* }
116118
* ```

burst/api/burst.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public abstract class app/cash/burst/TestFunction {
1414
public final fun getFunctionName ()Ljava/lang/String;
1515
public final fun getPackageName ()Ljava/lang/String;
1616
public abstract fun invoke ()V
17+
public fun toString ()Ljava/lang/String;
1718
}
1819

1920
public abstract interface class app/cash/burst/TestInterceptor {

burst/src/commonMain/kotlin/app/cash/burst/TestInterceptor.kt

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,53 @@
1515
*/
1616
package app.cash.burst
1717

18+
/**
19+
* Intercepts the execution of a test function, including its `@BeforeTest` and `@AfterTest`
20+
* functions.
21+
*
22+
* This sample creates a directory before a test runs and deletes it after.
23+
*
24+
* ```
25+
* class TemporaryDirectory : TestInterceptor {
26+
* lateinit var path: Path
27+
* private set
28+
*
29+
* override fun intercept(testFunction: TestFunction) {
30+
* path = createTemporaryDirectory(testFunction)
31+
* try {
32+
* testFunction()
33+
* } finally {
34+
* deleteTemporaryDirectory(path)
35+
* }
36+
* }
37+
* }
38+
* ```
39+
*
40+
* Adopt an interceptor in your test by declaring a property of this type (or any subtype) and
41+
* annotating it `@InterceptTest`:
42+
*
43+
* ```
44+
* class DocumentStorageTest {
45+
* @InterceptTest
46+
* val temporaryDirectory = TemporaryDirectory()
47+
*
48+
* @Test
49+
* fun happyPath() {
50+
* val original = SampleData.document
51+
* DocumentWriter().write(original, temporaryDirectory.path)
52+
* val decoded = DocumentReader().read(temporaryDirectory.path)
53+
* assertThat(decoded).isEqualTo(original)
54+
* }
55+
* }
56+
* ```
57+
*/
58+
interface TestInterceptor {
59+
fun intercept(testFunction: TestFunction)
60+
}
61+
62+
@Target(AnnotationTarget.PROPERTY)
63+
annotation class InterceptTest
64+
1865
abstract class TestFunction(
1966
/** The package that this test is defined in, or "" it has none. */
2067
val packageName: String,
@@ -35,11 +82,19 @@ abstract class TestFunction(
3582
* * The `@AfterTest` functions (if any)
3683
*/
3784
abstract operator fun invoke()
38-
}
3985

40-
interface TestInterceptor {
41-
fun intercept(testFunction: TestFunction)
86+
/**
87+
* Returns the full test name, like `com.example.project.FeatureTest.testMyFeature`.
88+
*/
89+
override fun toString(): String {
90+
return buildString {
91+
if (packageName.isNotEmpty()) {
92+
append(packageName)
93+
append(".")
94+
}
95+
append(className)
96+
append(".")
97+
append(functionName)
98+
}
99+
}
42100
}
43-
44-
@Target(AnnotationTarget.PROPERTY)
45-
annotation class InterceptTest

0 commit comments

Comments
 (0)