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;
|
||||
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* 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'
|
||||
requirements:
|
||||
_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\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\StreamCapturer;
|
||||
use Drupal\Tests\Traits\Core\CronRunTrait;
|
||||
use Drupal\user\Entity\Role;
|
||||
use PHPUnit\Framework\ExpectationFailedException;
|
||||
|
||||
/**
|
||||
|
@ -949,4 +951,39 @@ class BrowserTestBaseTest extends BrowserTestBase {
|
|||
$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\Traits\PhpUnitWarnings;
|
||||
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
||||
use Drupal\TestTools\TestVarDumper;
|
||||
use PHPUnit\Framework\Exception;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
@ -30,6 +31,7 @@ use org\bovigo\vfs\vfsStream;
|
|||
use org\bovigo\vfs\visitor\vfsStreamPrintVisitor;
|
||||
use Drupal\Core\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
|
||||
/**
|
||||
|
@ -64,6 +66,9 @@ use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
|||
* KernelTestBase::installEntitySchema(). Alternately, tests which need modules
|
||||
* 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::enableModules()
|
||||
* @see \Drupal\Tests\KernelTestBase::installConfig()
|
||||
|
@ -223,6 +228,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
|
|||
*/
|
||||
public static function setUpBeforeClass() {
|
||||
parent::setUpBeforeClass();
|
||||
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||
|
||||
// Change the current dir to DRUPAL_ROOT.
|
||||
chdir(static::getDrupalRoot());
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace Drupal\KernelTests;
|
|||
use Drupal\Component\FileCache\FileCacheFactory;
|
||||
use Drupal\Core\Database\Database;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Drupal\Tests\StreamCapturer;
|
||||
use Drupal\user\Entity\Role;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use org\bovigo\vfs\visitor\vfsStreamStructureVisitor;
|
||||
use PHPUnit\Framework\SkippedTestError;
|
||||
|
@ -396,4 +398,24 @@ class KernelTestBaseTest extends KernelTestBase {
|
|||
$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\user\Traits\UserCreationTrait;
|
||||
use Drupal\TestTools\Comparator\MarkupInterfaceComparator;
|
||||
use Drupal\TestTools\TestVarDumper;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* 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
|
||||
*/
|
||||
abstract class BrowserTestBase extends TestCase {
|
||||
|
@ -214,6 +221,14 @@ abstract class BrowserTestBase extends TestCase {
|
|||
*/
|
||||
protected $originalContainer;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function setUpBeforeClass() {
|
||||
parent::setUpBeforeClass();
|
||||
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\PluralTranslatableMarkup;
|
||||
use Drupal\Tests\Traits\PhpUnitWarnings;
|
||||
use Drupal\TestTools\TestVarDumper;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
abstract class UnitTestCase extends TestCase {
|
||||
|
@ -38,6 +43,14 @@ abstract class UnitTestCase extends TestCase {
|
|||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function setUpBeforeClass() {
|
||||
parent::setUpBeforeClass();
|
||||
VarDumper::setHandler(TestVarDumper::class . '::cliHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -19,4 +19,48 @@ class UnitTestCaseTest extends UnitTestCase {
|
|||
$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