Newer
Older
catch
committed
<?php
/**
* @file
Jennifer Hodgdon
committed
* Definition of \Drupal\simpletest\TestBase.
catch
committed
*/
namespace Drupal\simpletest;
Dries Buytaert
committed
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Random;
use Drupal\Component\Utility\String;
use Drupal\Core\Database\Database;
use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Config\StorageComparer;
use Drupal\Core\DependencyInjection\ContainerBuilder;
catch
committed
use Drupal\Core\Database\ConnectionNotDefinedException;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Session\AccountProxy;
use Drupal\Core\Session\AnonymousUserSession;
Alex Pott
committed
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\PublicStream;
catch
committed
use Drupal\Core\Utility\Error;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\DependencyInjection\Reference;
catch
committed
/**
* Base class for Drupal tests.
*
Jennifer Hodgdon
committed
* Do not extend this class directly; use either
* \Drupal\simpletest\WebTestBase or \Drupal\simpletest\KernelTestBase.
catch
committed
*/
abstract class TestBase {
/**
* The test run ID.
*
* @var string
*/
protected $testId;
/**
* The site directory of this test run.
*
* @var string
*/
protected $siteDirectory = NULL;
catch
committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* The database prefix of this test run.
*
* @var string
*/
protected $databasePrefix = NULL;
/**
* Time limit for the test.
*/
protected $timeLimit = 500;
/**
* Current results of this test case.
*
* @var Array
*/
public $results = array(
'#pass' => 0,
'#fail' => 0,
'#exception' => 0,
'#debug' => 0,
);
/**
* Assertions thrown in that test case.
*
* @var Array
*/
protected $assertions = array();
/**
* This class is skipped when looking for the source of an assertion.
*
* When displaying which function an assert comes from, it's not too useful
* to see "WebTestBase->drupalLogin()', we would like to see the test
* that called it. So we need to skip the classes defining these helper
* methods.
*/
protected $skipClasses = array(__CLASS__ => TRUE);
catch
committed
/**
* TRUE if verbose debugging is enabled.
*
* @var boolean
*/
public $verbose;
catch
committed
/**
* Incrementing identifier for verbose output filenames.
*
* @var integer
*/
protected $verboseId = 0;
/**
* Safe class name for use in verbose output filenames.
*
* Namespaces separator (\) replaced with _.
*
* @var string
*/
protected $verboseClassName;
/**
* Directory where verbose output files are put.
*
* @var string
*/
protected $verboseDirectory;
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/**
* URL to the verbose output file directory.
*
* @var string
*/
protected $verboseDirectoryUrl;
/**
* The original configuration (variables), if available.
*
* @var string
* @todo Remove all remnants of $GLOBALS['conf'].
* @see https://drupal.org/node/2183323
*/
protected $originalConf;
/**
* The original configuration (variables).
*
* @var string
*/
protected $originalConfig;
/**
* The original configuration directories.
*
* An array of paths keyed by the CONFIG_*_DIRECTORY constants defined by
* core/includes/bootstrap.inc.
*
* @var array
*/
protected $originalConfigDirectories;
/**
* The original container.
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $originalContainer;
/**
* The original file directory, before it was changed for testing purposes.
*
* @var string
*/
protected $originalFileDirectory = NULL;
/**
* The original language.
*
* @var \Drupal\Core\Language\LanguageInterface
*/
protected $originalLanguage;
/**
* The original database prefix when running inside Simpletest.
*
* @var string
*/
protected $originalPrefix;
Angie Byron
committed
/**
* The original installation profile.
Angie Byron
committed
*
* @var string
*/
protected $originalProfile;
/**
* The name of the session cookie.
*
* @var string
*/
protected $originalSessionName;
Angie Byron
committed
/**
* The settings array.
*
* @var array
*/
protected $originalSettings;
/**
* The original array of shutdown function callbacks.
*
* @var array
*/
protected $originalShutdownCallbacks;
/**
* The site directory of the original parent site.
*
* @var string
*/
protected $originalSite;
/**
* The original user, before testing began.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $originalUser;
/**
* The public file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
*
* @var string
*/
protected $publicFilesDirectory;
/**
* The private file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
*
* @var string
*/
protected $privateFilesDirectory;
/**
* The temporary file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
*
* @var string
*/
protected $tempFilesDirectory;
/**
* The translation file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
*
* @var string
*/
protected $translationFilesDirectory;
Angie Byron
committed
/**
* Whether to die in case any test assertion fails.
*
Angie Byron
committed
* @var boolean
*
* @see run-tests.sh
Angie Byron
committed
*/
public $dieOnFail = FALSE;
Angie Byron
committed
/**
* The DrupalKernel instance used in the test.
*
* @var \Drupal\Core\DrupalKernel
*/
protected $kernel;
Jennifer Hodgdon
committed
/**
* The dependency injection container used in the test.
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
/**
* The config importer that can used in a test.
*
* @var \Drupal\Core\Config\ConfigImporter
*/
protected $configImporter;
/**
* The random generator.
*
* @var \Drupal\Component\Utility\Random
*/
protected $randomGenerator;
/**
* Set to TRUE to strict check all configuration saved.
*
* @see \Drupal\Core\Config\Testing\ConfigSchemaChecker
*
* @var bool
*/
protected $strictConfigSchema = TRUE;
/**
* HTTP authentication method (specified as a CURLAUTH_* constant).
*
* @var int
* @see http://php.net/manual/en/function.curl-setopt.php
*/
protected $httpAuthMethod = CURLAUTH_BASIC;
/**
* HTTP authentication credentials (<username>:<password>).
*
* @var string
*/
protected $httpAuthCredentials = NULL;
catch
committed
/**
* Constructor for Test.
*
* @param $test_id
* Tests with the same id are reported together.
*/
public function __construct($test_id = NULL) {
$this->testId = $test_id;
}
Dries Buytaert
committed
/**
* Performs setup tasks before each individual test method is run.
*/
abstract protected function setUp();
catch
committed
/**
* Checks the matching requirements for Test.
*
* @return
* Array of errors containing a list of unmet requirements.
*/
protected function checkRequirements() {
return array();
}
/**
* Helper method to store an assertion record in the configured database.
*
* This method decouples database access from assertion logic.
*
* @param array $assertion
* Keyed array representing an assertion, as generated by assert().
*
* @see self::assert()
*/
protected function storeAssertion(array $assertion) {
return self::getDatabaseConnection()
->insert('simpletest')
->fields($assertion)
->execute();
}
catch
committed
/**
* Internal helper: stores the assert.
*
* @param $status
* Can be 'pass', 'fail', 'exception', 'debug'.
catch
committed
* TRUE is a synonym for 'pass', FALSE for 'fail'.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
catch
committed
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
* @param $caller
* By default, the assert comes from a function whose name starts with
* 'test'. Instead, you can specify where this assert originates from
* by passing in an associative array as $caller. Key 'file' is
* the name of the source file, 'line' is the line number and 'function'
* is the caller function itself.
*/
protected function assert($status, $message = '', $group = 'Other', array $caller = NULL) {
// Convert boolean status to string status.
if (is_bool($status)) {
$status = $status ? 'pass' : 'fail';
}
// Increment summary result counter.
$this->results['#' . $status]++;
// Get the function information about the call to the assertion method.
if (!$caller) {
$caller = $this->getAssertionCall();
}
// Creation assertion array that can be displayed while tests are running.
$this->assertions[] = $assertion = array(
'test_id' => $this->testId,
'test_class' => get_class($this),
'status' => $status,
'message' => $message,
'message_group' => $group,
'function' => $caller['function'],
'line' => $caller['line'],
'file' => $caller['file'],
);
// Store assertion for display after the test has completed.
$this->storeAssertion($assertion);
catch
committed
// We do not use a ternary operator here to allow a breakpoint on
// test failure.
if ($status == 'pass') {
return TRUE;
}
else {
if ($this->dieOnFail && ($status == 'fail' || $status == 'exception')) {
Angie Byron
committed
exit(1);
}
catch
committed
return FALSE;
}
}
/**
* Store an assertion from outside the testing context.
*
* This is useful for inserting assertions that can only be recorded after
* the test case has been destroyed, such as PHP fatal errors. The caller
* information is not automatically gathered since the caller is most likely
* inserting the assertion on behalf of other code. In all other respects
Jennifer Hodgdon
committed
* the method behaves just like \Drupal\simpletest\TestBase::assert() in terms
catch
committed
* of storing the assertion.
*
* @return
* Message ID of the stored assertion.
*
Jennifer Hodgdon
committed
* @see \Drupal\simpletest\TestBase::assert()
* @see \Drupal\simpletest\TestBase::deleteAssert()
catch
committed
*/
public static function insertAssert($test_id, $test_class, $status, $message = '', $group = 'Other', array $caller = array()) {
// Convert boolean status to string status.
if (is_bool($status)) {
$status = $status ? 'pass' : 'fail';
}
$caller += array(
catch
committed
'function' => 'Unknown',
catch
committed
'line' => 0,
catch
committed
'file' => 'Unknown',
catch
committed
);
$assertion = array(
'test_id' => $test_id,
'test_class' => $test_class,
'status' => $status,
'message' => $message,
'message_group' => $group,
'function' => $caller['function'],
'line' => $caller['line'],
'file' => $caller['file'],
);
// We can't use storeAssertion() because this method is static.
return self::getDatabaseConnection()
->insert('simpletest')
catch
committed
->fields($assertion)
->execute();
}
/**
* Delete an assertion record by message ID.
*
* @param $message_id
* Message ID of the assertion to delete.
*
catch
committed
* @return
* TRUE if the assertion was deleted, FALSE otherwise.
*
Jennifer Hodgdon
committed
* @see \Drupal\simpletest\TestBase::insertAssert()
catch
committed
*/
public static function deleteAssert($message_id) {
// We can't use storeAssertion() because this method is static.
return (bool) self::getDatabaseConnection()
->delete('simpletest')
catch
committed
->condition('message_id', $message_id)
->execute();
}
/**
* Returns the database connection to the site running Simpletest.
*
Jennifer Hodgdon
committed
* @return \Drupal\Core\Database\Connection
* The database connection to use for inserting assertions.
*/
public static function getDatabaseConnection() {
Angie Byron
committed
// Check whether there is a test runner connection.
// @see run-tests.sh
// @todo Convert Simpletest UI runner to create + use this connection, too.
try {
Angie Byron
committed
$connection = Database::getConnection('default', 'test-runner');
}
catch (ConnectionNotDefinedException $e) {
Angie Byron
committed
// Check whether there is a backup of the original default connection.
// @see TestBase::prepareEnvironment()
try {
$connection = Database::getConnection('default', 'simpletest_original_default');
}
catch (ConnectionNotDefinedException $e) {
// If TestBase::prepareEnvironment() or TestBase::restoreEnvironment()
// failed, the test-specific database connection does not exist
// yet/anymore, so fall back to the default of the (UI) test runner.
$connection = Database::getConnection('default', 'default');
}
}
return $connection;
}
catch
committed
/**
* Cycles through backtrace until the first non-assertion method is found.
*
* @return
* Array representing the true caller.
*/
protected function getAssertionCall() {
$backtrace = debug_backtrace();
// The first element is the call. The second element is the caller.
// We skip calls that occurred in one of the methods of our base classes
// or in an assertion function.
while (($caller = $backtrace[1]) &&
((isset($caller['class']) && isset($this->skipClasses[$caller['class']])) ||
substr($caller['function'], 0, 6) == 'assert')) {
// We remove that call.
array_shift($backtrace);
}
catch
committed
return Error::getLastCaller($backtrace);
catch
committed
}
/**
Jennifer Hodgdon
committed
* Check to see if a value is not false.
*
* False values are: empty string, 0, NULL, and FALSE.
catch
committed
*
* @param $value
* The value on which the assertion is to be done.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertTrue($value, $message = '', $group = 'Other') {
catch
committed
return $this->assert((bool) $value, $message ? $message : String::format('Value @value is TRUE.', array('@value' => var_export($value, TRUE))), $group);
catch
committed
}
/**
Jennifer Hodgdon
committed
* Check to see if a value is false.
*
* False values are: empty string, 0, NULL, and FALSE.
catch
committed
*
* @param $value
* The value on which the assertion is to be done.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertFalse($value, $message = '', $group = 'Other') {
catch
committed
return $this->assert(!$value, $message ? $message : String::format('Value @value is FALSE.', array('@value' => var_export($value, TRUE))), $group);
catch
committed
}
/**
* Check to see if a value is NULL.
*
* @param $value
* The value on which the assertion is to be done.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertNull($value, $message = '', $group = 'Other') {
catch
committed
return $this->assert(!isset($value), $message ? $message : String::format('Value @value is NULL.', array('@value' => var_export($value, TRUE))), $group);
catch
committed
}
/**
* Check to see if a value is not NULL.
*
* @param $value
* The value on which the assertion is to be done.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertNotNull($value, $message = '', $group = 'Other') {
catch
committed
return $this->assert(isset($value), $message ? $message : String::format('Value @value is not NULL.', array('@value' => var_export($value, TRUE))), $group);
catch
committed
}
/**
* Check to see if two values are equal.
*
* @param $first
* The first value to check.
* @param $second
* The second value to check.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertEqual($first, $second, $message = '', $group = 'Other') {
catch
committed
return $this->assert($first == $second, $message ? $message : String::format('Value @first is equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
catch
committed
}
/**
* Check to see if two values are not equal.
*
* @param $first
* The first value to check.
* @param $second
* The second value to check.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertNotEqual($first, $second, $message = '', $group = 'Other') {
catch
committed
return $this->assert($first != $second, $message ? $message : String::format('Value @first is not equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
catch
committed
}
/**
* Check to see if two values are identical.
*
* @param $first
* The first value to check.
* @param $second
* The second value to check.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertIdentical($first, $second, $message = '', $group = 'Other') {
catch
committed
return $this->assert($first === $second, $message ? $message : String::format('Value @first is identical to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
catch
committed
}
/**
* Check to see if two values are not identical.
*
* @param $first
* The first value to check.
* @param $second
* The second value to check.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
protected function assertNotIdentical($first, $second, $message = '', $group = 'Other') {
catch
committed
return $this->assert($first !== $second, $message ? $message : String::format('Value @first is not identical to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group);
catch
committed
}
/**
* Checks to see if two objects are identical.
*
* @param object $object1
* The first object to check.
* @param object $object2
* The second object to check.
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
* @return
* TRUE if the assertion succeeded, FALSE otherwise.
*/
Angie Byron
committed
protected function assertIdenticalObject($object1, $object2, $message = '', $group = 'Other') {
catch
committed
$message = $message ?: String::format('!object1 is identical to !object2', array(
'!object1' => var_export($object1, TRUE),
'!object2' => var_export($object2, TRUE),
));
$identical = TRUE;
foreach ($object1 as $key => $value) {
$identical = $identical && isset($object2->$key) && $object2->$key === $value;
}
Angie Byron
committed
return $this->assertTrue($identical, $message, $group);
}
/**
* Asserts that no errors have been logged to the PHP error.log thus far.
*
* @return bool
* TRUE if the assertion succeeded, FALSE otherwise.
*
* @see TestBase::prepareEnvironment()
* @see \Drupal\Core\DrupalKernel::bootConfiguration()
*/
protected function assertNoErrorsLogged() {
// Since PHP only creates the error.log file when an actual error is
// triggered, it is sufficient to check whether the file exists.
return $this->assertFalse(file_exists(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'), 'PHP error.log is empty.');
}
catch
committed
/**
* Fire an assertion that is always positive.
*
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* TRUE.
*/
protected function pass($message = NULL, $group = 'Other') {
return $this->assert(TRUE, $message, $group);
}
/**
* Fire an assertion that is always negative.
*
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
*
catch
committed
* @return
* FALSE.
*/
protected function fail($message = NULL, $group = 'Other') {
return $this->assert(FALSE, $message, $group);
}
/**
* Fire an error assertion.
*
* @param $message
Jennifer Hodgdon
committed
* (optional) A message to display with the assertion. Do not translate
catch
committed
* messages: use \Drupal\Component\Utility\String::format() to embed
* variables in the message text, not t(). If left blank, a default message
* will be displayed.
catch
committed
* @param $group
Jennifer Hodgdon
committed
* (optional) The group this message is in, which is displayed in a column
* in test output. Use 'Debug' to indicate this is debugging output. Do not
* translate this string. Defaults to 'Other'; most tests do not override
* this default.
catch
committed
* @param $caller
* The caller of the error.
*
catch
committed
* @return
* FALSE.
*/
protected function error($message = '', $group = 'Other', array $caller = NULL) {
if ($group == 'User notice') {
// Since 'User notice' is set by trigger_error() which is used for debug
// set the message to a status of 'debug'.
return $this->assert('debug', $message, 'Debug', $caller);
}
return $this->assert('exception', $message, $group, $caller);
}
/**
* Logs a verbose message in a text file.
catch
committed
*
* The link to the verbose message will be placed in the test results as a
* passing assertion with the text '[verbose message]'.
catch
committed
*
* @param $message
* The verbose message to be stored.
*
* @see simpletest_verbose()
*/
protected function verbose($message) {
catch
committed
// Do nothing if verbose debugging is disabled.
if (!$this->verbose) {
return;
}
$message = '<hr />ID #' . $this->verboseId . ' (<a href="' . $this->verboseClassName . '-' . ($this->verboseId - 1) . '.html">Previous</a> | <a href="' . $this->verboseClassName . '-' . ($this->verboseId + 1) . '.html">Next</a>)<hr />' . $message;
$verbose_filename = $this->verboseDirectory . '/' . $this->verboseClassName . '-' . $this->verboseId . '.html';
if (file_put_contents($verbose_filename, $message, FILE_APPEND)) {
Angie Byron
committed
$url = $this->verboseDirectoryUrl . '/' . $this->verboseClassName . '-' . $this->verboseId . '.html';
// Not using _l() to avoid invoking the theme system, so that unit tests
catch
committed
// can use verbose() as well.
catch
committed
$url = '<a href="' . $url . '" target="_blank">Verbose message</a>';
catch
committed
$this->error($url, 'User notice');
catch
committed
}
catch
committed
$this->verboseId++;
catch
committed
}
/**
* Run all tests in this class.
*
* Regardless of whether $methods are passed or not, only method names
* starting with "test" are executed.
*
* @param $methods
* (optional) A list of method names in the test case class to run; e.g.,
* array('testFoo', 'testBar'). By default, all methods of the class are
* taken into account, but it can be useful to only run a few selected test
* methods during debugging.
*/
public function run(array $methods = array()) {
$class = get_class($this);
if ($missing_requirements = $this->checkRequirements()) {
$object_info = new \ReflectionObject($this);
$caller = array(
'file' => $object_info->getFileName(),
);
foreach ($missing_requirements as $missing_requirement) {
TestBase::insertAssert($this->testId, $class, FALSE, $missing_requirement, 'Requirements check', $caller);
}
return;
}
TestServiceProvider::$currentTest = $this;
$simpletest_config = $this->config('simpletest.settings');
// Unless preset from run-tests.sh, retrieve the current verbose setting.
if (!isset($this->verbose)) {
$this->verbose = $simpletest_config->get('verbose');
}
if ($this->verbose) {
catch
committed
// Initialize verbose debugging.
$this->verbose = TRUE;
$this->verboseDirectory = PublicStream::basePath() . '/simpletest/verbose';
Angie Byron
committed
$this->verboseDirectoryUrl = file_create_url($this->verboseDirectory);
catch
committed
if (file_prepare_directory($this->verboseDirectory, FILE_CREATE_DIRECTORY) && !file_exists($this->verboseDirectory . '/.htaccess')) {
file_put_contents($this->verboseDirectory . '/.htaccess', "<IfModule mod_expires.c>\nExpiresActive Off\n</IfModule>\n");
}
$this->verboseClassName = str_replace("\\", "_", $class);
}
catch
committed
// HTTP auth settings (<username>:<password>) for the simpletest browser
// when sending requests to the test site.
$this->httpAuthMethod = (int) $simpletest_config->get('httpauth.method');
$username = $simpletest_config->get('httpauth.username');
$password = $simpletest_config->get('httpauth.password');
if (!empty($username) && !empty($password)) {
$this->httpAuthCredentials = $username . ':' . $password;
catch
committed
}
set_error_handler(array($this, 'errorHandler'));
// Iterate through all the methods in this class, unless a specific list of
// methods to run was passed.
$test_methods = array_filter(get_class_methods($class), function ($method) {
return strpos($method, 'test') === 0;
});
Angie Byron
committed
if (empty($test_methods)) {
// Call $this->assert() here because we need to pass along custom caller
// information, lest the wrong originating code file/line be identified.
$this->assert(FALSE, 'No test methods found.', 'Requirements', array('function' => __METHOD__ . '()', 'file' => __FILE__, 'line' => __LINE__));
}
catch
committed
if ($methods) {
$test_methods = array_intersect($test_methods, $methods);
}
foreach ($test_methods as $method) {
// Insert a fail record. This will be deleted on completion to ensure
// that testing completed.
$method_info = new \ReflectionMethod($class, $method);
catch
committed
$caller = array(
'file' => $method_info->getFileName(),
'line' => $method_info->getStartLine(),
'function' => $class . '->' . $method . '()',
catch
committed
);
$test_completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller);
try {
$this->prepareEnvironment();
catch
committed
}
catch (\Exception $e) {
$this->exceptionHandler($e);
// The prepareEnvironment() method isolates the test from the parent
// Drupal site by creating a random database prefix and test site
// directory. If this fails, a test would possibly operate in the
// parent site. Therefore, the entire test run for this test class
// has to be aborted.
// restoreEnvironment() cannot be called, because we do not know
// where exactly the environment setup failed.
break;
}
try {
$this->setUp();
}
catch (\Exception $e) {
$this->exceptionHandler($e);
// Abort if setUp() fails, since all test methods will fail.
// But ensure to clean up and restore the environment, since
// prepareEnvironment() succeeded.
$this->restoreEnvironment();
break;
Angie Byron
committed
}
try {
$this->$method();
catch
committed
}
catch (\Exception $e) {
$this->exceptionHandler($e);
}
try {
$this->tearDown();
}