TestRequirementsTrait.php

Same filename and directory in other branches
  1. 9 core/tests/Drupal/Tests/TestRequirementsTrait.php
  2. 10 core/tests/Drupal/Tests/TestRequirementsTrait.php
  3. 11.x core/tests/Drupal/Tests/TestRequirementsTrait.php

Namespace

Drupal\Tests

File

core/tests/Drupal/Tests/TestRequirementsTrait.php

View source
<?php

namespace Drupal\Tests;

use Drupal\Core\Extension\ExtensionDiscovery;
use PHPUnit\Util\Test;
use PHPUnit\Framework\SkippedTestError;

/**
 * Allows test classes to require Drupal modules as dependencies.
 *
 * This trait is assumed to be on a subclass of \PHPUnit\Framework\TestCase, and
 * overrides \PHPUnit\Framework\TestCase::checkRequirements(). This allows the
 * test to be marked as skipped before any kernel boot processes have happened.
 */
trait TestRequirementsTrait {
    
    /**
     * Returns the Drupal root directory.
     *
     * @return string
     */
    protected static function getDrupalRoot() {
        return dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
    }
    
    /**
     * Check module requirements for the Drupal use case.
     *
     * This method is assumed to override
     * \PHPUnit\Framework\TestCase::checkRequirements().
     *
     * @throws \PHPUnit\Framework\SkippedTestError
     *   Thrown when the requirements are not met, and this test should be
     *   skipped. Callers should not catch this exception.
     */
    protected function checkRequirements() {
        if (!$this->getName(FALSE) || !method_exists($this, $this->getName(FALSE))) {
            return;
        }
        $missingRequirements = Test::getMissingRequirements(get_class($this), $this->getName(FALSE));
        if (!empty($missingRequirements)) {
            $this->markTestSkipped(implode(PHP_EOL, $missingRequirements));
        }
        $root = static::getDrupalRoot();
        // Check if required dependencies exist.
        $annotations = $this->getAnnotations();
        if (!empty($annotations['class']['requires'])) {
            $this->checkModuleRequirements($root, $annotations['class']['requires']);
        }
        if (!empty($annotations['method']['requires'])) {
            $this->checkModuleRequirements($root, $annotations['method']['requires']);
        }
    }
    
    /**
     * Checks missing module requirements.
     *
     * Iterates through a list of requires annotations and looks for missing
     * modules. The test will be skipped if any of the required modules is
     * missing.
     *
     * @param string $root
     *   The path to the root of the Drupal installation to scan.
     * @param string[] $annotations
     *   A list of requires annotations from either a method or class annotation.
     *
     * @throws \PHPUnit\Framework\SkippedTestError
     *   Thrown when the requirements are not met, and this test should be
     *   skipped. Callers should not catch this exception.
     */
    private function checkModuleRequirements($root, array $annotations) {
        // drupal_valid_ua() might not be loaded.
        require_once $root . '/core/includes/bootstrap.inc';
        // Make a list of required modules.
        $required_modules = [];
        foreach ($annotations as $requirement) {
            if (strpos($requirement, 'module ') === 0) {
                $required_modules[] = trim(str_replace('module ', '', $requirement));
            }
        }
        // If there are required modules, check if they're available.
        if (!empty($required_modules)) {
            // Scan for modules.
            $discovery = new ExtensionDiscovery($root, FALSE);
            $discovery->setProfileDirectories([]);
            $list = array_keys($discovery->scan('module'));
            $not_available = array_diff($required_modules, $list);
            if (!empty($not_available)) {
                throw new SkippedTestError('Required modules: ' . implode(', ', $not_available));
            }
        }
    }

}

Traits

Title Deprecated Summary
TestRequirementsTrait Allows test classes to require Drupal modules as dependencies.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.