Skip to content

Commit 6ddda62

Browse files
committed
Add tests for dev services behaviour in devmode
1 parent 3e2f9e6 commit 6ddda62

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

integration-tests/redis-devservices/pom.xml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@
2424
<artifactId>quarkus-junit5</artifactId>
2525
<scope>test</scope>
2626
</dependency>
27+
<dependency>
28+
<groupId>io.quarkus</groupId>
29+
<artifactId>quarkus-devservices-common</artifactId>
30+
<scope>test</scope>
31+
</dependency>
32+
<dependency>
33+
<groupId>io.quarkus</groupId>
34+
<artifactId>quarkus-junit5-internal</artifactId>
35+
<scope>test</scope>
36+
</dependency>
2737
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
2838
<dependency>
2939
<groupId>io.quarkus</groupId>
@@ -103,6 +113,30 @@
103113
<configuration>
104114
<skip>false</skip>
105115
</configuration>
116+
<executions>
117+
<execution>
118+
<id>default-test</id>
119+
<goals>
120+
<goal>test</goal>
121+
</goals>
122+
<configuration>
123+
<excludes>
124+
<exclude>**/continuoustesting/**/*.java</exclude>
125+
</excludes>
126+
</configuration>
127+
</execution>
128+
<execution>
129+
<id>devmode-test</id>
130+
<goals>
131+
<goal>test</goal>
132+
</goals>
133+
<configuration>
134+
<includes>
135+
<include>**/continuoustesting/**/*.java</include>
136+
</includes>
137+
</configuration>
138+
</execution>
139+
</executions>
106140
</plugin>
107141
<plugin>
108142
<artifactId>maven-failsafe-plugin</artifactId>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package io.quarkus.redis.devservices.continuoustesting.it;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
import org.jboss.shrinkwrap.api.ShrinkWrap;
12+
import org.jboss.shrinkwrap.api.asset.StringAsset;
13+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
14+
import org.junit.jupiter.api.Disabled;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.RegisterExtension;
17+
import org.testcontainers.DockerClientFactory;
18+
19+
import com.github.dockerjava.api.model.Container;
20+
import com.github.dockerjava.api.model.ContainerPort;
21+
22+
import io.quarkus.redis.devservices.it.PlainQuarkusTest;
23+
import io.quarkus.test.ContinuousTestingTestUtils;
24+
import io.quarkus.test.QuarkusDevModeTest;
25+
26+
public class DevServicesRedisContinuousTestingTest {
27+
28+
static final String DEVSERVICES_DISABLED_PROPERTIES = ContinuousTestingTestUtils.appProperties(
29+
"quarkus.devservices.enabled=false");
30+
31+
static final String FIXED_PORT_PROPERTIES = ContinuousTestingTestUtils.appProperties(
32+
"quarkus.redis.devservices.port=6377");
33+
34+
static final String UPDATED_FIXED_PORT_PROPERTIES = ContinuousTestingTestUtils.appProperties(
35+
"quarkus.redis.devservices.port=6342");
36+
37+
@RegisterExtension
38+
public static QuarkusDevModeTest test = new QuarkusDevModeTest()
39+
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
40+
.addClasses()
41+
.addAsResource(new StringAsset(ContinuousTestingTestUtils.appProperties("")),
42+
"application.properties"))
43+
.setTestArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClass(PlainQuarkusTest.class));
44+
45+
@Disabled("Not currently working")
46+
@Test
47+
public void testContinuousTestingDisablesDevServicesWhenPropertiesChange() {
48+
ContinuousTestingTestUtils utils = new ContinuousTestingTestUtils();
49+
var result = utils.waitForNextCompletion();
50+
assertEquals(1, result.getTotalTestsPassed());
51+
assertEquals(0, result.getTotalTestsFailed());
52+
53+
// Now let's disable dev services globally ... BOOOOOM! Splat!
54+
test.modifyResourceFile("application.properties", s -> DEVSERVICES_DISABLED_PROPERTIES);
55+
result = utils.waitForNextCompletion();
56+
assertEquals(0, result.getTotalTestsPassed());
57+
assertEquals(1, result.getTotalTestsFailed());
58+
59+
// We could check the container goes away, but we'd have to check slowly, because ryuk can be slow
60+
}
61+
62+
@Test
63+
public void testContinuousTestingReusesInstanceWhenPropertiesAreNotChanged() {
64+
65+
ContinuousTestingTestUtils utils = new ContinuousTestingTestUtils();
66+
var result = utils.waitForNextCompletion();
67+
assertEquals(1, result.getTotalTestsPassed());
68+
assertEquals(0, result.getTotalTestsFailed());
69+
List<Container> redisContainers = getRedisContainers();
70+
71+
// Make a change that shouldn't affect dev services
72+
test.modifyTestSourceFile(PlainQuarkusTest.class, s -> s.replaceAll("redisClient", "updatedRedisClient"));
73+
74+
result = utils.waitForNextCompletion();
75+
assertEquals(1, result.getTestsPassed());
76+
assertEquals(0, result.getTestsFailed());
77+
78+
// Some containers could have disappeared, because ryuk cleaned them up, but no new containers should have appeared
79+
List<Container> newContainers = getRedisContainersExcludingExisting(redisContainers);
80+
assertEquals(0, newContainers.size(),
81+
"New containers: " + newContainers + "\n Old containers: " + redisContainers + "\n All containers: "
82+
+ getAllContainers());
83+
}
84+
85+
@Test
86+
public void testContinuousTestingCreatesANewInstanceWhenPropertiesAreChanged() {
87+
88+
ContinuousTestingTestUtils utils = new ContinuousTestingTestUtils();
89+
var result = utils.waitForNextCompletion();
90+
assertEquals(1, result.getTotalTestsPassed());
91+
assertEquals(0, result.getTotalTestsFailed());
92+
List<Container> existingContainers = new ArrayList<>();
93+
existingContainers.addAll(getRedisContainers());
94+
95+
test.modifyResourceFile("application.properties", s -> FIXED_PORT_PROPERTIES);
96+
97+
result = utils.waitForNextCompletion();
98+
assertEquals(1, result.getTestsPassed());
99+
assertEquals(0, result.getTestsFailed());
100+
101+
// A new container should have appeared
102+
{
103+
List<Container> newContainers = getRedisContainersExcludingExisting(existingContainers);
104+
existingContainers.addAll(newContainers);
105+
assertEquals(1, newContainers.size(),
106+
"New containers: " + newContainers + "\n Old containers: " + existingContainers + "\n All containers: "
107+
+ getAllContainers());
108+
109+
// The new container should be on the new port
110+
List<Integer> ports = Arrays.stream(newContainers.get(0).getPorts())
111+
.map(ContainerPort::getPublicPort)
112+
.toList();
113+
114+
// Oh good, it's one port, so it should be the expected one
115+
assertTrue(ports.contains(6377), "Container ports: " + ports);
116+
}
117+
test.modifyResourceFile("application.properties", s -> UPDATED_FIXED_PORT_PROPERTIES);
118+
119+
result = utils.waitForNextCompletion();
120+
assertEquals(1, result.getTestsPassed());
121+
assertEquals(0, result.getTestsFailed());
122+
123+
// Another new container should have appeared
124+
125+
{
126+
List<Container> newContainers = getRedisContainersExcludingExisting(existingContainers);
127+
assertEquals(1, newContainers.size(),
128+
"New containers: " + newContainers + "\n Old containers: " + existingContainers + "\n All containers: "
129+
+ getAllContainers());
130+
131+
// The new container should be on the new port
132+
List<Integer> ports = Arrays.stream(newContainers.get(0).getPorts())
133+
.map(ContainerPort::getPublicPort)
134+
.toList();
135+
assertTrue(ports.contains(6342), "Container ports: " + ports);
136+
137+
}
138+
}
139+
140+
private static List<Container> getAllContainers() {
141+
return DockerClientFactory.lazyClient().listContainersCmd().exec().stream()
142+
.filter(container -> isRedisContainer(container)).toList();
143+
}
144+
145+
private static List<Container> getRedisContainers() {
146+
return getAllContainers();
147+
}
148+
149+
private static List<Container> getRedisContainersExcludingExisting(Collection<Container> existingContainers) {
150+
return getRedisContainers().stream().filter(
151+
container -> existingContainers.stream().noneMatch(existing -> existing.getId().equals(container.getId())))
152+
.toList();
153+
}
154+
155+
private static boolean isRedisContainer(Container container) {
156+
// The output of getCommand() seems to vary by host OS (it's different on CI and mac), but the image name should be reliable
157+
return container.getImage().contains("redis");
158+
}
159+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.quarkus.redis.devservices.it;
2+
3+
import static org.junit.jupiter.api.Assertions.assertNotNull;
4+
5+
import jakarta.inject.Inject;
6+
7+
import org.junit.jupiter.api.Test;
8+
9+
import io.quarkus.redis.datasource.RedisDataSource;
10+
import io.quarkus.test.junit.QuarkusTest;
11+
12+
@QuarkusTest
13+
public class PlainQuarkusTest {
14+
15+
@Inject
16+
RedisDataSource redisClient;
17+
18+
@Test
19+
public void shouldStartRedisContainer() {
20+
assertNotNull(redisClient);
21+
}
22+
}

0 commit comments

Comments
 (0)