Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e95ea81

Browse filesBrowse files
author
Robin Chalas
committed
feature #27434 [Console] Add support for error ouput in the CommandTester (cdekok)
This PR was merged into the 4.2-dev branch. Discussion ---------- [Console] Add support for error ouput in the CommandTester Move initialization of the streams to the trait so the `capture_stderr_separately` also works in the CommandTester. | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no | Tests pass? | yes | Fixed tickets | #27422 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> Make it possible to test seperate stderr output. ```$tester = new CommandTester($command); $tester->execute( array('foo' => 'bar'), array('capture_stderr_separately' => true) ); $this->assertEquals('foo', $tester->getErrorOutput()); ```` Commits ------- cec5317 [Console] Add support for error ouput in the CommandTester
2 parents a43f307 + cec5317 commit e95ea81
Copy full SHA for e95ea81

File tree

Expand file treeCollapse file tree

6 files changed

+118
-67
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+118
-67
lines changed

‎src/Symfony/Component/Console/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
pass it the command as an array of its arguments instead
1111
* made the `ProcessHelper` class final
1212
* added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`)
13+
* added `capture_stderr_separately` option to `CommandTester::execute()`
1314

1415
4.1.0
1516
-----

‎src/Symfony/Component/Console/Tester/ApplicationTester.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tester/ApplicationTester.php
+1-57Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
use Symfony\Component\Console\Application;
1515
use Symfony\Component\Console\Input\ArrayInput;
16-
use Symfony\Component\Console\Output\ConsoleOutput;
17-
use Symfony\Component\Console\Output\StreamOutput;
1816

1917
/**
2018
* Eases the testing of console applications.
@@ -33,7 +31,6 @@ class ApplicationTester
3331
private $application;
3432
private $input;
3533
private $statusCode;
36-
private $captureStreamsIndependently = false;
3734

3835
public function __construct(Application $application)
3936
{
@@ -69,65 +66,12 @@ public function run(array $input, $options = array())
6966
putenv('SHELL_INTERACTIVE=1');
7067
}
7168

72-
$this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
73-
if (!$this->captureStreamsIndependently) {
74-
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
75-
if (isset($options['decorated'])) {
76-
$this->output->setDecorated($options['decorated']);
77-
}
78-
if (isset($options['verbosity'])) {
79-
$this->output->setVerbosity($options['verbosity']);
80-
}
81-
} else {
82-
$this->output = new ConsoleOutput(
83-
isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL,
84-
isset($options['decorated']) ? $options['decorated'] : null
85-
);
86-
87-
$errorOutput = new StreamOutput(fopen('php://memory', 'w', false));
88-
$errorOutput->setFormatter($this->output->getFormatter());
89-
$errorOutput->setVerbosity($this->output->getVerbosity());
90-
$errorOutput->setDecorated($this->output->isDecorated());
91-
92-
$reflectedOutput = new \ReflectionObject($this->output);
93-
$strErrProperty = $reflectedOutput->getProperty('stderr');
94-
$strErrProperty->setAccessible(true);
95-
$strErrProperty->setValue($this->output, $errorOutput);
96-
97-
$reflectedParent = $reflectedOutput->getParentClass();
98-
$streamProperty = $reflectedParent->getProperty('stream');
99-
$streamProperty->setAccessible(true);
100-
$streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
101-
}
69+
$this->initOutput($options);
10270

10371
$this->statusCode = $this->application->run($this->input, $this->output);
10472

10573
putenv($shellInteractive ? "SHELL_INTERACTIVE=$shellInteractive" : 'SHELL_INTERACTIVE');
10674

10775
return $this->statusCode;
10876
}
109-
110-
/**
111-
* Gets the output written to STDERR by the application.
112-
*
113-
* @param bool $normalize Whether to normalize end of lines to \n or not
114-
*
115-
* @return string
116-
*/
117-
public function getErrorOutput($normalize = false)
118-
{
119-
if (!$this->captureStreamsIndependently) {
120-
throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
121-
}
122-
123-
rewind($this->output->getErrorOutput()->getStream());
124-
125-
$display = stream_get_contents($this->output->getErrorOutput()->getStream());
126-
127-
if ($normalize) {
128-
$display = str_replace(PHP_EOL, "\n", $display);
129-
}
130-
131-
return $display;
132-
}
13377
}

‎src/Symfony/Component/Console/Tester/CommandTester.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tester/CommandTester.php
+8-8Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Component\Console\Command\Command;
1515
use Symfony\Component\Console\Input\ArrayInput;
16-
use Symfony\Component\Console\Output\StreamOutput;
1716

1817
/**
1918
* Eases the testing of console commands.
@@ -39,9 +38,10 @@ public function __construct(Command $command)
3938
*
4039
* Available execution options:
4140
*
42-
* * interactive: Sets the input interactive flag
43-
* * decorated: Sets the output decorated flag
44-
* * verbosity: Sets the output verbosity flag
41+
* * interactive: Sets the input interactive flag
42+
* * decorated: Sets the output decorated flag
43+
* * verbosity: Sets the output verbosity flag
44+
* * capture_stderr_separately: Make output of stdOut and stdErr separately available
4545
*
4646
* @param array $input An array of command arguments and options
4747
* @param array $options An array of execution options
@@ -68,12 +68,12 @@ public function execute(array $input, array $options = array())
6868
$this->input->setInteractive($options['interactive']);
6969
}
7070

71-
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
72-
$this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
73-
if (isset($options['verbosity'])) {
74-
$this->output->setVerbosity($options['verbosity']);
71+
if (!isset($options['decorated'])) {
72+
$options['decorated'] = false;
7573
}
7674

75+
$this->initOutput($options);
76+
7777
return $this->statusCode = $this->command->run($this->input, $this->output);
7878
}
7979
}

‎src/Symfony/Component/Console/Tester/TesterTrait.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tester/TesterTrait.php
+69-2Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@
1212
namespace Symfony\Component\Console\Tester;
1313

1414
use Symfony\Component\Console\Input\InputInterface;
15+
use Symfony\Component\Console\Output\ConsoleOutput;
1516
use Symfony\Component\Console\Output\OutputInterface;
1617
use Symfony\Component\Console\Output\StreamOutput;
1718

1819
/**
1920
* @author Amrouche Hamza <hamza.simperfit@gmail.com>
20-
*
21-
* @internal
2221
*/
2322
trait TesterTrait
2423
{
2524
/** @var StreamOutput */
2625
private $output;
2726
private $inputs = array();
27+
private $captureStreamsIndependently = false;
2828

2929
/**
3030
* Gets the display returned by the last execution of the command or application.
@@ -46,6 +46,30 @@ public function getDisplay($normalize = false)
4646
return $display;
4747
}
4848

49+
/**
50+
* Gets the output written to STDERR by the application.
51+
*
52+
* @param bool $normalize Whether to normalize end of lines to \n or not
53+
*
54+
* @return string
55+
*/
56+
public function getErrorOutput($normalize = false)
57+
{
58+
if (!$this->captureStreamsIndependently) {
59+
throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
60+
}
61+
62+
rewind($this->output->getErrorOutput()->getStream());
63+
64+
$display = stream_get_contents($this->output->getErrorOutput()->getStream());
65+
66+
if ($normalize) {
67+
$display = str_replace(PHP_EOL, "\n", $display);
68+
}
69+
70+
return $display;
71+
}
72+
4973
/**
5074
* Gets the input instance used by the last execution of the command or application.
5175
*
@@ -91,6 +115,49 @@ public function setInputs(array $inputs)
91115
return $this;
92116
}
93117

118+
/**
119+
* Initializes the output property.
120+
*
121+
* Available options:
122+
*
123+
* * decorated: Sets the output decorated flag
124+
* * verbosity: Sets the output verbosity flag
125+
* * capture_stderr_separately: Make output of stdOut and stdErr separately available
126+
*/
127+
private function initOutput(array $options)
128+
{
129+
$this->captureStreamsIndependently = array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
130+
if (!$this->captureStreamsIndependently) {
131+
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
132+
if (isset($options['decorated'])) {
133+
$this->output->setDecorated($options['decorated']);
134+
}
135+
if (isset($options['verbosity'])) {
136+
$this->output->setVerbosity($options['verbosity']);
137+
}
138+
} else {
139+
$this->output = new ConsoleOutput(
140+
isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL,
141+
isset($options['decorated']) ? $options['decorated'] : null
142+
);
143+
144+
$errorOutput = new StreamOutput(fopen('php://memory', 'w', false));
145+
$errorOutput->setFormatter($this->output->getFormatter());
146+
$errorOutput->setVerbosity($this->output->getVerbosity());
147+
$errorOutput->setDecorated($this->output->isDecorated());
148+
149+
$reflectedOutput = new \ReflectionObject($this->output);
150+
$strErrProperty = $reflectedOutput->getProperty('stderr');
151+
$strErrProperty->setAccessible(true);
152+
$strErrProperty->setValue($this->output, $errorOutput);
153+
154+
$reflectedParent = $reflectedOutput->getParentClass();
155+
$streamProperty = $reflectedParent->getProperty('stream');
156+
$streamProperty->setAccessible(true);
157+
$streamProperty->setValue($this->output, fopen('php://memory', 'w', false));
158+
}
159+
}
160+
94161
private static function createStream(array $inputs)
95162
{
96163
$stream = fopen('php://memory', 'r+', false);

‎src/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,24 @@ public function testGetStatusCode()
9090
{
9191
$this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
9292
}
93+
94+
public function testErrorOutput()
95+
{
96+
$application = new Application();
97+
$application->setAutoExit(false);
98+
$application->register('foo')
99+
->addArgument('foo')
100+
->setCode(function ($input, $output) {
101+
$output->getErrorOutput()->write('foo');
102+
})
103+
;
104+
105+
$tester = new ApplicationTester($application);
106+
$tester->run(
107+
array('command' => 'foo', 'foo' => 'bar'),
108+
array('capture_stderr_separately' => true)
109+
);
110+
111+
$this->assertSame('foo', $tester->getErrorOutput());
112+
}
93113
}

‎src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,23 @@ public function testSymfonyStyleCommandWithInputs()
160160

161161
$this->assertEquals(0, $tester->getStatusCode());
162162
}
163+
164+
public function testErrorOutput()
165+
{
166+
$command = new Command('foo');
167+
$command->addArgument('command');
168+
$command->addArgument('foo');
169+
$command->setCode(function ($input, $output) {
170+
$output->getErrorOutput()->write('foo');
171+
}
172+
);
173+
174+
$tester = new CommandTester($command);
175+
$tester->execute(
176+
array('foo' => 'bar'),
177+
array('capture_stderr_separately' => true)
178+
);
179+
180+
$this->assertSame('foo', $tester->getErrorOutput());
181+
}
163182
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.