Skip to content

Commit d5e9509

Browse files
runningcodeclaude
andcommitted
test(spring): Move the Spring 7 WAR sample's tests into the module
Adds sentry-spring-jakarta's embedded-Tomcat integrationTest suite to sentry-spring-7, with the module's packages. The sample's tests were the jakarta WAR sample's, so the suite is too. Spring Boot 4's BOM picks Spring 7 and Tomcat 11. The sample has no system tests left, so it comes off the system-test runner, the backend workflow and the Spring Boot 4 matrix. That was the matrix's last runner step, so it drops the Python setup and the runner's logs too. integrationTests includes the suite. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 0fb9338 commit d5e9509

15 files changed

Lines changed: 316 additions & 205 deletions

File tree

‎.github/workflows/spring-boot-4-matrix.yml‎

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ jobs:
2525

2626
name: Spring Boot ${{ matrix.springboot-version }}
2727
env:
28-
SENTRY_URL: http://127.0.0.1:8000
2928
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
3029

3130
steps:
@@ -34,16 +33,6 @@ jobs:
3433
with:
3534
submodules: 'recursive'
3635

37-
- name: Set up Python
38-
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
39-
with:
40-
python-version: '3.10'
41-
42-
- name: Install Python dependencies
43-
run: |
44-
python3 -m pip install --upgrade pip
45-
python3 -m pip install -r requirements.txt
46-
4736
- name: Set up Java
4837
uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
4938
with:
@@ -68,29 +57,17 @@ jobs:
6857
perl -0pi -e 'BEGIN { $v = shift } s/^springboot4[[:space:]]*=[[:space:]]*"\K[^"]*/$v/m or die "::error::springboot4 version entry not found in gradle/libs.versions.toml\n"' "$springboot_version" gradle/libs.versions.toml
6958
echo "Updated Spring Boot 4.x version to $springboot_version"
7059
71-
- name: Build sample artifacts
72-
run: |
73-
./gradlew \
74-
:sentry-samples:sentry-samples-spring-7:war \
75-
:sentry-samples:sentry-samples-spring-7:testClasses
76-
77-
- name: Test sentry-spring-boot-4 integration suites
60+
- name: Test integration suites
7861
run: |
7962
./gradlew \
63+
:sentry-spring-7:integrationTest \
8064
:sentry-spring-boot-4:integrationTest \
8165
:sentry-spring-boot-4:integrationTestWebflux \
8266
:sentry-spring-boot-4:integrationTestOtelNoAgent \
8367
:sentry-spring-boot-4:integrationTestLog4j2 \
8468
:sentry-spring-boot-4:integrationTestOtelAgent \
8569
:sentry-spring-boot-4:integrationTestOtelAgentWithoutAutoInit
8670
87-
- name: Run sentry-samples-spring-7
88-
run: |
89-
python3 test/system-test-runner.py test \
90-
--module "sentry-samples-spring-7" \
91-
--agent false \
92-
--auto-init "true"
93-
9471
- name: Upload test results
9572
if: always()
9673
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
@@ -99,8 +76,6 @@ jobs:
9976
path: |
10077
**/build/reports/*
10178
**/build/test-results/**/*.xml
102-
sentry-mock-server.txt
103-
spring-server.txt
10479
10580
- name: Test Report
10681
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16

‎.github/workflows/system-tests-backend.yml‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ jobs:
4343
- sample: "sentry-samples-spring-boot-4-otlp"
4444
agent: "false"
4545
agent-auto-init: "true"
46-
- sample: "sentry-samples-spring-7"
47-
agent: "false"
48-
agent-auto-init: "true"
4946
- sample: "sentry-samples-spring"
5047
agent: "false"
5148
agent-auto-init: "true"

‎build.gradle.kts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ tasks.register("integrationTests") {
258258
":sentry-spring-boot-4:integrationTestOtelAgent",
259259
":sentry-spring-boot-4:integrationTestOtelAgentWithoutAutoInit",
260260
":sentry-spring-jakarta:integrationTest",
261+
":sentry-spring-7:integrationTest",
261262
)
262263
}
263264

‎sentry-samples/sentry-samples-spring-7/build.gradle.kts‎

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ plugins {
1010
alias(libs.plugins.kotlin.spring)
1111
id("war")
1212
alias(libs.plugins.gretty)
13-
id("io.sentry.systemtest")
1413
}
1514

1615
application { mainClass.set("io.sentry.samples.spring7.Main") }
@@ -51,12 +50,6 @@ dependencies {
5150

5251
implementation(libs.tomcat.catalina.jakarta)
5352
implementation(libs.tomcat.embed.jasper.jakarta)
54-
55-
testImplementation(projects.sentrySystemTestSupport)
56-
testImplementation(libs.kotlin.test.junit)
57-
testImplementation(libs.springboot4.starter.test) {
58-
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
59-
}
6053
}
6154

