[
https://issues.apache.org/jira/browse/SUREFIRE-2144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17680131#comment-17680131
]
Geoff Soutter edited comment on SUREFIRE-2144 at 2/1/23 5:52 AM:
-----------------------------------------------------------------
OK, so I made a local version of JUnit to explore what a JUnit fix might looks
like. This has ErrorRunningReporter replaced with throw
{{RuntimeException("PREVENTING ...". e)}} in both {{SuiteMethodBuilder}} and
{{{}AllDefaultPossibilitiesBuilder{}}}. When run directly from IDEA, it reports
{{{}"No tests were found"{}}}, which is what we want - no fake tests created.
But when tested with Surefire, slightly different fake test is synthesised. In
this case, we can see the {{initializationFailed}} disappears which makes me
think this fake test was being created by Surefire rather than JUnit -
presumably in {{executeTestSet}} as above.
{code:java}
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.918 s
<<< FAILURE! - in com.project.package.MySuite
[ERROR] com.project.package.MySuite Time elapsed: 0.912 s <<< ERROR!
java.lang.RuntimeException: PREVENTING AllDefaultPossibilitiesBuilder
ErrorReportingRunner
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.safeRunnerForClass(AllDefaultPossibilitiesBuilder.java:63)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:362)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
at
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
at
org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
Caused by: java.lang.RuntimeException: PREVENTING SuiteMethodBuilder
ErrorReportingRunner
at
org.junit.internal.builders.SuiteMethodBuilder.safeRunnerForClass(SuiteMethodBuilder.java:32)
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.safeRunnerForClass(AllDefaultPossibilitiesBuilder.java:59)
... 9 more
Caused by: java.lang.RuntimeException: java.net.ConnectException: Connection
refused (Connection refused)
{code}
So it seems fixing this problem would require changes in both JUnit and
Surefire. Sigh.
was (Author: gsoutter):
OK, so I made a local version of JUnit with the ErrorRunningReporter replaced
with throw {{RuntimeException("PREVENTING ...". e)}} in both
{{SuiteMethodBuilder}} and {{{}AllDefaultPossibilitiesBuilder{}}}. When run
directly from IDEA this reports {{{}"No tests were found"{}}}, which is what we
want - no fake tests created.
But when tested with Surefire, it still synthesizes a slightly different fake
test. In this case, we can see the {{initializationFailed}} disappears which
makes me think this fake test was being created by Surefire rather than JUnit -
presumably in {{executeTestSet}} as above.
{code:java}
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.918 s
<<< FAILURE! - in com.project.package.MySuite
[ERROR] com.project.package.MySuite Time elapsed: 0.912 s <<< ERROR!
java.lang.RuntimeException: PREVENTING AllDefaultPossibilitiesBuilder
ErrorReportingRunner
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.safeRunnerForClass(AllDefaultPossibilitiesBuilder.java:63)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:362)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
at
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
at
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
at
org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
Caused by: java.lang.RuntimeException: PREVENTING SuiteMethodBuilder
ErrorReportingRunner
at
org.junit.internal.builders.SuiteMethodBuilder.safeRunnerForClass(SuiteMethodBuilder.java:32)
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at
org.junit.internal.builders.AllDefaultPossibilitiesBuilder.safeRunnerForClass(AllDefaultPossibilitiesBuilder.java:59)
... 9 more
Caused by: java.lang.RuntimeException: java.net.ConnectException: Connection
refused (Connection refused)
{code}
So it seems fixing this problem would require changes in both JUnit and
Surefire. Sigh.
> Using JUnit4 TestSuite to create test dynamically, synthetic
> initializationError failure breaks Jenkins test history
> --------------------------------------------------------------------------------------------------------------------
>
> Key: SUREFIRE-2144
> URL: https://issues.apache.org/jira/browse/SUREFIRE-2144
> Project: Maven Surefire
> Issue Type: Bug
> Affects Versions: 2.22.2
> Reporter: Geoff Soutter
> Priority: Major
>
> My team is dynamically creating tests using the JUnit3/4 static suite method
> + TestSuite API
> {code}
> public static junit.framework.Test suite() {
> TestSuite testSuite = new TestSuite(xxx);
> for (Test test: tests) {
> testSuite.addTest(yyy);
> }
> return testSuite;
> }
> {code}
> and then running this using Jenkins CI with Surefire.
> There is a nasty failure pattern which periodically deletes the Jenkins test
> history - it resets the Age of all tests in Jenkins back to 1. The history /
> Age report in Jenkins is key for us as it reveals which commit caused the
> failure. We definitely do not want to lose that information.
> The failure pattern goes like this:
> * many tests are running fine, with some failures
> * a commit is made, CI triggers, Jenkins runs surefire.
> ** This results in a problem inside the suite() method, which throws a
> RuntimeException. This is the dynamic test creation phase, before any tests
> are run.
> ** This results in Surefire reporting a successful run of a single
> "fake/synthetic" test which is reported as failed.
> * a commit is made to fix the test creation phase, CI again triggeers,
> Jenkins runs surefire
> ** This results in many tests again running fine, with the same failures as
> before
> ** However, Jenkins now reports all the old failures from the first step as
> Age 1 - all the Age history is lost
> The synthetic test failure looks like so:
> {code}
> [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed:
> 1.064 s <<< FAILURE! - in com.company.package.MySuite
> [ERROR] initializationError(com.company.package.MySuite) Time elapsed: 0.019
> s <<< ERROR!
> java.lang.RuntimeException: java.net.ConnectException: Connection refused
> (Connection refused)
> ...
> at com.company.package.MySuite.suite(MySuite.java:xx)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at
> org.junit.internal.runners.SuiteMethod.testFromSuiteMethod(SuiteMethod.java:35)
> at org.junit.internal.runners.SuiteMethod.<init>(SuiteMethod.java:24)
> at
> org.junit.internal.builders.SuiteMethodBuilder.runnerForClass(SuiteMethodBuilder.java:11)
> at
> org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
> at
> org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
> at
> org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
> at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:362)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
> at
> org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
> at
> org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
> at
> org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
> at
> org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
> at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)
> Caused by: java.net.ConnectException: Connection refused (Connection refused)
> ...
> ... 23 more
>
> [INFO]
> [INFO] Results:
> [INFO]
> [ERROR] Errors:
> [ERROR] MySuite.suite:xx ยป Runtime java.net.ConnectException: Connection
> refused (...
> [INFO]
> [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
> [INFO]
> [INFO]
> ------------------------------------------------------------------------
> [INFO] BUILD SUCCESS
> [INFO]
> ------------------------------------------------------------------------
> {code}
> There is no "initializationError" test in our source code. I presume Surefire
> has created it.
> It seems that the Jenkins JUnit report analysis gets completely confused when
> it does the history analysis in this case. Presumably it tries to compare
> * the "many" passing and failing tests from run N-1 with
> * the single fake test from run N
> After that I presume it decides that those many N-1 tests have been deleted,
> and therefore deletes the history of those tests.
> So it seems that if we value the history analysis, we need to keep the test
> names stable. If so, I suspect the fix is here is that Surefire should never
> create and pretend to run synthetic tests. Rather, the entire run should
> simply fail - I presume throw an exception out of the surefire plugin back to
> maven?
> Hopefully this would then prevent Jenkins from doing the test analysis and it
> will not break the history / Age reporting.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)