Рейтинг:1

Автозагрузка вспомогательных классов в тестах/src/ для phpunit в модуле contrib

флаг in

Я работаю над модулем contrib с тестами phpunit.

В настоящее время в самом модуле нет composer.json или phpunit.xml или процедуры установки, вместо этого нужно запускать функциональные и браузерные тесты с пользовательского сайта drupal, где модуль установлен в web/modules/contrib/*. Пока это работает.

Теперь я хочу использовать вспомогательные классы в тесты/src/помощник/, в пространстве имен "Drupal\Тесты\$имя_модуля\Помощник\" и, возможно, в другом месте.

Однако я заметил, что drupal_phpunit_get_extension_namespaces() регистрирует только некоторые избранные пространства имен внутри "Drupal\Тесты\$имя_модуля\", а не все пространство имен.

Мои вопросы:

  • Почему интеграция Drupal с phpunit ведет себя именно так, вместо регистрации всего тесты/источник/ каталог пространства имен?
  • Как правильно зарегистрировать весь тесты/источник/ каталог в загрузчике классов? Я все еще хочу иметь возможность запускать тесты из установки Drupal вне самого модуля.

РЕДАКТИРОВАТЬ: Новая проблема на drupal.org: #3258817: Почему мы не регистрируем все /tests/src/ для загрузки классов?

Рейтинг:0
флаг in

Здесь я предоставлю грязный обходной путь, который можно легко скопировать без какой-либо корректировки кода.

Могут быть лучшие решения, я открыт для других ответов!

Кроме того, я не обещаю на 100%, что это работает при любых обстоятельствах. Возможно, opcache может преподнести неприятные сюрпризы?

Создайте следующий файл в "tests/src/$modulename/Traits/AutoloadHelperTrait.php". Заменять <MODULENAME> с реальным именем модуля.

<?php

/**
 * @файл
 * Регистрирует весь каталог 'tests/src/' в загрузчике классов.
 *
 * По умолчанию интеграция Drupal с phpunit регистрирует только _some_ namespace
 * каталоги в 'tests/src/' в загрузчике классов. Один из них является
 * '/Черты/'. 
 * Этот обходной путь регистрирует пространство имен верхнего уровня.
 *
 * Код написан таким образом, что его можно легко скопировать в другие модули:
 * - Не зависит от имени модуля.
 * - Не зависит от того, где модуль находится в файловой системе.
 *
 * См. https://drupal.stackexchange.com/questions/309143/autoload-helper-classes-in-tests-src-for-phpunit-in-contrib-module
 *
 * @см. \drupal_phpunit_populate_class_loader()
 * @см. \drupal_phpunit_get_extension_namespaces()
 */

объявить (строгие_типы = 1);

пространство имен Drupal\Tests\<ИМЯ МОДУЛЯ>\Traits;

используйте Composer\Autoload\ClassLoader;

\ call_user_func (статическая функция (): недействительным {
  // Класс Composer ClassLoader всегда присутствует в одном и том же месте
  // внутри каталога поставщика. Оттуда мы можем добраться до
  // autoload.php, чтобы получить настоящий загрузчик классов. 
  $rc = новый \ReflectionClass(ClassLoader::class);
  /** @var \Composer\Autoload\ClassLoader $classLoader */
  $classLoader = требуется имя_каталога($rc->getFileName(), 2) . '/autoload.php';
  // Определяем пространство имен и каталог из магических констант.
  // Это позволяет скопировать код в другое место.
  $level = \substr_count(__NAMESPACE__, '\');
  $dir = dirname(__DIR__, $level - 2);
  // Пространство имен всегда начинается с 'Drupal\Tests\', независимо от
  // имя модуля.
  $nspos = \strpos(__NAMESPACE__, '\', 13);
  $namespace = \substr(__NAMESPACE__, 0, $nspos + 1);
  $classLoader->addPsr4($namespace, $dir);
});

/**
 * Включите этот трейт, чтобы зарегистрировать все тесты/src/ для загрузки класса.
 */
трейт AutoloadHelperTrait {}

Теперь включите трейт в любой тестовый класс, для которого требуется включить эту автозагрузку. Или включите его из тестового базового класса.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.