6255
tasks.withType<KotlinCompile>().configureEach {
@@ -70,22 +63,3 @@ tasks.withType<KotlinCompile>().configureEach {
7063
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
7164
}
7265
}
73-
74-
tasks.register<Test>("systemTest").configure {
75-
group = "verification"
76-
description = "Runs the System tests"
77-
78-
val test = project.extensions.getByType<SourceSetContainer>()["test"]
79-
testClassesDirs = test.output.classesDirs
80-
classpath = test.runtimeClasspath
81-
82-
maxParallelForks = 1
83-
84-
filter { includeTestsMatching("io.sentry.systemtest*") }
85-
}
86-
87-
tasks.named("test").configure {
88-
require(this is Test)
89-
90-
filter { excludeTestsMatching("io.sentry.systemtest.*") }
91-
}

‎sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/DummyTest.kt‎

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/MetricsSystemTest.kt‎

Lines changed: 0 additions & 51 deletions
This file was deleted.

‎sentry-samples/sentry-samples-spring-7/src/test/kotlin/io/sentry/systemtest/PersonSystemTest.kt‎

Lines changed: 0 additions & 85 deletions
This file was deleted.

‎sentry-spring-7/build.gradle.kts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,27 @@ kotlin {
122122
freeCompilerArgs.add("-Xskip-metadata-version-check")
123123
}
124124
}
125+
126+
testing {
127+
suites {
128+
// Runs a plain Spring MVC app in an embedded Tomcat against MockSentryServer, the way a servlet
129+
// container runs a WAR. Spring Boot isn't on its classpath, because Sentry behaves differently
130+
// with it.
131+
register<JvmTestSuite>("integrationTest") {
132+
useJUnit()
133+
dependencies {
134+
implementation(platform(SpringBootPlugin.BOM_COORDINATES))
135+
implementation(project())
136+
implementation(projects.sentryAsyncProfiler)
137+
implementation(projects.sentryTestSupport)
138+
implementation(Config.Libs.springWeb)
139+
implementation(libs.jackson.databind)
140+
implementation(libs.kotlin.test.junit)
141+
implementation(libs.google.truth)
142+
implementation(libs.tomcat.embed.core)
143+
}
144+
}
145+
}
146+
}
147+
148+
tasks.named("check") { dependsOn(testing.suites.named("integrationTest")) }
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package io.sentry.spring7.integrationtest
2+
3+
import io.sentry.test.MockSentryServer
4+
import jakarta.servlet.ServletContainerInitializer
5+
import java.nio.file.Files
6+
import java.util.ServiceLoader
7+
import org.apache.catalina.startup.Tomcat
8+
import org.junit.Before
9+
import org.springframework.http.client.ClientHttpResponse
10+
import org.springframework.web.client.DefaultResponseErrorHandler
11+
import org.springframework.web.client.RestTemplate
12+
import org.springframework.web.util.DefaultUriBuilderFactory
13+
14+
/**
15+
* Drives [AppInitializer]'s app over HTTP and asserts what reaches [server].
16+
*
17+
* Subclasses share one app and one server. Envelopes that arrive late can outlive [server]'s reset,
18+
* so tests match on values only they produce.
19+
*/
20+
abstract class IntegrationTest {
21+
val server = TomcatApp.server
22+
val restTemplate = TomcatApp.restTemplate
23+
24+
@Before
25+
fun resetServer() {
26+
server.reset()
27+
}
28+
}
29+
30+
/**
31+
* The app in an embedded Tomcat, with no Spring Boot on the classpath, so Sentry takes the same
32+
* path as in a WAR. Tomcat starts once per test JVM.
33+
*/
34+
object TomcatApp {
35+
val server = MockSentryServer()
36+
37+
init {
38+
System.setProperty("sentry.dsn", server.dsn)
39+
// The profiler rejects a traces path with a dot anywhere in it, which the module's absolute
40+
// path can have.
41+
System.setProperty(
42+
"sentry.profiling-traces-dir-path",
43+
"${System.getProperty("java.io.tmpdir")}/sentry-integration-test/profiling-traces",
44+
)
45+
}
46+
47+
private val tomcat =
48+
Tomcat().apply {
49+
setBaseDir(Files.createTempDirectory("tomcat").toString())
50+
setPort(0)
51+
// Creates the default connector.
52+
connector
53+
val context = addContext("", Files.createTempDirectory("docbase").toString())
54+
// As Tomcat does for a WAR, runs each initializer the classpath registers: Spring's starts
55+
// AppInitializer's app, and Sentry's adds SentrySpringFilter. Only Spring's uses the set.
56+
ServiceLoader.load(ServletContainerInitializer::class.java).forEach {
57+
context.addServletContainerInitializer(it, setOf(AppInitializer::class.java))
58+
}
59+
start()
60+
}
61+
62+
val restTemplate =
63+
RestTemplate().apply {
64+
uriTemplateHandler =
65+
DefaultUriBuilderFactory("http://localhost:${tomcat.connector.localPort}")
66+
// Returns error responses rather than throwing them, so tests can check a failed request.
67+
errorHandler =
68+
object : DefaultResponseErrorHandler() {
69+
override fun hasError(response: ClientHttpResponse): Boolean = false
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)