Problem/Motivation
When using run-tests.sh with Gitlab CI it doesn't know there were failures because the script always exits with at status of 0.
Proposed resolution
We return exit(1) if there were any failures or exceptions, otherwise exit(0)
Remaining tasks
Discuss the best approach or maybe arguments as to why we shouldn't do this?
User interface changes
n/a
API changes
The exit status for the run-tests.sh script would change.
I'm not sure this is the right approach, but the patch attached demonstrates roughly what i'm suggesting. The patch attached applies to the D7 version of run-tests.sh because thats what I was working with when I came across the issue. I'm happy to re-roll against D8 if there is a consensus e on the approach.
Comment | File | Size | Author |
---|---|---|---|
#170 | failure-without-patch.patch | 414 bytes | David_Rothstein |
#170 | original-patch-with-failure.patch | 6.24 KB | David_Rothstein |
#170 | original-patch.patch | 5.84 KB | David_Rothstein |
#167 | 2189345-39.patch | 5.84 KB | jibran |
Comments
Comment #2
benjy CreditAttribution: benjy commentedSetting back to needs review, didn't mean to trigger the bot.
Comment #3
benjy CreditAttribution: benjy commentedComment #4
sunChanging the exit code to always be 1 in case of any test failures and errors sounds fine to me.
That said, the script already does so, but only in case of fatal errors (and uncaught exceptions if they manage to bubble up into test runner).
Therefore, only two adjustments should be necessary:
Comment #5
benjy CreditAttribution: benjy commentedThis just returns the right statuses from
simpletest_script_execute_batch()
and exits with the right status fromsimpletest_script_run_one_test()
Comment #7
benjy CreditAttribution: benjy commentedI think that could be something to do with how the testbot is called?
Comment #8
jbekker CreditAttribution: jbekker commentedMaybe this is a better approach? We dont want to see the fatal error message whenever a test is failing or has a exception.
Comment #9
jbekker CreditAttribution: jbekker commentedComment #10
sunThis can be written in a single line (conditional argument value instead of conditional code paths).
The PHP exit code can be anything between 0 and 255.
Unless I'm terribly mistaken, a Fatal error yields 255.
In any case, a child process that does not exit with 0 (success) must always trigger a verbose error on the command line, because something/anything blew up in very unexpected ways (not caught by the testing framework's built-in error handling).
Let's consistently return exit codes (ideally constants) instead of Booleans, so that we don't translate them in multiple spots.
This appears to implement what I mentioned in my earlier comment; good start.
However, there is a standard for I/O process exit status codes. We should use the closest matching one.
(unless you verified that 2 is a compatible code already?)
Comment #11
jbekker CreditAttribution: jbekker commentedI've tried to fix most of the things you said or do things a little differently, I'm just not sure what exit code to use, suggestions are welcome! I wasn't able to find a complete list anywhere.
Comment #12
benjy CreditAttribution: benjy commentedIf we're trying to be more granular with the error codes lets use proc_get_status() and return the exact error code?
Comment #13
benjy CreditAttribution: benjy commentedAlso, @jbekker, can you please post interdiffs, it's very hard to follow along otherwise.
Comment #14
jbekker CreditAttribution: jbekker commentedThis would never work of course since it would exit the function after the first PHPUnit tests. I could return the exit code but I think its a little messy. What would a better approach?
@benjy I'll think about interdiffs on next patches.
Comment #15
jbekker CreditAttribution: jbekker commentedAlright, this is the best I can come up with at this moment.
Comment #16
sunBase libc definition of process exist status codes:
http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html
POSIX process exit status codes are defined by sysexits.h in glibc:
- Canonical source: http://osxr.org/glibc/source/misc/sysexits.h
- More elaborate interpretation: http://www.freebsd.org/cgi/man.cgi?query=sysexits&sektion=3
Bash process exit status codes:
http://tldp.org/LDP/abs/html/exitcodes.html
PHPUnit process exit status codes:
https://github.com/sebastianbergmann/phpunit/blob/master/src/TextUI/Test...
Note that
EXCEPTION_EXIT
(2) is used both for (internal) test runner execution errors as well as (user-space) errors in tests. Simpletest makes no differentation between errors and exceptions, so the latter is always FAILURE_EXIT (1).Let's simply be consistent with PHPUnit.
Comment #17
sunIn case this happens, the change should be backported to D7 (+ possibly to the D6 simpletest contrib module), so the test runners are consistent.
Comment #18
sunNeeds to be updated for #2310415: run-tests.sh does not handle the error when invalid test groups/classes are specified
Comment #19
XanoHas this been coordinated with the testbot maintainers? IIRC the testbot relies on exit statuses, but I could be wrong here.
Comment #20
XanoWhy not use
max()
?Comment #21
benjy CreditAttribution: benjy commentedThe bot uses Drush I believe.
Comment #22
sunTestbot is definitely fine. This patch only changes failure conditions anyway. PIFR reports failures despite the lack of proper exit codes already.
Next to #18, @Xano you mentioned in IRC that you encountered an exit code 1 for a passing test (without this patch); any new clues on that, or is that obsolete?
Comment #23
XanoNo new clues on that. Note that Travis says the
run-tests.sh
command exited with 0, but that storing the status in a variable and using it later results in a status of 1. See https://travis-ci.org/bartfeenstra/currency_test/jobs/33989295. Line 3618 contains Travis' result of therun-tests.sh
command and lines 3626 and 3627 are the result of storing the exit status in a variable and printing it in the terminal.Comment #24
Berdir@Xano that is a travis problem, we solved that by moving the exit status parsing to the same line, has nothing to do wit this issue. See https://github.com/md-systems/redirect/commit/f582109358c64e7cf20d26b356...
Comment #27
joshtaylor CreditAttribution: joshtaylor commentedReroll.
For some reason I can't create an interdiff?
Comment #28
joshtaylor CreditAttribution: joshtaylor commentedStraight re-roll, no interdiff.
Comment #29
joshtaylor CreditAttribution: joshtaylor commentedComment #30
joshtaylor CreditAttribution: joshtaylor commentedStraight re-roll, no interdiff.
Comment #31
sanduhrsPatch looks good and applies fine.
It returns 0 on success, 1 on failure/exception and 255 on fatal error.
As per #10 I changed all calls to exit, exit(), exit(1) to exit(SIMPLETEST_SCRIPT_EXIT_SUCCESS) or exit(SIMPLETEST_SCRIPT_EXIT_FAILURE) respectively – just to be more verbose and consistent.
Patch and interdiff attached.
Otherwise this looks ready to go!
Comment #32
sanduhrsD7 backport attached.
Comment #33
benjy CreditAttribution: benjy commentedI've reviewed this patch, I understand a few of the points about exiting with success/failure are just copying the current behaviour but I thought i'd question them anyway.
Is this a success if the number of args is wrong?
Is this a success if we pass unknown args. Right above I see, simpltest_script_print_error ?
Why do we need to check for greater than, can't we just assign the status?
Does this need to check failure or exception?
Same here, i'm a little confused by why we need this check.
Comment #34
sanduhrs1. Changed that to distinguish between --help and missing args
2. Nice catch, changed that too.
And changed some more occurences of SIMPLETEST_SCRIPT_EXIT_SUCCESS after simpletest_script_print_error to SIMPLETEST_SCRIPT_EXIT_FAILURE
3. As multiple tests are run in a batch, we always want to return the most serious status code on exit, not just the last.
4. I don't think so. Exceptions are taken care of in the else statement following 5 lines further down
5. Same as in three.
Attached is a new patch, interdiff and backport updated.
Comment #35
benjy CreditAttribution: benjy commentedOK this looks good to me. I was thinking how does this fit in with the commit policy now we're in beta but I do think it's a significant DX improvement for people using Drupal with CI servers like Travis and Circle. Saves horrible looking one liners like this: https://github.com/larowlan/token/blob/8.x-1.x/.travis.yml#L84
Hopefully the committers agree.
Comment #36
sanduhrsAs per #2189345: run-tests.sh should exit with a failure code if any tests failed this is actually not an API change but rather a correction.
Also, looking at workarounds like
https://github.com/md-systems/redirect/blob/f582109358c64e7cf20d26b35667...
https://github.com/bartfeenstra/currency_test/blob/8.x-3.x/.travis.yml#L83
https://github.com/larowlan/token/blob/8.x-1.x/.travis.yml#L84
from my point of view this should be considered a bugfix.
Comment #37
alexpottYeah I agree this is bugfix but also testing infrastructure changes are not prohibited during beta. This issue is a normal bug fix, and doesn't include any disruptive changes, so it is allowed per https://www.drupal.org/core/beta-changes. Committed 1edfae7 and pushed to 8.0.x. Thanks!
Comment #39
benjy CreditAttribution: benjy commentedUploading patch from #34.
Comment #40
sanduhrsThis is a straight port just missing the phpunit part not available in D7, so it should be just fine.
But I'm not going to RTBC my own patch.
Comment #41
benjy CreditAttribution: benjy commentedI RTBC'd the original, I only uploaded your patch in #39 so I think I can set this back to RTBC.
Comment #42
znerol CreditAttribution: znerol commentedFollow-up #2376039: Undefined property ContainerAwareEventDispatcherTest::results in run-tests.sh.
Comment #43
benjy CreditAttribution: benjy commentedIs it really a follow up? I don't think this issue caused the problem in #2376039: Undefined property ContainerAwareEventDispatcherTest::results in run-tests.sh ?
Comment #44
znerol CreditAttribution: znerol commented@benjy it is not causing the problem, but it currently makes test-results from qa.drupal.org unusable (if there are other errors). For example #2324055-66: Split up the module manager into runtime information and extension information. has only one exceptions and zero test-fails, still the status of the patch is "Failed to run tests: failed during invocation of run-tests.sh.". As a result, the detailed table of test-results is also not displayed on the qa-page, rather only the test log is shown.
Comment #46
alexpottThis is causes issues with testbot reporting... rolling back.
Comment #47
alexpottSee https://qa.drupal.org/pifr/test/910608
Comment #48
alexpottThis patch is causing a random issue with the testbot infrastructure. If there is a fail during a test run, the fails are not reported properly. See https://qa.drupal.org/pifr/test/910608 an example. This test tun had #2376039: Undefined property ContainerAwareEventDispatcherTest::results in run-tests.sh applied so that did not actually fix the issue which is why I reverted this patch.
Comment #49
znerol CreditAttribution: znerol commentedI guess that qa.drupal.org does not expect non-zero exit status unless there is a fatal error. This patch changes the exit status for fatal errors from 1 to 2 and for soft-failures (failed tests) from 0 to 1.
Therefore this needs to be coordinated with the pifr team (probably rfay or jthorson). Maybe it would be possible to commit this in two pieces:
SIMPLETEST_SCRIPT_EXIT_FAILURE
set to 0.SIMPLETEST_SCRIPT_EXIT_FAILURE
to 1.Comment #50
benjy CreditAttribution: benjy commentedI created this issue #2378713: Results broken when run-tests exits with appropriate error code in the hope to get it in front of jthorson, I also left him a tell.
Your input over there would be appreciated.
Comment #51
sanduhrsreroll, no further changes.
Comment #52
sanduhrsneeds test
Comment #53
jsacksick CreditAttribution: jsacksick commentedReroll of the patch in #51.
Comment #56
klausiklausi opened a new pull request for this issue.
Comment #57
klausiJust a reroll, no other changes.
Comment #58
klausiklausi pushed some commits to the pull request.
For an interdiff please see the list of recent commits.
Comment #59
klausiAnother reroll, resolved a merge conflict.
Comment #60
joshtaylor CreditAttribution: joshtaylor commentedReroll for latest HEAD.
Comment #61
joshtaylor CreditAttribution: joshtaylor commentedAttached is a straight reroll, no changes.
Comment #63
pfrenssenI was working around this issue by using Drush to run the tests, since Drush was correctly returning an error code on failure. The test runner now has been removed from Drush: https://github.com/drush-ops/drush/issues/1362
Comment #64
znerol CreditAttribution: znerol commentedThe problem is that we first need to change pifr (or pift?) to detect soft-failure ("Detect a failing test") vs. hard failure ("Detect a test run failure"). See #46ff.
Comment #65
pfrenssenI have started using this but hit a case where tests failed but the script still returned 0: after all tests ran the following exception occurred when the script tries to compile the test results:
This is caused by a too low
wait_timeout
setting in MySQL. I'm using Travis CI and it defaults to only 180 seconds, if a test suite runs longer than this then MySQl closed the connection and this exception is thrown.What would be the best way of solving this? We cannot use
set_exception_handler()
since there is already one being set in the bootstrap. Shall we wrap the entire test runner in a try-catch block?Comment #66
pfrenssenAdded try-catch blocks around all the function calls that do database calls, and also when creating the request since this can also throw a multitude of exceptions.
Comment #67
alberto56 CreditAttribution: alberto56 commentedThis does not work for PHPUnit tests. I made some modifications to the core BlockFormTest (Unit) and BlockCacheTest (requiring database), so that they both fail, and here is the output on Ubuntu:
The web test gives the exit code 1, as expected:
However, when running a unit test, the exit code is still 0, despite the fact that there is a failture (I inserted
$this->assertTrue(FALSE);
in the code):Comment #68
alberto56 CreditAttribution: alberto56 commentedFYI, as a workaround if you do need to have a failure when running PHPUnit tests, until this is corrected, you can run PHPUnit directly like so (this uses the same example as above with a modified version of BlockFormTest which fails):
Comment #69
benjy CreditAttribution: benjy at PreviousNext commentedRe-rolled for head at 7b1ad46
What do we need to do to push this forward? Now we have Drupal CI, is there any chance of trying to get this in before release?
Comment #72
benjy CreditAttribution: benjy at PreviousNext commentedRe-rolled and fixed issues with KTB.
Comment #74
benjy CreditAttribution: benjy at PreviousNext commentedRe-roll for recent changes in simpletest. The patch in #72 works against RC1 if is anyone is using this. Current patch is against RC2
Comment #76
benjy CreditAttribution: benjy at PreviousNext commentedComment #77
benjy CreditAttribution: benjy at PreviousNext commentedGoing to tag this rc eligible, I think it's quite important and it's the test runner only.
Anyone running tests on their d8 project won't get the appropriate failures on CI servers like Jenkins, Travis and Circle Ci without some grep magic or this patch.
Comment #79
larowlannit ===
can we use max() here?
Otherwise this looks good to me
Comment #80
zaporylieComment #81
zaporylieThank you @larowlan for helpful review. Here is a patch with changes you've suggested.
Comment #82
benjy CreditAttribution: benjy at PreviousNext commentedRTBC +1 from me.
Comment #83
sanduhrsTime to fix the codestyle a bit.
Comment #84
zaporylieI'm not entirely sure that we should fix codestyle here. I would rather opt for follow-up issue.
I marked issue RTBC, so committers can look at it and say if we should fix it now or in separate issue.
Comment #86
dawehner@sanduhrs
I think the idea with codestyle issues is to have issues per codestyle rule so we minimize the complexity of reviews.
Comment #87
sanduhrsI'm perfectly fine doing followups, then.
Comment #91
benjy CreditAttribution: benjy at PreviousNext commented#81 is still green.
Comment #93
Mile23Just a heads-up that if you search the issues for the name run-tests.sh you get zero result. I had to use google to get here.
+1 on proper return values from run-tests.sh.
Comment #94
Mile23Here's your coding standards follow-up: #2605290: Improve docs, coding standards for run-tests.sh
Comment #96
zaporylieTestbot was in a bad mood again - back to RTBC.
Comment #98
benjy CreditAttribution: benjy at PreviousNext commentedAdding the triage tag as well just to get approval although i'm hoping it's OK since it's tests only.
Comment #99
alexpott@benjy rc eligible is the correct tag for tests only changes.
Comment #100
alexpottSo have we confirmed that this does not cause any problems for DrupalCI - when this was originally committed we rolled it back because it caused pifr problems. It would be great to have some failing patches that should this doesn't break DrupalCI reporting.
Comment #101
Mile23I'd make a failing test here to demo, but...
The patch in 81 didn't apply, so I tried to reroll.
When I did, there ended up being no diff.
Did this get committed somewhere?
Comment #102
alexpott@Mile23 all sorted now
Comment #104
Mile23So here are two patches.
One is only a module added to
modules/
with two failing tests in it: One each SimpleTest and PHPUnit.The other is the patch from 81 with the same extra module.
Here's what it looks like when I run it locally:
Not sure why it shows me that it found the prefix.
Comment #106
Mile23At the moment the tests-only patch is still running but the 81+tests one says this in the CI log https://dispatcher.drupalci.org/job/default/31559/console :
Comment #108
benjy CreditAttribution: benjy at PreviousNext commentedI guess that leaves us needing help from infrastructure people again. I created #2378713: Results broken when run-tests exits with appropriate error code last time but never got a response.
Comment #109
sanduhrs#2378713: Results broken when run-tests exits with appropriate error code waiting for review.
Comment #110
Mixologic#2378713: Results broken when run-tests exits with appropriate error code is now in production, and I manually requeued the patches in #106. Could somebody more familiar with the changes here evaluate the impact of #2580293: Patch having test with "PHP Fatal error" is marked as PASSED https://www.drupal.org/node/2580293#comment-10558844 and determine if we need to handle anything additional here as a result?
Comment #112
Mile23Here's a reroll after #2580293: Patch having test with "PHP Fatal error" is marked as PASSED
It's a reroll of #104 which is a reroll of #81. :-)
Patch, patch with added failing tests, failing tests only.
Comment #116
benjy CreditAttribution: benjy at PreviousNext commentedWhy is SelectPagerDefaultTest failing in #patch 2 and not #patch 1?
Comment #117
MixologicDunno. I queued it again to see if it was testbot related. Did seem strange that it was a database error like that.
Comment #119
benjy CreditAttribution: benjy at PreviousNext commentedSeems almost random, this time LocalePluralFormatTest, i've queued another run, see if we can get two the same :)
Comment #122
benjy CreditAttribution: benjy at PreviousNext commentedThe last failure had 3, exactly what we were expecting, can we put the other two down to random failures? +1 for RTBC
Comment #125
sanduhrsBoth Database errors seem to be totally unrelated to this patch.
No idea where the error in LocalePluralFormatTest came from, but seems to be unrelated, too.
Everything else working as expected, so:
+1 RTBC
Comment #138
benjy CreditAttribution: benjy at PreviousNext commentedBack as per @124
Comment #146
benjy CreditAttribution: benjy at PreviousNext commentedComment #154
sanduhrsDisabled the by intention failing tests to calm testbot.
Comment #157
sanduhrsMore files to hide.
Comment #159
sanduhrs#112 passes and is RTBC :)
Comment #161
alexpottPersonally I don;t think this can be backported as anyone using run-tests.sh for continuous integration has probably already got their own solutions.
I'm committing this work now because I think it makes sense to have in for Drupal 8.0.0 and represents very little risk now that we've proved the Drupal CI is not broken by this change. Committed 37705f2 and pushed to 8.0.x. Thanks!
Comment #163
benjy CreditAttribution: benjy at PreviousNext commentedAwesome!
Comment #165
cafuego CreditAttribution: cafuego at PreviousNext commentedAlso desperately needed for D7, updating issue status.
Comment #167
jibranRe-uploading the patch form #39 for visibility.
Comment #168
benjy CreditAttribution: benjy at PreviousNext commentedThe bot is green, it seems Drupal CI is working fine for the 7.x branch as well. RTBC
Comment #169
Mixologic+1
I didn't notice this until now, and it's in the other patch, but sending a "There were failed Tests" signal when you do not provide arguments to the script is unusual. It should probably throw the SIMPLETEST_SCRIPT_EXIT_EXCEPTION signal instead, but otherwise LGTM.
+1 on getting this into d7 as is.
Comment #170
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedThis looks good to me and I agree backporting it to Drupal 7 is reasonable (with a release notes mention so people know the exit code is changing).
However based on the above discussion it seems worth double-checking that this doesn't cause any problems with the Drupal 7 testbot actually failing patches that it's supposed to fail, so here is a quick test of that.
Comment #173
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedHm, it looks like there is a problem after all (similar to the ones reported earlier in this issue for the old testbot).
Instead of reporting the failures it's reporting a "CI error" with this in the logs:
I'm setting this back to "needs review" because I don't think there's anything wrong with this patch; however, it may need to wait for changes to the testbot before it can be committed.
Comment #174
alex.skrypnykBeen using #39 for at least 6 month now. Various CI providers handle this properly.
Has the Drupal testbot been updated to be ready for this patch?
Comment #175
alex.skrypnykComment #176
ronaldmulero CreditAttribution: ronaldmulero for edX commented#39 works for me in Travis CI.
Comment #177
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedRe-testing #173.
+1 to the approach, I worked around this in drupal_ti by parsing the output.
Comment #179
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedThis needs to be fixed in DrupalCI first.
Comment #180
MixologicThis is a pretty simple fix in drupalci, and I cant see a whole lot of risk in putting it in now: please watch #2756485: Update drupal7 to use the testcommand for handling signals for updates.
Comment #186
MixologicI've deployed the change to drupalci that will no longer treat signal > 0 coming back from the testrunner as abnormal, now it treats signal > 1 as abnormal, and treats a 1 as "failed tests"
Comment #187
MixologicI also requeued the tests in #170, and the middle one no longer says CI Error, it says 1 Fail, like it should.
Comment #188
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedAwesome, back to RTBC then.
Comment #189
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedMarking for commit later.
Comment #190
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedCommitted to 7.x - thanks!
Comment #192
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedAn interesting side effect of this patch is that if a test fails early (for example, a PDOException in the setUp() method), previously the testbot would report that particular test case as failing. Now it just reports it as "CI error". You can see the difference by comparing the first two tests at https://www.drupal.org/node/1970534#comment-11363869
In some ways this is a good thing - a lot of times when a test fails that early it's because of one of the random testbot failures we sometimes see (i.e. it has nothing to do with the patch that was being tested, so "CI error" is better than a message about a specific test failure).
But for others e.g. PostgreSQL and SQLite tests at https://www.drupal.org/node/2656548#comment-11363217 it would be better to see the actual failures. (Although you still can get them in some form by clicking through to the console output.)
Not sure which we want: A followup to the core patch here to deal with that, or a followup on the testbot to be able to handle this situation?
Because what the current code is doing is this:
And I think the problem comes when it exits with SIMPLETEST_SCRIPT_EXIT_EXCEPTION.
Given that this exception happens either as a result of a failure boostrapping Drupal, or an exception that happens while initializing the test, do we really want to treat it differently than a test which has an exception inside the test results (and which exits with SIMPLETEST_SCRIPT_EXIT_FAILURE instead)?
Comment #193
Fabianx CreditAttribution: Fabianx as a volunteer and at Tag1 Consulting commentedWhat are we doing for Drupal 8 in the same situation? (e.g. on testbot)
I think that is what is important to check first as parity should remove headaches in the future.
Comment #194
Mile23@Fabianx: See #37.
Comment #195
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedFrom the code it looks like it should have the same problem (unless there is a difference on the testbot). I just posted https://www.drupal.org/node/1970534#comment-11383991 to find out.
Comment #196
alexpottI think the difference here is that Drupal 8 does not install a Drupal site in order to run tests. I don't think we backported that change.
Comment #197
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedI think it actually might just be because Drupal 8 does a try/catch around test setUp() methods and Drupal 7 doesn't. That was added in #2170023: Use exceptions when something goes wrong in test setup.
I've created an issue for Drupal 7 to try to at least backport some of that, which hopefully will take care of the regression noted above: #2763435: Exceptions during the setUp() or tearDown() method of a test are not handled
However it's interesting that if you look at my above test results for Drupal 8 (https://dispatcher.drupalci.org/job/default/169015/consoleFull), Drupal 8 is still getting a fatal error about the test runner returning with a non-zero error code (which suggests the script is still exiting with SIMPLETEST_SCRIPT_EXIT_EXCEPTION).... But in Drupal 8 it doesn't prevent it from reporting the issues as test failures. Not quite sure what's going on with that: