Commit 85215b03 authored by catch's avatar catch
Browse files

Issue #3497431 by mondrake, catch, larowlan, godotislate, jonathan1055,...

Issue #3497431 by mondrake, catch, larowlan, godotislate, jonathan1055, fjgarlin, xjm: Deprecate TestDiscovery test file scanning, use PHPUnit API instead

(cherry picked from commit 375995de)
parent ca266be9
Loading
Loading
Loading
Loading
Loading
+67 −6
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@

use Drupal\Core\Test\Exception\MissingGroupException;
use Drupal\TestTools\PhpUnitCompatibility\RunnerVersion;
use PHPUnit\Event\EventFacadeIsSealedException;
use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Framework\DataProviderTestSuite;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
@@ -20,6 +22,13 @@
 */
class PhpUnitTestDiscovery {

  /**
   * The singleton.
   *
   * @var \Drupal\Core\Test\PhpUnitTestDiscovery|null
   */
  private static ?self $instance = NULL;

  /**
   * The map of legacy test suite identifiers to phpunit.xml ones.
   *
@@ -41,6 +50,11 @@ class PhpUnitTestDiscovery {
   */
  private array $reverseMap;

  /**
   * Path to PHPUnit's configuration file.
   */
  private string $configurationFilePath;

  /**
   * The warnings generated during the discovery.
   *
@@ -48,10 +62,33 @@ class PhpUnitTestDiscovery {
   */
  private array $warnings = [];

  public function __construct(
    private string $configurationFilePath,
  ) {
  private function __construct() {
    $this->reverseMap = array_flip($this->map);
    try {
      EventFacade::instance()->registerTracer(new PhpUnitTestDiscoveryTracer($this));
      EventFacade::instance()->seal();
    }
    catch (EventFacadeIsSealedException) {
      // Just continue.
    }
  }

  /**
   * Returns the singleton instance.
   */
  public static function instance(): self {
    if (self::$instance === NULL) {
      self::$instance = new self();
    }
    return self::$instance;
  }

  /**
   * Sets the configuration file path.
   */
  public function setConfigurationFilePath(string $configurationFilePath): self {
    $this->configurationFilePath = $configurationFilePath;
    return $this;
  }

  /**
@@ -109,9 +146,11 @@ public function getTestClasses(?string $extension = NULL, array $testSuites = []
    }
    $phpUnitTestSuite = (new TestSuiteBuilder())->build($phpUnitConfiguration);
    if (isset($containerObjectId) && $containerObjectId !== spl_object_id(\Drupal::getContainer())) {
      $this->warnings[] = '*** The service container was changed during the test discovery ***';
      $this->warnings[] = 'Probably a test data provider method called \\Drupal::setContainer.';
      $this->warnings[] = 'Ensure that all the data providers restore the original container before returning data.';
      $this->addWarning(
        ">>> The service container was changed during the test discovery <<<\n" .
        "Probably, a test data provider method called \\Drupal::setContainer().\n" .
        "Ensure that all the data providers restore the original container before returning data."
      );
      assert(isset($container));
      \Drupal::setContainer($container);
    }
@@ -152,6 +191,16 @@ public function findAllClassFiles(?string $extension = NULL, ?string $directory
    return $classMap;
  }

  /**
   * Adds warning message generated during the discovery.
   *
   * @param string $message
   *   The warning message.
   */
  public function addWarning(string $message): void {
    $this->warnings[] = $message;
  }

  /**
   * Returns the warnings generated during the discovery.
   *
@@ -180,6 +229,10 @@ private function getTestList(TestSuite $phpUnitTestSuite, ?string $extension): a
    $list = [];
    foreach ($phpUnitTestSuite->tests() as $testSuite) {
      foreach ($testSuite->tests() as $testClass) {
        if ($testClass->isEmpty()) {
          continue;
        }

        if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) {
          continue;
        }
@@ -218,6 +271,10 @@ private function getTestListLimitedToDirectory(TestSuite $phpUnitTestSuite, ?str

    // In this case, PHPUnit found a single test class to run tests for.
    if ($phpUnitTestSuite->isForTestClass()) {
      if ($phpUnitTestSuite->isEmpty()) {
        return [];
      }

      if ($extension !== NULL && !str_starts_with($phpUnitTestSuite->name(), "Drupal\\Tests\\{$extension}\\")) {
        return [];
      }
@@ -239,6 +296,10 @@ private function getTestListLimitedToDirectory(TestSuite $phpUnitTestSuite, ?str
    // Multiple test classes were found.
    $list = [];
    foreach ($phpUnitTestSuite->tests() as $testClass) {
      if ($testClass->isEmpty()) {
        continue;
      }

      if ($extension !== NULL && !str_starts_with($testClass->name(), "Drupal\\Tests\\{$extension}\\")) {
        continue;
      }
+38 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Core\Test;

use PHPUnit\Event\Event;
use PHPUnit\Event\Test\PhpunitErrorTriggered;
use PHPUnit\Event\Test\PhpunitWarningTriggered;
use PHPUnit\Event\TestRunner\WarningTriggered;
use PHPUnit\Event\Tracer\Tracer;

/**
 * Traces events dispatched by PHPUnit during the test discovery.
 *
 * @internal
 */
class PhpUnitTestDiscoveryTracer implements Tracer {

  public function __construct(
    private readonly PHPUnitTestDiscovery $testDiscovery,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public function trace(Event $event): void {
    if (in_array(get_class($event), [
      PhpunitErrorTriggered::class,
      PhpunitWarningTriggered::class,
      WarningTriggered::class,
    ])) {
      $this->testDiscovery->addWarning(sprintf('%s: %s', get_class($event), $event->message()));
    }
  }

}
+11 −5
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@
  // Display all available tests organized by one @group annotation.
  echo "\nAvailable test groups & classes\n";
  echo "-------------------------------\n\n";
  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  $test_discovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  try {
    $groups = $test_discovery->getTestClasses($args['module']);
    foreach ($test_discovery->getWarnings() as $warning) {
@@ -122,7 +122,7 @@
// @see https://www.drupal.org/node/2569585
if ($args['list-files'] || $args['list-files-json']) {
  // List all files which could be run as tests.
  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  $test_discovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  // PhpUnitTestDiscovery::findAllClassFiles() gives us a classmap similar to a
  // Composer 'classmap' array.
  $test_classes = $test_discovery->findAllClassFiles();
@@ -934,14 +934,20 @@ function simpletest_script_command(TestRun $test_run, string $test_class): array
function simpletest_script_get_test_list() {
  global $args;

  $test_discovery = new PhpUnitTestDiscovery(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  $test_discovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath(\Drupal::root() . \DIRECTORY_SEPARATOR . 'core');
  $test_list = [];
  $slow_tests = [];
  if ($args['all'] || $args['module'] || $args['directory']) {
    try {
      $groups = $test_discovery->getTestClasses($args['module'], $args['types'], $args['directory']);
      foreach ($test_discovery->getWarnings() as $warning) {
        simpletest_script_print($warning . "\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
      $warnings = $test_discovery->getWarnings();
      if (!empty($warnings)) {
        simpletest_script_print("Test discovery warnings\n", SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE);
        simpletest_script_print("-----------------------\n", SIMPLETEST_SCRIPT_COLOR_BRIGHT_WHITE);
        foreach ($warnings as $warning) {
          simpletest_script_print('* ' . $warning . "\n\n", SIMPLETEST_SCRIPT_COLOR_EXCEPTION);
        }
        echo "\n";
      }
    }
    catch (Exception $e) {
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public function testEquality(?string $extension = NULL, ?string $directory = NUL
    if (RunnerVersion::getMajor() >= 11) {
      $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml';
    }
    $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath);
    $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath);
    $phpUnitList = $phpUnitTestDiscovery->findAllClassFiles($extension, $directory);

    // Legacy TestDiscovery.
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public function testEquality(array $suites, ?string $extension = NULL, ?string $
    if (RunnerVersion::getMajor() >= 11) {
      $configurationFilePath .= \DIRECTORY_SEPARATOR . '.phpunit-next.xml';
    }
    $phpUnitTestDiscovery = new PhpUnitTestDiscovery($configurationFilePath);
    $phpUnitTestDiscovery = PhpUnitTestDiscovery::instance()->setConfigurationFilePath($configurationFilePath);
    $phpUnitList = $phpUnitTestDiscovery->getTestClasses($extension, $suites, $directory);

    // Legacy TestDiscovery.