Commit 61d9b66c authored by DaveD's avatar DaveD
Browse files

fix autoloading and bootstrap

parent 4b019dc6
......@@ -5,7 +5,7 @@
https://www.drupal.org/node/2116263 for details.
-->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="../../../../../../../web/core/tests/bootstrap.php"
bootstrap="tests/phpunit/bootstrap.mink.php"
colors="true"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutOutputDuringTests="true"
......
<?php
// @todo fix autoloading in this extension - something is off
require_once 'Base.php';
/**
* @group headless
......
<?php
namespace Cdntaxreceipts\Tests\Mink;
require_once 'CdntaxreceiptsBase.php';
namespace Civi\Cdntaxreceipts\Tests\Mink;
/**
* @group mink
*/
class AggregateTest extends CdntaxreceiptsBase {
/**
......
<?php
namespace Cdntaxreceipts\Tests\Mink;
namespace Civi\Cdntaxreceipts\Tests\Mink;
use Drupal\Tests\civicrm\FunctionalJavascript\CiviCrmTestBase;
/**
* @group mink
*/
class CdntaxreceiptsBase extends CiviCrmTestBase {
use \Drupal\Tests\mink_civicrm_helpers\Traits\Utils;
......@@ -126,7 +129,7 @@ class CdntaxreceiptsBase extends CiviCrmTestBase {
* @return string
*/
protected function getFixtureFileFor(string $class, string $func, $type = '.pdf') {
return str_replace('\\', '/', __DIR__) . '/fixtures/' . preg_replace('/[^a-zA-Z0-9_]/', '_', "{$class}{$func}") . $type;
return str_replace('\\', '/', __DIR__) . '/../../../../fixtures/' . preg_replace('/[^a-zA-Z0-9_]/', '_', "{$class}{$func}") . $type;
}
/**
......
<?php
namespace Cdntaxreceipts\Tests\Mink;
// This feels awkward, but the extension and civi aren't installed yet, so the
// autoloader at the time this gets compiled won't be able to find it since
// it's within our extension. Or at least that seems like what's happening.
require_once 'CdntaxreceiptsBase.php';
namespace Civi\Cdntaxreceipts\Tests\Mink;
/**
* @group mink
*/
class IssueTest extends CdntaxreceiptsBase {
/**
......
<?php
/**
* @file
* Autoloader for Drupal PHPUnit testing.
*
* @see phpunit.xml.dist
*/
use Drupal\Component\Assertion\Handle;
use Drupal\TestTools\PhpUnitCompatibility\PhpUnit8\ClassWriter;
/**
* This file is going to be in the extension, but we have no idea where the
* extension is relative to drupal. If it's in a shared central location among
* multiple sites this won't work, but you can set the environment variable in
* phpunit.mink.xml. We don't have access to any drupal functions right now
* to find it, so brute force assuming we are somewhere under the root.
*/
function drupal_find_top_root() {
if ($dir = getenv('DRUPAL_PROJECT_ROOT')) {
return $dir;
}
$dir = dirname(__DIR__, 1);
// just avoid infinite loop - if it can't find it you'll need to set the environment var
for ($loop_count = 0; $loop_count < 30; $loop_count++) {
if (file_exists("$dir/web") && file_exists("$dir/vendor")) {
return $dir;
}
$dir = dirname($dir, 1);
}
throw new \Exception("Can't find drupal project root. Please set the environment var DRUPAL_PROJECT_ROOT in phpunit.mink.xml pointing to the top-level folder containing web and vendor.");
}
$top_root = drupal_find_top_root();
/**
* Finds all valid extension directories recursively within a given directory.
*
* @param string $scan_directory
* The directory that should be recursively scanned.
*
* @return array
* An associative array of extension directories found within the scanned
* directory, keyed by extension name.
*/
function drupal_phpunit_find_extension_directories($scan_directory) {
$extensions = [];
$dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($scan_directory, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
foreach ($dirs as $dir) {
if (strpos($dir->getPathname(), '.info.yml') !== FALSE) {
// Cut off ".info.yml" from the filename for use as the extension name. We
// use getRealPath() so that we can scan extensions represented by
// directory aliases.
$extensions[substr($dir->getFilename(), 0, -9)] = $dir->getPathInfo()
->getRealPath();
}
}
return $extensions;
}
/**
* Returns directories under which contributed extensions may exist.
*
* @param string $root
* (optional) Path to the root of the Drupal installation.
*
* @return array
* An array of directories under which contributed extensions may exist.
*/
function drupal_phpunit_contrib_extension_directory_roots($root = NULL) {
if ($root === NULL) {
$root = dirname(__DIR__, 2);
}
$paths = [
$root . '/core/modules',
$root . '/core/profiles',
$root . '/core/themes',
$root . '/modules',
$root . '/profiles',
$root . '/themes',
];
$sites_path = $root . '/sites';
// Note this also checks sites/../modules and sites/../profiles.
foreach (scandir($sites_path) as $site) {
if ($site[0] === '.' || $site === 'simpletest') {
continue;
}
$path = "$sites_path/$site";
$paths[] = is_dir("$path/modules") ? realpath("$path/modules") : NULL;
$paths[] = is_dir("$path/profiles") ? realpath("$path/profiles") : NULL;
$paths[] = is_dir("$path/themes") ? realpath("$path/themes") : NULL;
}
return array_filter($paths, 'file_exists');
}
/**
* Registers the namespace for each extension directory with the autoloader.
*
* @param array $dirs
* An associative array of extension directories, keyed by extension name.
*
* @return array
* An associative array of extension directories, keyed by their namespace.
*/
function drupal_phpunit_get_extension_namespaces($dirs) {
$suite_names = ['Unit', 'Kernel', 'Functional', 'Build', 'FunctionalJavascript'];
$namespaces = [];
foreach ($dirs as $extension => $dir) {
if (is_dir($dir . '/src')) {
// Register the PSR-4 directory for module-provided classes.
$namespaces['Drupal\\' . $extension . '\\'][] = $dir . '/src';
}
$test_dir = $dir . '/tests/src';
if (is_dir($test_dir)) {
foreach ($suite_names as $suite_name) {
$suite_dir = $test_dir . '/' . $suite_name;
if (is_dir($suite_dir)) {
// Register the PSR-4 directory for PHPUnit-based suites.
$namespaces['Drupal\\Tests\\' . $extension . '\\' . $suite_name . '\\'][] = $suite_dir;
}
}
// Extensions can have a \Drupal\extension\Traits namespace for
// cross-suite trait code.
$trait_dir = $test_dir . '/Traits';
if (is_dir($trait_dir)) {
$namespaces['Drupal\\Tests\\' . $extension . '\\Traits\\'][] = $trait_dir;
}
}
}
return $namespaces;
}
// We define the COMPOSER_INSTALL constant, so that PHPUnit knows where to
// autoload from. This is needed for tests run in isolation mode, because
// phpunit.xml.dist is located in a non-default directory relative to the
// PHPUnit executable.
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
define('PHPUNIT_COMPOSER_INSTALL', $top_root . '/web/autoload.php');
}
/**
* Populate class loader with additional namespaces for tests.
*
* We run this in a function to avoid setting the class loader to a global
* that can change. This change can cause unpredictable false positives for
* phpunit's global state change watcher. The class loader can be retrieved from
* composer at any time by requiring autoload.php.
*/
function drupal_phpunit_populate_class_loader($root) {
/** @var \Composer\Autoload\ClassLoader $loader */
$loader = require "$root/web/autoload.php";
// Start with classes in known locations.
$loader->add('Drupal\\BuildTests', "$root/web/core/tests");
$loader->add('Drupal\\Tests', "$root/web/core/tests");
$loader->add('Drupal\\TestSite', "$root/web/core/tests");
$loader->add('Drupal\\KernelTests', "$root/web/core/tests");
$loader->add('Drupal\\FunctionalTests', "$root/web/core/tests");
$loader->add('Drupal\\FunctionalJavascriptTests', "$root/web/core/tests");
$loader->add('Drupal\\TestTools', "$root/web/core/tests");
if (!isset($GLOBALS['namespaces'])) {
// Scan for arbitrary extension namespaces from core and contrib.
$extension_roots = drupal_phpunit_contrib_extension_directory_roots("$root/web");
$dirs = array_map('drupal_phpunit_find_extension_directories', $extension_roots);
$dirs = array_reduce($dirs, 'array_merge', []);
$GLOBALS['namespaces'] = drupal_phpunit_get_extension_namespaces($dirs);
}
foreach ($GLOBALS['namespaces'] as $prefix => $paths) {
$loader->addPsr4($prefix, $paths);
}
$loader->add('CRM_', __DIR__);
$loader->add('Civi\\', __DIR__);
$loader->add('api_', __DIR__);
$loader->add('api\\', __DIR__);
$loader->add('Mink\\', __DIR__);
// We want to also load classes starting with namespace Civi that are under
// the Mink folder. They need to be in a separate folder from non-Mink tests
// because they use a different bootstrap and so there's no simple way of
// separating them in a single run without knowing all the test names in
// advance. E.g. @group will still initially try to parse/load all the files
// in a given folder even ones it wouldn't run for that group, and so will
// fail while trying to autoload if using a different bootstrap.
$loader->addPsr4('Civi\\', __DIR__ . '/Mink/Civi');
return $loader;
}
// Do class loader population.
$loader = drupal_phpunit_populate_class_loader($top_root);
ClassWriter::mutateTestBase($loader);
// Set sane locale settings, to ensure consistent string, dates, times and
// numbers handling.
// @see \Drupal\Core\DrupalKernel::bootEnvironment()
setlocale(LC_ALL, 'C');
// Set appropriate configuration for multi-byte strings.
mb_internal_encoding('utf-8');
mb_language('uni');
// Set the default timezone. While this doesn't cause any tests to fail, PHP
// complains if 'date.timezone' is not set in php.ini. The Australia/Sydney
// timezone is chosen so all tests are run using an edge case scenario (UTC+10
// and DST). This choice is made to prevent timezone related regressions and
// reduce the fragility of the testing system in general.
date_default_timezone_set('Australia/Sydney');
// Runtime assertions. PHPUnit follows the php.ini assert.active setting for
// runtime assertions. By default this setting is on. Ensure exceptions are
// thrown if an assert fails, but this call does not turn runtime assertions on
// if they weren't on already.
Handle::register();
<?php
ini_set('memory_limit', '2G');
ini_set('safe_mode', 0);
define('CIVICRM_TEST', 1);
// phpcs:disable
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
eval(cv('php:boot --level=classloader'));
}
else {
eval(cv('php:boot --level=classloader', 'phpcode'));
}
eval(cv('php:boot --level=settings', 'phpcode'));
// phpcs:enable
// Allow autoloading of PHPUnit helper classes in this extension.
$loader = new \Composer\Autoload\ClassLoader();
......@@ -18,6 +13,10 @@ $loader->add('api_', __DIR__);
$loader->add('api\\', __DIR__);
$loader->register();
if (CIVICRM_UF === 'UnitTests') {
Civi\Test::headless()->apply();
}
/**
* Call the "cv" command.
*
......@@ -38,10 +37,7 @@ function cv($cmd, $decode = 'json') {
// Execute `cv` in the original folder. This is a work-around for
// phpunit/codeception, which seem to manipulate PWD.
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$cmd = sprintf('cd %s && %s', escapeshellarg(getenv('PWD')), $cmd);
}
else {
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
$cmd = sprintf('cd %s; %s', escapeshellarg(getenv('PWD')), $cmd);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment