Unverified Commit f7dd26aa authored by alexpott's avatar alexpott

Issue #2795567 by joachim, jungle, daffie, Sophie.SK, mondrake, ravi.shankar,...

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 c377d261
......@@ -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 @@ public function testPage() {
];
}
/**
* 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\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 @@ public function testDrupalGetHeader() {
$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\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\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 @@
* 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 @@
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 @@ public function testKernelTestBaseInstallSchema() {
$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);
}
}
<?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\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 @@
* 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.
*/
......
<?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\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 @@ public function testAssertArrayEquals() {
$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);
}
}
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