Skip to content

[Console] Simplify simulation of user inputs in CommandTester #18710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 16, 2016

Conversation

chalasr
Copy link
Member

@chalasr chalasr commented May 4, 2016

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets n/a
License MIT
Doc PR symfony/symfony-docs#6623

After @javiereguiluz pointed it in #17470, I open this PR to simplify the simulation of user inputs for testing a Command.
It would be done by calling CommandTester::setUserInputs() with an array of inputs as argument, and so make the CommandTester creating an input stream from the inputs set by the developer, then call QuestionHelper::setInputStream and assign it to the helperSet of the command, sort as all is done automatically in one call.

Depends on #18999

@chalasr chalasr changed the title [Console] Simplify user inputs simulation in the CommandTester [Console] Simplify simulation of user inputs in CommandTester May 4, 2016
@chalasr chalasr force-pushed the patch_commandtester branch 4 times, most recently from ad967f7 to 63fbfd1 Compare May 5, 2016 18:42
{
$stream = fopen('php://memory', 'r+', false);

fputs($stream, implode("\n", $this->userInputs));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we use fwrite instead of fputs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to follow this http://symfony.com/doc/current/components/console/helpers/questionhelper.html#testing-a-command-that-expects-input as possible, please let me know if you still think that I should use fwrite.

@chalasr chalasr force-pushed the patch_commandtester branch from 63fbfd1 to 07c7fb1 Compare May 19, 2016 09:53
@@ -129,4 +137,48 @@ public function getStatusCode()
{
return $this->statusCode;
}

/**
* Sets the faked user inputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would remove the word faked

@OskarStark
Copy link
Contributor

this should be documented somewhere

thanks for your effort 👍

@chalasr
Copy link
Member Author

chalasr commented May 24, 2016

@OskarStark Thanks for the review.
I am waiting for the opinion of a maintainer before proposing the changes in the doc to make it in one shot.

@javiereguiluz
Copy link
Member

@chalasr could you please make the test more complex to simulate several inputs in a row? Thanks!

@chalasr chalasr force-pushed the patch_commandtester branch 2 times, most recently from daab5d1 to e0be96f Compare May 24, 2016 20:25
@chalasr
Copy link
Member Author

chalasr commented May 24, 2016

@javiereguiluz Of course, I added a failure test (3 questions for only 2 inputs) and made the first taking 3 questions for 3 inputs.

I also fixed the @OskarStark line notes and started to write documentation.

@chalasr chalasr force-pushed the patch_commandtester branch from e0be96f to 9b5a645 Compare May 24, 2016 21:22
@OskarStark
Copy link
Contributor

I also fixed the @OskarStark line notes and started to write documentation.

Thank you for your effort 👍

@chalasr
Copy link
Member Author

chalasr commented May 26, 2016

According to #17136, this will not work if the SymfonyStyle is used.
I'm working for find a clean solution (out of this PR), but making the SymfonyQuestionHelper out of the command HelperSet made interactive command testing very hard.
In a perfect world, the SymfonyQuestionHelper should be set in the helperSet and be accessible through Command::getHelper('question'). Actually the SymfonyStyle cannot access the Command and the Command cannot access the SymfonyStyle...

EDIT Should be fixed by #18902

@chalasr
Copy link
Member Author

chalasr commented May 28, 2016

Doc submitted.

*
* @return CommandTester
*/
public function setUserInputs(array $inputs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have named the method setInputs() instead.

@chalasr
Copy link
Member Author

chalasr commented Jun 2, 2016

I made the changes and updated the doc.

*
* @param array
*
* @return CommandTester
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo this docblock as it is now is quite useless and could be removed as well (input types and the return type can be inferred by IDEs from the method itself) and the description doesn't add any value to the user apart from what the method name already states. Though explaining what $inputs exactly is expected to be would be something that justified its presence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a description.

@chalasr chalasr force-pushed the patch_commandtester branch 6 times, most recently from b4768e0 to 4c39bc8 Compare June 9, 2016 19:59
@chalasr
Copy link
Member Author

chalasr commented Jun 9, 2016

Rebased this on #18999 to see the benefit by testing commands using both QuestionHelper and SymfonyQuestionHelper (via SymfonyStyle, no need of an HelperSet).
Would be closed otherwise.

@chalasr chalasr force-pushed the patch_commandtester branch 2 times, most recently from 438ca34 to 0e64796 Compare June 9, 2016 22:46

return $this->statusCode = $this->command->run($this->input, $this->output);
}
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an indentation problem here for this method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. The changes of this PR are separated in 69dd333

@chalasr chalasr force-pushed the patch_commandtester branch from 0e64796 to 69dd333 Compare June 10, 2016 07:52
fabpot added a commit that referenced this pull request Jun 16, 2016
…(chalasr)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[Console] Centralize input stream in base Input class

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #10844
| License       | MIT
| Doc PR        | not yet

Actually we have two classes that have an `inputStream` property with its getter+setter:
the QuestionHelper ('question' helper) and the SymfonyQuestionHelper (used via SymfonyStyle, that inherits the inputStream from the QuestionHelper class).

This situation makes command testing really hard.
ATM we can't test a command that uses `SymfonyStyle::ask` without ugly hacks, and we can't find a generic way to set the inputs passed to a command from the CommandTester, as it need to be done on a specific helper that may not be the one used by the command (SymfonyStyle case).

What I propose here is to add a `stream` property (and its getter+setter) to the abstract `Symfony\Component\Console\Input\Input` class.

For now I just made the two helpers setting their `inputStream` from `Input::getStream`, as both QuestionHelper and SymfonyQuestionHelper classes have an `ask` method that takes the command Input as argument.
In a next time (4.0), we could remove the `getInputStream` and `setInputStream` methods from the QuestionHelper class (this only deprecates them in favor of Input `setStream` and `getStream`).

This would close PR #18902 (trying to make interactive command testing with SymfonyStyle easier).
This would also make PR #18710 widely better by setting the input stream in a generic way (working for both helpers without caring about if they are used and which one is used).

Please give me your opinions.

Commits
-------

54d3d63 Centralize input stream in base Input class
@fabpot
Copy link
Member

fabpot commented Jun 16, 2016

@chalasr Now that #18999 is merged, can you rebase this one?

return $this;
}

