Adding description of how to test a command which expects user input #2398

Merged
merged 3 commits into from Apr 26, 2013

Conversation

Projects
None yet
5 participants
Contributor

Sgoettschkes commented Mar 30, 2013

This PR adds a description on testing a command which uses the DialogHelper and expects some user input.

Q A
Doc fix? no
New docs? yes
Applies to 2.0+
Fixed tickets #2351

One thing I'm not sure about is if I should add a link to the section about command testing. If so, where should I add it?

@wouterj wouterj commented on an outdated diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+Testing a command which expects input
+-------------------------------------
+
+If you want to write a unit test for a command which expects some kind of input
+from the command line, you need to overwrite the HelperSet used by the command::
+
+ use Symfony\Component\Console\Helper\DialogHelper;
+ use Symfony\Component\Console\Helper\HelperSet;
+
+ // ...
+
+ public function testExecute()
+ {
+
+ // ..
@wouterj

wouterj Mar 30, 2013

Member

please use 3 dots

@wouterj wouterj commented on an outdated diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+
+Testing a command which expects input
+-------------------------------------
+
+If you want to write a unit test for a command which expects some kind of input
+from the command line, you need to overwrite the HelperSet used by the command::
+
+ use Symfony\Component\Console\Helper\DialogHelper;
+ use Symfony\Component\Console\Helper\HelperSet;
+
+ // ...
+
+ public function testExecute()
+ {
+
@wouterj

wouterj Mar 30, 2013

Member

unneeded empty line

@wouterj wouterj commented on the diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+be able to proceed if her input is valid.
+
+Testing a command which expects input
+-------------------------------------
+
+If you want to write a unit test for a command which expects some kind of input
+from the command line, you need to overwrite the HelperSet used by the command::
+
+ use Symfony\Component\Console\Helper\DialogHelper;
+ use Symfony\Component\Console\Helper\HelperSet;
+
+ // ...
+
@wouterj

wouterj Mar 30, 2013

Member

unneeded empty line here

@wouterj wouterj commented on the diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+ $commandTester = new CommandTester($command);
+
+ $dialog = new DialogHelper();
+ $dialog->setInputStream($this->getInputStream('Test\n'));
+ // Equals to a user inputing "Test" and hitting ENTER
+ // If you need to enter a confirmation, "yes\n" will work
+
+ $command->setHelperSet(new HelperSet(array($dialog)));
+
+ $commandTester->execute(array('command' => $command->getName()));
+
+ // $this->assertRegExp('/.../', $commandTester->getDisplay());
+ }
+
+ protected function getInputStream($input)
@wouterj

wouterj Mar 30, 2013

Member

Asserting is not something that's usually done in a Command test. Mock objects are a better practise

@Sgoettschkes

Sgoettschkes Mar 30, 2013

Contributor

I copied this from the description on how to test commands. I think as a comment it is ok because it ilustrates that the command is now being executed and one can either test the outcome or end the test.

@wouterj wouterj commented on the diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+
+ $dialog = new DialogHelper();
+ $dialog->setInputStream($this->getInputStream('Test\n'));
+ // Equals to a user inputing "Test" and hitting ENTER
+ // If you need to enter a confirmation, "yes\n" will work
+
+ $command->setHelperSet(new HelperSet(array($dialog)));
+
+ $commandTester->execute(array('command' => $command->getName()));
+
+ // $this->assertRegExp('/.../', $commandTester->getDisplay());
+ }
+
+ protected function getInputStream($input)
+ {
@wouterj

wouterj Mar 30, 2013

Member

unneeded empty line

@Sgoettschkes

Sgoettschkes Mar 30, 2013

Contributor

I'm not sure which line you refer to! I guess between methods there should be an empty line, bracets should also be on their own line. I don't see any other empty lines?

@wouterj

wouterj Mar 30, 2013

Member

:) there was an empty line somewhere here, but I commented on the oldest commit, but it is showing the comments on the new commit. Just a github bug..

@stof stof commented on an outdated diff Mar 30, 2013

components/console/helpers/dialoghelper.rst
+
+If you want to write a unit test for a command which expects some kind of input
+from the command line, you need to overwrite the HelperSet used by the command::
+
+ use Symfony\Component\Console\Helper\DialogHelper;
+ use Symfony\Component\Console\Helper\HelperSet;
+
+ // ...
+ public function testExecute()
+ {
+ // ...
+ $commandTester = new CommandTester($command);
+
+ $dialog = new DialogHelper();
+ $dialog->setInputStream($this->getInputStream('Test\n'));
@stof

stof Mar 30, 2013

Member

you don't need to overwrite the whole helperSet as all you need is calling a setter on the dialog helper:

$dialog = $command->getHelper('dialog');
$dialog->setInputStream(...)
Contributor

tiraeth commented Apr 7, 2013

Impressive. I tried mocking DialogHelper using Mockery, with no luck, but this seems to be cleaner and easier. Unfortunately, this won't work if the order of questions for which we want user to provide answers to is non-deterministic. Is there any chance of getting a description about how to use Mockery in order to create more sophisticated tests for our commands?

Contributor

Sgoettschkes commented Apr 12, 2013

I see your problem. Actually, testing the command itself with Mockery doesn't make much sense, much in the same way testing a controller in a unit test doesn't make much sense. Both are more or less boilerplate code, connecting your services to some front end (http or cli).

You could see if you can read the output stream and parse it, so you know which question is asked. Then you could provide some sort of mapping (if question x, answer with y). This of course means that rewriting one of your questions would break tests, but I guess it should be possible.

Anyway, I think this should be either discussed on the mailing list or postet to SO as to not pollute the PR.

weaverryan merged commit 61b0787 into symfony:2.0 Apr 26, 2013

Member

weaverryan commented Apr 26, 2013

Thanks Sebastian - awesome work!

Sgoettschkes deleted the unknown repository branch Apr 27, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment