From 8f92d9a166c3880447ac9b5cdf56c213de01fd95 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Tue, 22 May 2018 09:41:43 +0100
Subject: [PATCH] Issue #2973127 by vaplas, Mile23, alexpott: Exclude
 *TestBase.php, *Trait.php and *Interface.php files from test discovery
 reflection

---
 core/modules/simpletest/src/TestDiscovery.php  | 12 ++++++++++--
 .../tests/src/Unit/TestDiscoveryTest.php       | 18 ++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/core/modules/simpletest/src/TestDiscovery.php b/core/modules/simpletest/src/TestDiscovery.php
index 219106e80c22..92c12fe60965 100644
--- a/core/modules/simpletest/src/TestDiscovery.php
+++ b/core/modules/simpletest/src/TestDiscovery.php
@@ -282,13 +282,21 @@ public static function scanDirectory($namespace_prefix, $path) {
     $flags |= \FilesystemIterator::SKIP_DOTS;
     $flags |= \FilesystemIterator::FOLLOW_SYMLINKS;
     $flags |= \FilesystemIterator::CURRENT_AS_SELF;
+    $flags |= \FilesystemIterator::KEY_AS_FILENAME;
 
     $iterator = new \RecursiveDirectoryIterator($path, $flags);
-    $filter = new \RecursiveCallbackFilterIterator($iterator, function ($current, $key, $iterator) {
+    $filter = new \RecursiveCallbackFilterIterator($iterator, function ($current, $file_name, $iterator) {
       if ($iterator->hasChildren()) {
         return TRUE;
       }
-      return $current->isFile() && $current->getExtension() === 'php';
+      // We don't want to discover abstract TestBase classes, traits or
+      // interfaces. They can be deprecated and will call @trigger_error()
+      // during discovery.
+      return
+        substr($file_name, -4) === '.php' &&
+        substr($file_name, -12) !== 'TestBase.php' &&
+        substr($file_name, -9) !== 'Trait.php' &&
+        substr($file_name, -13) !== 'Interface.php';
     });
     $files = new \RecursiveIteratorIterator($filter);
     $classes = [];
diff --git a/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php b/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php
index 8b00bb40b38a..4ce189950eb0 100644
--- a/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php
+++ b/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php
@@ -281,6 +281,9 @@ class FunctionalExampleTest {}
               ],
               'Kernel' => [
                 'KernelExampleTest3.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTest3', '@group example2'], $test_file),
+                'KernelExampleTestBase.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTestBase', '@group example2'], $test_file),
+                'KernelExampleTrait.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTrait', '@group example2'], $test_file),
+                'KernelExampleInterface.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleInterface', '@group example2'], $test_file),
               ],
             ],
           ],
@@ -400,6 +403,21 @@ public function testGetTestInfoEmptyDocblock() {
     TestDiscovery::getTestInfo('Drupal\Tests\simpletest\ThisTestDoesNotExistTest', '');
   }
 
+  /**
+   * Ensure TestDiscovery::scanDirectory() ignores certain abstract file types.
+   *
+   * @covers ::scanDirectory
+   */
+  public function testScanDirectoryNoAbstract() {
+    $this->setupVfsWithTestClasses();
+    $files = TestDiscovery::scanDirectory('Drupal\\Tests\\test_module\\Kernel\\', vfsStream::url('drupal/modules/test_module/tests/src/Kernel'));
+    $this->assertNotEmpty($files);
+    $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTestBase', $files);
+    $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTrait', $files);
+    $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleInterface', $files);
+    $this->assertArrayHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTest3', $files);
+  }
+
 }
 
 class TestTestDiscovery extends TestDiscovery {
-- 
GitLab