TestRequirementsTrait.php 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <?php
  2. namespace Drupal\Tests;
  3. use Drupal\Core\Extension\ExtensionDiscovery;
  4. /**
  5. * Allows test classes to require Drupal modules as dependencies.
  6. *
  7. * This trait is assumed to be on a subclass of \PHPUnit_Framework_TestCase, and
  8. * overrides \PHPUnit_Framework_TestCase::checkRequirements(). This allows the
  9. * test to be marked as skipped before any kernel boot processes have happened.
  10. */
  11. trait TestRequirementsTrait {
  12. /**
  13. * Returns the Drupal root directory.
  14. *
  15. * @return string
  16. */
  17. protected static function getDrupalRoot() {
  18. return dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
  19. }
  20. /**
  21. * Check module requirements for the Drupal use case.
  22. *
  23. * This method is assumed to override
  24. * \PHPUnit_Framework_TestCase::checkRequirements().
  25. *
  26. * @throws \PHPUnit_Framework_SkippedTestError
  27. * Thrown when the requirements are not met, and this test should be
  28. * skipped. Callers should not catch this exception.
  29. */
  30. protected function checkRequirements() {
  31. parent::checkRequirements();
  32. $root = static::getDrupalRoot();
  33. // Check if required dependencies exist.
  34. $annotations = $this->getAnnotations();
  35. if (!empty($annotations['class']['requires'])) {
  36. $this->checkModuleRequirements($root, $annotations['class']['requires']);
  37. }
  38. if (!empty($annotations['method']['requires'])) {
  39. $this->checkModuleRequirements($root, $annotations['method']['requires']);
  40. }
  41. }
  42. /**
  43. * Checks missing module requirements.
  44. *
  45. * Iterates through a list of requires annotations and looks for missing
  46. * modules. The test will be skipped if any of the required modules is
  47. * missing.
  48. *
  49. * @param string $root
  50. * The path to the root of the Drupal installation to scan.
  51. * @param string[] $annotations
  52. * A list of requires annotations from either a method or class annotation.
  53. *
  54. * @throws \PHPUnit_Framework_SkippedTestError
  55. * Thrown when the requirements are not met, and this test should be
  56. * skipped. Callers should not catch this exception.
  57. */
  58. private function checkModuleRequirements($root, array $annotations) {
  59. // drupal_valid_ua() might not be loaded.
  60. require_once $root . '/core/includes/bootstrap.inc';
  61. // Make a list of required modules.
  62. $required_modules = [];
  63. foreach ($annotations as $requirement) {
  64. if (strpos($requirement, 'module ') === 0) {
  65. $required_modules[] = trim(str_replace('module ', '', $requirement));
  66. }
  67. }
  68. // If there are required modules, check if they're available.
  69. if (!empty($required_modules)) {
  70. // Scan for modules.
  71. $discovery = new ExtensionDiscovery($root, FALSE);
  72. $discovery->setProfileDirectories([]);
  73. $list = array_keys($discovery->scan('module'));
  74. $not_available = array_diff($required_modules, $list);
  75. if (!empty($not_available)) {
  76. throw new \PHPUnit_Framework_SkippedTestError('Required modules: ' . implode(', ', $not_available));
  77. }
  78. }
  79. }
  80. }