-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve finding tests (1) #1420
Changes from 8 commits
a58cc72
2b2fd43
54edbb4
1457d68
cc3c700
73b3e27
7d6fded
5d848aa
0b24a1f
a32bf85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,12 +47,12 @@ runs: | |
|
||
# save with the current run_id, but restore it without it. This means two things: | ||
# 1) if we re-run, cache will be available | ||
# 2) if there is a new run, we restore as '${{ runner.os }}-spring-cloud-kubernetes-existing-test-times-cache-' | ||
# 2) if there is a new run, we restore as '${{ runner.os }}-spring-cloud-k8s-existing-test-times-cache-' | ||
# meaning there could be many of them already present and this is not an exact match | ||
# github in this case will pick up the latest one, exactly what we want. | ||
- name: save test times in cache | ||
uses: actions/cache/save@v3 | ||
if: env.BASE_BRANCH != '2.1.x' | ||
with: | ||
path: /tmp/sorted.txt | ||
key: ${{ runner.os }}-spring-cloud-kubernetes-existing-test-times-cache-${{ github.run_id }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with the change from |
||
key: ${{ runner.os }}-spring-cloud-k8s-existing-test-times-cache-${{ github.run_id }} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ | |
/** | ||
* @author wind57 | ||
*/ | ||
public class AbstractKubernetesProfileEnvironmentPostProcessorTest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is an interesting one too. Now that we use the proper way to find tests, junit-5 finds this one. On the other hand because the name in the test contains |
||
public class KubernetesProfileEnvironmentPostProcessorTest { | ||
|
||
private static final String FOUNT_IT = "foundIt"; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,9 +13,15 @@ | |
|
||
<properties> | ||
<awaitility.version>4.0.3</awaitility.version> | ||
<testcontainers.version>1.18.0</testcontainers.version> | ||
<testcontainers.version>1.19.0</testcontainers.version> | ||
</properties> | ||
<dependencies> | ||
|
||
<dependency> | ||
<groupId>org.junit.platform</groupId> | ||
<artifactId>junit-platform-launcher</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
|
@@ -43,4 +49,24 @@ | |
|
||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.codehaus.mojo</groupId> | ||
<artifactId>exec-maven-plugin</artifactId> | ||
<version>3.1.0</version> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>java</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wind57 I think we need to skip this unless a specific profile is activated. In other words we should only due this is we are running on GitHub actions. If we don't generate the tmp file before running the build, the build will fail. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah! indeed, I did not think about this. PR is out |
||
<mainClass>org.springframework.cloud.kubernetes.tests.discovery.TestsDiscovery</mainClass> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright 2013-2023 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.springframework.cloud.kubernetes.tests.discovery; | ||
|
||
import java.io.File; | ||
import java.net.URI; | ||
import java.net.URL; | ||
import java.net.URLClassLoader; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.List; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
import org.junit.platform.engine.discovery.DiscoverySelectors; | ||
import org.junit.platform.launcher.Launcher; | ||
import org.junit.platform.launcher.LauncherDiscoveryRequest; | ||
import org.junit.platform.launcher.TestIdentifier; | ||
import org.junit.platform.launcher.TestPlan; | ||
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | ||
import org.junit.platform.launcher.core.LauncherFactory; | ||
|
||
/** | ||
* @author wind57 | ||
*/ | ||
public class TestsDiscovery { | ||
|
||
public static void main(String[] args) throws Exception { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it turns out I was wrong, here is the story. We need to find what tests we have without running them. Initially, of course, I went to stackoverflow and the solution that we currently have seemed reasonable. But then, I read a bit of junit-5 documentation and found this, which clearly says:
Exactly what we want to achieve: a dedicated feature/api to find out what tests we have. How this works is you tell junit where to find classes + classpath to use when searching for those. That is why before this class is called, I have two pipeline stepts:
the first one takes care to create There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the added benefit is that this is even faster then the previous solution |
||
List<String> targetClasses = entireClasspath().stream().filter(x -> x.contains("target/classes")).toList(); | ||
List<String> targetTestClasses = targetClasses.stream().map(x -> x.replace("classes", "test-classes")).toList(); | ||
List<String> jars = entireClasspath().stream().filter(x -> x.contains(".jar")).toList(); | ||
|
||
List<URL> urls = Stream.of(targetClasses, targetTestClasses, jars).flatMap(List::stream) | ||
.map(x -> toURL(new File(x).toPath().toUri())).toList(); | ||
|
||
Set<Path> paths = Stream.of(targetClasses, targetTestClasses, jars).flatMap(List::stream).map(Paths::get) | ||
.collect(Collectors.toSet()); | ||
|
||
replaceClassloader(urls); | ||
|
||
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() | ||
.selectors(DiscoverySelectors.selectClasspathRoots(paths)).build(); | ||
|
||
Launcher launcher = LauncherFactory.openSession().getLauncher(); | ||
TestPlan testPlan = launcher.discover(request); | ||
testPlan.getRoots().stream().flatMap(x -> testPlan.getChildren(x).stream()) | ||
.map(TestIdentifier::getLegacyReportingName).sorted().forEach(test -> { | ||
System.out.println("spring.cloud.k8s.test.to.run -> " + test); | ||
}); | ||
} | ||
|
||
private static void replaceClassloader(List<URL> classpathURLs) { | ||
ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); | ||
URLClassLoader classLoader = URLClassLoader.newInstance(classpathURLs.toArray(new URL[0]), parentClassLoader); | ||
Thread.currentThread().setContextClassLoader(classLoader); | ||
} | ||
|
||
// /tmp/deps.txt are created by the pipeline | ||
private static List<String> entireClasspath() throws Exception { | ||
return Files.lines(Paths.get("/tmp/deps.txt")).distinct().collect(Collectors.toList()); | ||
} | ||
|
||
private static URL toURL(URI uri) { | ||
try { | ||
return uri.toURL(); | ||
} | ||
catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have a series of problems that are waiting to pop-up and I am fixing them here, granted I created them via various changes.
For example this change:
./mvnw test -B -Dskip.build.image=true
. It used to be./mvnw clean install -B -Dskip.build.image=true
. Sotest
instead ofclean install
. This will cause three problems:The first one can already be seen here. TL;DR : when we re-name things, instead of compiling with these new changes, we will try to compile with the ones from cache. Since there were renames - compilation will fail. As such, we really need
install
here.The second one is that with this
test
goal, we will not find any integration tests (integration-test
goal was take when we hadinstall
). And this is a serious problem. This means that our cache will never contain times for integration tests, which in turn means that at some point in time, the last step of some matrix will need to run all integration tests - and it will fail since there are too many of them. I already "caught" this issue in a build here.The third one has to do with the way we find tests without running them, I will comment more under the appropriate files.