Skip to content
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

Pipeline tests simplification #1348

Merged
merged 76 commits into from
May 22, 2023

Conversation

wind57
Copy link
Contributor

@wind57 wind57 commented May 14, 2023

No description provided.

wind57 and others added 30 commits December 4, 2021 07:59
- name: run tests
env:
CURRENT_INDEX: ${{ matrix.current_index }}
NUMBER_OF_JOBS: ${{ matrix.number_of_jobs }}
run: |

# - find all tests
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea of this PR is in these lines, I'll try to explain.

In this removed code, we were trying to find out what tests is this part of the matrix supposed to run. For example, we find out that there are 100 tests to run and there are 10 instances where these are supposed to run, so split 10 tests per instance.
In order to do this, the very first thing we needed is find out the fully qualified class names of the tests that are supposed to run. Why? Because we do not simply call mvn clean install, but instead mvn clean install -DtestsToRun=test1,test2.

This is not trivial. We can not simply look into a class and see if there is a @Test there: it could be abstract, it could be nested, it could parametrized, it could have cases that we are not even aware of (potentially what if junit-6 add one more types?). We were trying our best (with lots of headache) to find the correct test here, but this was not a good idea in general.

Instead, I am proposing a different approach. Let's use junit itself to tell us what these class names are. For that:

  • I created an extension: class DisabledTestsCondition implements ExecutionCondition
  • enabled it via: junit.jupiter.extensions.autodetection.enabled=true
  • enabled it in META-INF/services (in our internal spring-cloud-kubernetes-test-support), via: org.springframework.cloud.kubernetes.tests.commons.junit_extension.DisabledTestsCondition.
  • added the spring-cloud-kubernetes-test-support to all modules that have tests

Changes in the pipeline:

  • first, find the tests, by doing:
./mvnw clean test integration-test -Dskip.build.image=true -Dspring.cloud.k8s.skip.tests=true \
                -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=error \
                -T 1C > /tmp/tests.txt

Notice the -Dspring.cloud.k8s.skip.tests=true. In the extension, if this flag is true:

if ("true".equals(System.getProperty("spring.cloud.k8s.skip.tests"))) {
			System.out.println("spring.cloud.k8s.test.to.run -> " + extensionContext.getRequiredTestClass().getName());
			return ConditionEvaluationResult.disabled("");
		}

that is:

  • I log the class name
  • skip this test class

Next, I upload these test class names in a file: /tmp/tests.txt

  • Then, in each matrix step, I download the test names. Do a little bit of grep and parsing via awk to find the actual fully qualified class name, and the rest of the code remains the same.

Copy link
Contributor Author

@wind57 wind57 May 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few benefits. At least now, we are sure that we get all the tests (I double checked this by doing diffs locally, I can go into the details if needed how I have done that, just let me know). We rely on the junit engine itself to tell us what the tests are, which of course means we will get the correct tests this time.

The downside is that finding tests in this manner takes more time, around 5 minutes more, and 7/8 minutes more per entire run of the pipeline. But I am all in for correctness here and far easier maintenance. This will get even better in my next PR, where I will split the tests in a far more balanced way, so we might not even notice increased time here compared to all the runs until now.

@wind57 wind57 marked this pull request as ready for review May 15, 2023 22:59
@wind57
Copy link
Contributor Author

wind57 commented May 16, 2023

@ryanjbaxter this is ready to be looked at too. I hope it will make sense why I think this is needed.


/**
* This is mainly needed for our pipeline, to get the test classes names.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be useful to provide an example of how to run it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

public class DisabledTestsCondition implements ExecutionCondition {

@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext extensionContext) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this get executed for each test class? What does the resulting output look like?
I assume it looks like

spring.cloud.k8s.test.to.run -> foo.class
spring.cloud.k8s.test.to.run -> bar.class

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is executed for each test class. and the output is indeed the way you showed.

@wind57 wind57 requested a review from ryanjbaxter May 17, 2023 06:19
@@ -37,6 +37,9 @@ jobs:
- name: build with skip tests and skip images
run: ./mvnw -T 1C -s .settings.xml clean install -U -DskipTests -Dskip.build.image=true

- name: find all tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to run this separately? Can we combine it with the steps above where we skip running the tests and but find a list of tests we need to run?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent suggestion! I don't know how I missed this :) thank you

@@ -0,0 +1,20 @@
name: find all tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe its best to rename this now as its purpose is to compile the code and find all tests? I image by combining these two steps we save sometime?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, it was too late for me to do it yesterday... and yes, it saved a few good minutes!

@wind57 wind57 requested a review from ryanjbaxter May 19, 2023 06:10
@wind57
Copy link
Contributor Author

wind57 commented May 22, 2023

do you think there is more to be done here?

@ryanjbaxter ryanjbaxter added this to the 3.0.3 milestone May 22, 2023
@ryanjbaxter ryanjbaxter merged commit e6e6cb6 into spring-cloud:main May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants