Issue #2795567 by joachim, jungle, daffie, Sophie.SK, mondrake, ravi.shankar, jonathanshaw, dawehner, AaronBauman, alexpott: Use Symfony's VarDumper for easier test debugging with dump()
parent
c377d26143
commit
f7dd26aa69
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Drupal\test_page_test\Controller;
|
namespace Drupal\test_page_test\Controller;
|
||||||
|
|
||||||
|
use Drupal\user\Entity\Role;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller routines for test_page_test routes.
|
* Controller routines for test_page_test routes.
|
||||||
*/
|
*/
|
||||||
|
@ -23,4 +25,16 @@ class TestPageTestController {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a test page and with the call to the dump() function.
|
||||||
|
*/
|
||||||
|
public function testPageVarDump() {
|
||||||
|
$role = Role::create(['id' => 'test_role']);
|
||||||
|
dump($role);
|
||||||
|
return [
|
||||||
|
'#title' => t('Test page with var dump'),
|
||||||
|
'#markup' => t('Test page text.'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,3 +144,11 @@ test_page_test.deprecations:
|
||||||
_controller: '\Drupal\test_page_test\Controller\Test::deprecations'
|
_controller: '\Drupal\test_page_test\Controller\Test::deprecations'
|
||||||
requirements:
|
requirements:
|
||||||
_access: 'TRUE'
|
_access: 'TRUE'
|
||||||
|
|
||||||
|
test_page_test.test_page_var_dump:
|
||||||
|
path: '/test-page-var-dump'
|
||||||
|
defaults:
|
||||||
|
_title: 'Test front page with var dump'
|
||||||
|
_controller: '\Drupal\test_page_test\Controller\TestPageTestController::testPageVarDump'
|
||||||
|
requirements:
|
||||||
|
_access: 'TRUE'
|
||||||
|
|
|
@ -8,7 +8,9 @@ use Drupal\Component\Serialization\Json;
|
||||||
use Drupal\Component\Utility\Html;
|
use Drupal\Component\Utility\Html;
|
||||||
use Drupal\Core\Url;
|
use Drupal\Core\Url;
|
||||||
use Drupal\Tests\BrowserTestBase;
|
use Drupal\Tests\BrowserTestBase;
|
||||||
|
use Drupal\Tests\StreamCapturer;
|
||||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||||
|
use Drupal\user\Entity\Role;
|
||||||
use PHPUnit\Framework\ExpectationFailedException;
|
use PHPUnit\Framework\ExpectationFailedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -949,4 +951,39 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
||||||
$this->drupalGetHeader('Content-Type');
|
$this->drupalGetHeader('Content-Type');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the dump() function provided by the var-dumper Symfony component.
|
||||||
|
*/
|
||||||
|
public function testVarDump() {
|
||||||
|
// Append the stream capturer to the STDOUT stream, so that we can test the
|
||||||
|
// dump() output and also prevent it from actually outputting in this
|
||||||
|
// particular test.
|
||||||
|
stream_filter_register("capture", StreamCapturer::class);
|
||||||
|
stream_filter_append(STDOUT, "capture");
|
||||||
|
|
||||||
|
// Dump some variables to check that dump() in test code produces output
|
||||||
|
// on the command line that is running the test.
|
||||||
|
$role = Role::load('authenticated');
|
||||||
|
dump($role);
|
||||||
|
dump($role->id());
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Drupal\user\Entity\Role', StreamCapturer::$cache);
|
||||||
|
$this->assertStringContainsString('authenticated', StreamCapturer::$cache);
|
||||||
|
|
||||||
|
// Visit a Drupal page with call to the dump() function to check that dump()
|
||||||
|
// in site code produces output in the requested web page's HTML.
|
||||||
|
$body = $this->drupalGet('test-page-var-dump');
|
||||||
|
$this->assertSession()->statusCodeEquals(200);
|
||||||
|
|
||||||
|
// It is too strict to assert all properties of the Role and it is easy to
|
||||||
|
// break if one of these properties gets removed or gets a new default
|
||||||
|
// value. It should be sufficient to test just a couple of properties.
|
||||||
|
$this->assertStringContainsString('<span class=sf-dump-note>', $body);
|
||||||
|
$this->assertStringContainsString(' #<span class=sf-dump-protected title="Protected property">id</span>: "<span class=sf-dump-str title="9 characters">test_role</span>"', $body);
|
||||||
|
$this->assertStringContainsString(' #<span class=sf-dump-protected title="Protected property">label</span>: <span class=sf-dump-const>null</span>', $body);
|
||||||
|
$this->assertStringContainsString(' #<span class=sf-dump-protected title="Protected property">permissions</span>: []', $body);
|
||||||
|
$this->assertStringContainsString(' #<span class=sf-dump-protected title="Protected property">uuid</span>: "', $body);
|
||||||
|
$this->assertStringContainsString('</samp>}', $body);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use Drupal\Tests\PhpUnitCompatibilityTrait;
|
||||||
use Drupal\Tests\TestRequirementsTrait;
|
use Drupal\Tests\TestRequirementsTrait;
|
||||||
use Drupal\Tests\Traits\PhpUnitWarnings;
|
use Drupal\Tests\Traits\PhpUnitWarnings;
|
||||||
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
||||||
|
use Drupal\TestTools\TestVarDumper;
|
||||||
use PHPUnit\Framework\Exception;
|
use PHPUnit\Framework\Exception;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
@ -30,6 +31,7 @@ use org\bovigo\vfs\vfsStream;
|
||||||
use org\bovigo\vfs\visitor\vfsStreamPrintVisitor;
|
use org\bovigo\vfs\visitor\vfsStreamPrintVisitor;
|
||||||
use Drupal\Core\Routing\RouteObjectInterface;
|
use Drupal\Core\Routing\RouteObjectInterface;
|
||||||
use Symfony\Component\Routing\Route;
|
use Symfony\Component\Routing\Route;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,6 +66,9 @@ use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||||
* KernelTestBase::installEntitySchema(). Alternately, tests which need modules
|
* KernelTestBase::installEntitySchema(). Alternately, tests which need modules
|
||||||
* to be fully installed could inherit from \Drupal\Tests\BrowserTestBase.
|
* to be fully installed could inherit from \Drupal\Tests\BrowserTestBase.
|
||||||
*
|
*
|
||||||
|
* Using Symfony's dump() function in Kernel tests will produce output on the
|
||||||
|
* command line, whether the call to dump() is in test code or site code.
|
||||||
|
*
|
||||||
* @see \Drupal\Tests\KernelTestBase::$modules
|
* @see \Drupal\Tests\KernelTestBase::$modules
|
||||||
* @see \Drupal\Tests\KernelTestBase::enableModules()
|
* @see \Drupal\Tests\KernelTestBase::enableModules()
|
||||||
* @see \Drupal\Tests\KernelTestBase::installConfig()
|
* @see \Drupal\Tests\KernelTestBase::installConfig()
|
||||||
|
@ -223,6 +228,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
|
||||||
*/
|
*/
|
||||||
public static function setUpBeforeClass() {
|
public static function setUpBeforeClass() {
|
||||||
parent::setUpBeforeClass();
|
parent::setUpBeforeClass();
|
||||||
|
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||||
|
|
||||||
// Change the current dir to DRUPAL_ROOT.
|
// Change the current dir to DRUPAL_ROOT.
|
||||||
chdir(static::getDrupalRoot());
|
chdir(static::getDrupalRoot());
|
||||||
|
|
|
@ -5,6 +5,8 @@ namespace Drupal\KernelTests;
|
||||||
use Drupal\Component\FileCache\FileCacheFactory;
|
use Drupal\Component\FileCache\FileCacheFactory;
|
||||||
use Drupal\Core\Database\Database;
|
use Drupal\Core\Database\Database;
|
||||||
use GuzzleHttp\Exception\GuzzleException;
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use Drupal\Tests\StreamCapturer;
|
||||||
|
use Drupal\user\Entity\Role;
|
||||||
use org\bovigo\vfs\vfsStream;
|
use org\bovigo\vfs\vfsStream;
|
||||||
use org\bovigo\vfs\visitor\vfsStreamStructureVisitor;
|
use org\bovigo\vfs\visitor\vfsStreamStructureVisitor;
|
||||||
use PHPUnit\Framework\SkippedTestError;
|
use PHPUnit\Framework\SkippedTestError;
|
||||||
|
@ -396,4 +398,24 @@ class KernelTestBaseTest extends KernelTestBase {
|
||||||
$this->assertFalse(Database::getConnection()->schema()->tableExists('key_value'));
|
$this->assertFalse(Database::getConnection()->schema()->tableExists('key_value'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the dump() function provided by the var-dumper Symfony component.
|
||||||
|
*/
|
||||||
|
public function testVarDump() {
|
||||||
|
// Append the stream capturer to the STDOUT stream, so that we can test the
|
||||||
|
// dump() output and also prevent it from actually outputting in this
|
||||||
|
// particular test.
|
||||||
|
stream_filter_register("capture", StreamCapturer::class);
|
||||||
|
stream_filter_append(STDOUT, "capture");
|
||||||
|
|
||||||
|
// Dump some variables.
|
||||||
|
$this->enableModules(['system', 'user']);
|
||||||
|
$role = Role::create(['id' => 'test_role']);
|
||||||
|
dump($role);
|
||||||
|
dump($role->id());
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Drupal\user\Entity\Role', StreamCapturer::$cache);
|
||||||
|
$this->assertStringContainsString('test_role', StreamCapturer::$cache);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\TestTools;
|
||||||
|
|
||||||
|
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||||
|
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||||
|
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides handlers for the Symfony VarDumper to work within tests.
|
||||||
|
*
|
||||||
|
* This allows the dump() function to produce output on the terminal without
|
||||||
|
* causing PHPUnit to complain.
|
||||||
|
*/
|
||||||
|
class TestVarDumper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A CLI handler for \Symfony\Component\VarDumper\VarDumper.
|
||||||
|
*/
|
||||||
|
public static function cliHandler($var) {
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new CliDumper();
|
||||||
|
fwrite(STDOUT, "\n");
|
||||||
|
$dumper->setColors(TRUE);
|
||||||
|
$dumper->dump(
|
||||||
|
$cloner->cloneVar($var),
|
||||||
|
function ($line, $depth, $indent_pad) {
|
||||||
|
// A negative depth means "end of dump".
|
||||||
|
if ($depth >= 0) {
|
||||||
|
// Adds a two spaces indentation to the line.
|
||||||
|
fwrite(STDOUT, str_repeat($indent_pad, $depth) . $line . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HTML handler for \Symfony\Component\VarDumper\VarDumper.
|
||||||
|
*/
|
||||||
|
public static function htmlHandler($var) {
|
||||||
|
$cloner = new VarCloner();
|
||||||
|
$dumper = new HtmlDumper();
|
||||||
|
$dumper->dump($cloner->cloneVar($var));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,10 +20,12 @@ use Drupal\Tests\node\Traits\NodeCreationTrait;
|
||||||
use Drupal\Tests\Traits\PhpUnitWarnings;
|
use Drupal\Tests\Traits\PhpUnitWarnings;
|
||||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||||
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
||||||
|
use Drupal\TestTools\TestVarDumper;
|
||||||
use GuzzleHttp\Cookie\CookieJar;
|
use GuzzleHttp\Cookie\CookieJar;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||||
use Symfony\Component\CssSelector\CssSelectorConverter;
|
use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a test case for functional Drupal tests.
|
* Provides a test case for functional Drupal tests.
|
||||||
|
@ -36,6 +38,11 @@ use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||||
* translation functionality. For example, avoid wrapping test text with t()
|
* translation functionality. For example, avoid wrapping test text with t()
|
||||||
* or TranslatableMarkup().
|
* or TranslatableMarkup().
|
||||||
*
|
*
|
||||||
|
* Using Symfony's dump() function in functional test test code will produce
|
||||||
|
* output on the command line; using dump() in site code will produce output in
|
||||||
|
* the requested web page, which can then be inspected in the HTML output from
|
||||||
|
* the test.
|
||||||
|
*
|
||||||
* @ingroup testing
|
* @ingroup testing
|
||||||
*/
|
*/
|
||||||
abstract class BrowserTestBase extends TestCase {
|
abstract class BrowserTestBase extends TestCase {
|
||||||
|
@ -214,6 +221,14 @@ abstract class BrowserTestBase extends TestCase {
|
||||||
*/
|
*/
|
||||||
protected $originalContainer;
|
protected $originalContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function setUpBeforeClass() {
|
||||||
|
parent::setUpBeforeClass();
|
||||||
|
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes Mink sessions.
|
* Initializes Mink sessions.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures output to a stream and stores it for retrieval.
|
||||||
|
*/
|
||||||
|
class StreamCapturer extends \php_user_filter {
|
||||||
|
|
||||||
|
public static $cache = '';
|
||||||
|
|
||||||
|
public function filter($in, $out, &$consumed, $closing) {
|
||||||
|
while ($bucket = stream_bucket_make_writeable($in)) {
|
||||||
|
self::$cache .= $bucket->data;
|
||||||
|
// cSpell:disable-next-line
|
||||||
|
$consumed += $bucket->datalen;
|
||||||
|
stream_bucket_append($out, $bucket);
|
||||||
|
}
|
||||||
|
// cSpell:disable-next-line
|
||||||
|
return PSFS_FEED_ME;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,12 +10,17 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||||
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
|
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
|
||||||
use Drupal\Tests\Traits\PhpUnitWarnings;
|
use Drupal\Tests\Traits\PhpUnitWarnings;
|
||||||
|
use Drupal\TestTools\TestVarDumper;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\VarDumper;
|
||||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a base class and helpers for Drupal unit tests.
|
* Provides a base class and helpers for Drupal unit tests.
|
||||||
*
|
*
|
||||||
|
* Using Symfony's dump() function() in Unit tests will produce output on the
|
||||||
|
* command line.
|
||||||
|
*
|
||||||
* @ingroup testing
|
* @ingroup testing
|
||||||
*/
|
*/
|
||||||
abstract class UnitTestCase extends TestCase {
|
abstract class UnitTestCase extends TestCase {
|
||||||
|
@ -38,6 +43,14 @@ abstract class UnitTestCase extends TestCase {
|
||||||
*/
|
*/
|
||||||
protected $root;
|
protected $root;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function setUpBeforeClass() {
|
||||||
|
parent::setUpBeforeClass();
|
||||||
|
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,4 +19,48 @@ class UnitTestCaseTest extends UnitTestCase {
|
||||||
$this->assertArrayEquals([], []);
|
$this->assertArrayEquals([], []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the dump() function in a test run in the same process.
|
||||||
|
*/
|
||||||
|
public function testVarDumpSameProcess() {
|
||||||
|
// Append the stream capturer to the STDOUT stream, so that we can test the
|
||||||
|
// dump() output and also prevent it from actually outputting in this
|
||||||
|
// particular test.
|
||||||
|
stream_filter_register("capture", StreamCapturer::class);
|
||||||
|
stream_filter_append(STDOUT, "capture");
|
||||||
|
|
||||||
|
// Dump some variables.
|
||||||
|
$object = (object) [
|
||||||
|
'foo' => 'bar',
|
||||||
|
];
|
||||||
|
dump($object);
|
||||||
|
dump('banana');
|
||||||
|
|
||||||
|
$this->assertStringContainsString('bar', StreamCapturer::$cache);
|
||||||
|
$this->assertStringContainsString('banana', StreamCapturer::$cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the dump() function in a test run in a separate process.
|
||||||
|
*
|
||||||
|
* @runInSeparateProcess
|
||||||
|
*/
|
||||||
|
public function testVarDumpSeparateProcess() {
|
||||||
|
// Append the stream capturer to the STDOUT stream, so that we can test the
|
||||||
|
// dump() output and also prevent it from actually outputting in this
|
||||||
|
// particular test.
|
||||||
|
stream_filter_register("capture", StreamCapturer::class);
|
||||||
|
stream_filter_append(STDOUT, "capture");
|
||||||
|
|
||||||
|
// Dump some variables.
|
||||||
|
$object = (object) [
|
||||||
|
'foo' => 'bar',
|
||||||
|
];
|
||||||
|
dump($object);
|
||||||
|
dump('banana');
|
||||||
|
|
||||||
|
$this->assertStringContainsString('bar', StreamCapturer::$cache);
|
||||||
|
$this->assertStringContainsString('banana', StreamCapturer::$cache);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue