Problem/Motivation

In #2799021: Ensure a failing PHPUnit test shows enough information via run-tests.sh we added code to allow for PHPUnit test results in simpletest/run-tests.sh reports.

Unfortunately, this results in duplicate fail/error reports in the testbot and other tools, due to extraneous processing of Junit results, among other problems: #2602248: Test result rule name cut off

Finally there is confusion about the meaning of the various result codes sent back by PHPUnit. We often conflate exceptions with runtime errors, and we use integers when we should be using constants.

Proposed resolution

We should normalize on status codes, using a set of constants that are more global in scope than those in run-tests.sh. Accomplish this by creating a TestStatus class which all code can use.

simpletest_run_phpunit_tests() should be modified to not include the junit results of fails, exceptions, or system-level problems.

Remaining tasks

Follow up to add use of TestStatus wherever we deal with test results. Namely run-tests.sh.

Modify simpletest ui result form so it doesn't display errors as exceptions.

Modify the testbot system to adapt to changes from this issue. #2602248: Test result rule name cut off

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Mile23 created an issue. See original summary.

Mile23’s picture

Issue summary: View changes
Status: Active » Needs review
FileSize
3.11 KB

A patch.

Mile23’s picture

Issue tags: +Dublin2016

Status: Needs review » Needs work

The last submitted patch, 2: 2810083_2.patch, failed testing.

dawehner’s picture

Nice!

Mile23’s picture

Issue summary: View changes
Status: Needs work » Needs review
Related issues: +#2602248: Test result rule name cut off

Fixing the tests.

We should probably put this in 8.2.x, or else live with the weird testbot results until 8.3.x :-) #2602248: Test result rule name cut off

The patch applies to 8.2.x, so I'm adding an 8.2.x test here.

Mile23’s picture

Mile23’s picture

Version: 8.3.x-dev » 8.2.x-dev
Mixologic’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Test/TestStatus.php
@@ -0,0 +1,36 @@
+  const SYSTEM = 3;

+++ b/core/modules/simpletest/simpletest.module
@@ -183,29 +184,15 @@ function simpletest_run_phpunit_tests($test_id, array $unescaped_test_classnames
+      'status' => TestStatus::labelForCode($status),

SYSTEM can be any number between 3 and 127, so Im not sure this would work. You may have to fill the status map in labelForCode with all the possible system signal errors. Everywhere we see SYSTEM we'll have to make sure we never say === we'll always have to test with >= SYSTEM as it will almost never be 3. Segfaults end up being signal 11, and there is a slew of other signals that are different from OS to OS. Suffice to say if its > 2, we consider all of those signals to be abnormal aborts as if it were a segfault.

More info here: http://php.net/manual/en/pcntl.constants.php

Otherwise, the rest of this is pretty sweet polish. Me gusta. ++

Mile23’s picture

Status: Needs work » Needs review
FileSize
5.89 KB
4.07 KB

Hah. I replicated the same mistake, just one integer higher.

OK:

Changed the name of labelForCode() to just label() because that's better.

label() now tells you the result code for TestStatus::SYSTEM codes, like this: error: 3 This might not be good. Please opine.

Updated the test.

Added better docs, explaining that TestStatus::SYSTEM is a lower limit.

Mixologic’s picture

+++ b/core/lib/Drupal/Core/Test/TestStatus.php
@@ -0,0 +1,64 @@
+    if ($status >= static::SYSTEM) {
+      $label = $label . ': ' . $status;
+    }

I would leave the status code off of the label. Signal numbers vary from OS to OS, so its doubtful that we'd ever want logic branches based on the signal number - easier to say if ('error') than to substr for 'error' etc. It might be interesting to have that data, but something tells me that at most we'll only ever see a few signals there.

Otherwise, still LGTM.

Mile23’s picture

OK. Took away the status code on the 'error' label and changed the tests.

dawehner’s picture

This looks quite great and almost ready.

+++ b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
@@ -10,12 +11,20 @@
-      exit(2);
+      exit(TestStatus::FAIL);
+    }
+    if (getenv('SimpletestPhpunitRunCommandTestWillDie') === 'exception') {
+      exit(TestStatus::EXCEPTION);
+    }
+    if (getenv('SimpletestPhpunitRunCommandTestWillDie') === 'error') {
+      exit(TestStatus::SYSTEM);
     }

Should we also have a test for the case of exit code > 2?

Mile23’s picture

Sometimes, when you ask for one thing, you get five more. :-)

Refactored the test a bit, in order to get rid of @runTestsInSeparateProcesses and to speed things up. We can't use a vfsStream here because the exec()'d stub test doesn't share memory with the real test.

dawehner’s picture

  1. +++ b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
    @@ -12,21 +9,19 @@
    +    $status = (int)getenv('SimpletestPhpunitRunCommandTestWillDie');
    

    afaik we use a space after the casting

  2. +++ b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php
    @@ -12,21 +9,19 @@
    +    else exit($status);
    

    Note: this is not our CS

  3. +++ b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
    @@ -3,35 +3,99 @@
    +    include_once self::$root . '/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php';
    ...
    +    include_once self::$root . '/core/modules/simpletest/simpletest.module';
    

    Includes change global state and given that we should run in a separate process

  4. +++ b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
    @@ -3,35 +3,99 @@
    +    // All status codes 3 and above should be labeled 'error'.
    +    // @todo: The valid values here would be 3 to 127. But since the test
    +    // touches the file system a lot, we only have 3, 4, and 127 for speed.
    +    foreach ([3, 4, 127] as $status) {
    +      $data[] = [$status, 'error'];
         }
    

    Nice additional test coverage

Mile23’s picture

Thanks.

#15.3: It's not that all includes add globals, it's that simpletest_phpunit_run_command() declares global $base_url. As long as we clean up afterwards there's no problem. Also, if we end up adding more globals to the code touched by the test, the test will show up as risky and we might learn something.

Anyway, setting @runTestsInSeparateProcesses because why not. :-)

All issues addressed.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you!

Mixologic’s picture

This would be great to get in sooner than later. Would help with fixing a lot of strange wtf reporting issues with errors.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 16: 2810083_16.patch, failed testing.

Mile23’s picture

Status: Needs work » Reviewed & tested by the community

Testbot is back to passing now. Patch in #16 applies locally. Setting back to RTBC and starting test again.

elachlan’s picture

It all passes and is RTBC, can we include it?

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 30f78fc to 8.3.x and 81ef407 to 8.2.x. Thanks!

I've committed this to 8.2.x as well because this part of the test-runner which should be viewed as @internal and correct reporting of results on DrupalCI outweighs any risks to alternate test runner implementations.

diff --git a/core/lib/Drupal/Core/Test/TestStatus.php b/core/lib/Drupal/Core/Test/TestStatus.php
index 47216f7..b70dcdd 100644
--- a/core/lib/Drupal/Core/Test/TestStatus.php
+++ b/core/lib/Drupal/Core/Test/TestStatus.php
@@ -59,4 +59,5 @@ public static function label($status) {
     $label = $statusMap[$status > static::SYSTEM ? static::SYSTEM : $status];
     return $label;
   }
+
 }
diff --git a/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
index 7cd3fc7..a96db96 100644
--- a/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
+++ b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php
@@ -4,7 +4,6 @@
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\File\FileSystemInterface;
-use Drupal\Tests\simpletest\Unit\SimpletestPhpunitRunCommandTestWillDie;
 
 /**
  * Tests simpletest_run_phpunit_tests() handles PHPunit fatals correctly.

Minor code style stuff fixed on commit.

  • alexpott committed 30f78fc on 8.3.x
    Issue #2810083 by Mile23, dawehner, Mixologic: Duplicate test results...

  • alexpott committed 81ef407 on 8.2.x
    Issue #2810083 by Mile23, dawehner, Mixologic: Duplicate test results...
Mixologic’s picture

Yay!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.