private function getInputStream()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would name it createInputStream() and pass $this->inputs as an argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would then rename it to createStream()

@fabpot
Copy link
Member

fabpot commented Jun 16, 2016

Just noticed that the second commit messages contain all messages from squashed commits, can you remove them as they are useless? Thanks.

@chalasr chalasr force-pushed the patch_commandtester branch 3 times, most recently from 769312f to b748435 Compare June 16, 2016 07:32
@chalasr
Copy link
Member Author

chalasr commented Jun 16, 2016

Made the changes, rebased and cleaned the commit message.

Rename getInputStream() to getStream(), taking inputs as argument

Make createStream static, typehint  as array
@chalasr chalasr force-pushed the patch_commandtester branch from b748435 to c7ba38a Compare June 16, 2016 07:44
@chalasr
Copy link
Member Author

chalasr commented Jun 16, 2016

@fabpot As it takes the inputs as argument, I made the getStream() method static.

return $this;
}

private static function createStream(array $inputs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of marking it public? I would have kept it private.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabpot : Did you mean static ?
I guess it makes sense, as this method looks like a utility one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I meant public. I think it should be private, I don't see why an end user would have to use this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabpot : But the createStream method is actually private. Not public. 😕

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, sorry about the confusion.

@fabpot
Copy link
Member

fabpot commented Jun 16, 2016

Thank you @chalasr.

@fabpot fabpot merged commit c7ba38a into symfony:master Jun 16, 2016
fabpot added a commit that referenced this pull request Jun 16, 2016
…dTester (chalasr)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[Console] Simplify simulation of user inputs in CommandTester

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | symfony/symfony-docs#6623

After @javiereguiluz pointed it in #17470, I open this PR to simplify the simulation of user inputs for testing a Command.
It would be done by calling `CommandTester::setUserInputs()` with an array of inputs as argument, and so make the CommandTester creating an input stream from the inputs set by the developer, then call `QuestionHelper::setInputStream` and assign it to the helperSet of the command, sort as all is done automatically in one call.

Depends on #18999

Commits
-------

c7ba38a [Console] Set user inputs from CommandTester
@chalasr chalasr deleted the patch_commandtester branch June 16, 2016 16:28
xabbuh added a commit to symfony/symfony-docs that referenced this pull request Jun 30, 2016
…ing user inputs (chalasr)

This PR was merged into the master branch.

Discussion
----------

[Console] Adapt doc for easier testing of commands needing user inputs

Doc-PR for symfony/symfony#18710.

This one eases testing of commands needing user interactions by simulating them from the CommandTester directly, by creating a input stream from the ones set by the developer.

Commits
-------

26fdbe0 [Console] Adapt doc for easier testing of commands needing user inputs
@fabpot fabpot mentioned this pull request Oct 27, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants