-
Notifications
You must be signed in to change notification settings - Fork 305
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
Recommendations for automated testing of Robo Scripts/Commands? #947
Comments
See g1a/starter. If you follow the |
@greg-1-anderson How would you go about testing a series of sequential input to interactive commands? My research so far has led me to https://symfony.com/doc/current/components/console/helpers/questionhelper.html#testing-a-command-that-expects-input. How would you approach using that with Robo in PHPUnit tests? |
CommandTester looks useful. I have been ambivalent about exposing the With some work, it would be possible to modify the CommandTesterTrait to work with the Symfony CommandTester. What we'd want to do is replace the |
I apologize for the very long post in advance! I've played around with this a bit, lots of hacking so far so no code to officially post as yet. For the most part I've been able to figure out a decent mechanism for extracting the command using the patch from #675 Input works fine so long as you put all interactive questions in an interact hook. I'm able to successfully capture the input and set options/arguments, and these get used in the primary command callback. However, I am running into a bit of a pain-point - extracting the output generated by the execution of the command. CommandTester creates its own input and output streams via Snippet of custom Robo command class GitCommand:
Snippet of test case:
The disconnect between output streams seems to come into play on line 257 of CommandProcessor, where the command callback function is invoked.
At this point, the output already assigned to I'm brand new to this framework, so I'll just ask a few follow up questions:
Ultimately, I like that CommandTester shoves everything into a memory stream, it keeps the PHPUnit console output clean. My preference would be to move in the direction of ensuring that Robo and annotated commands use the streams created by CommandTester. I'll work on getting some example code pushed up, probably tomorrow at this point. |
Sorry I only read the first bit of that. My suggestion was:
So, don't worry about what Runner does with the output stream, because we wouldn't use that. Just make a helper that returns the Command object, and then use the Symfony CommandTester as it was intended to be used. I think it's weird that CommandTester uses |
Sorry for the confusion, I did actually implement the return of the Symfony command instance https://bitbucket.org/lpeabody/release-manager/src/8108b6ccc1446388f48e80288c58a0be29e0c301/tests/CommandTesterTrait.php?at=feature%2Ftest-interactive-commands#lines-83 And the update I made to Runner https://github.com/lpeabody/Robo/blob/e1a2af011b2dfec3f9b80495c21beefae9b3dd85/src/Runner.php#L166-L177. |
So what you want is a new method of Runner that does:
The general idea is that you should get back the Symfony application object initialized and ready to go. Then you can use it to look up the The wrinkles are:
It is an aspirational goal to remove $input and $output from the container, but that's a Robo 3 thing. Again, I'm not sure if this will get in your way or not. It might depend on what your command does. |
OK it seems like you are basically doing what I recommended. One nit is that your new method shouldn't be called Anyway, the |
I am working on making this better. I am doing some work in consolidaiton/annotated-command to insure that the $input and $output objects used with the Symfony command object are injected into the Robo command instance iff it is input aware / output aware. Robo files are supposed to extend \Robo\Tasks; any that do will be input and output aware. Those that do not should use IO. The task builder already injects the $input and $output objects from the Robo command instance into each task that is created (for any task that is input / output aware). This should fix the problem you're having with |
That would be a huge win for testing fully interactive applications, really appreciate you digging in on this. If you push something up I'd be happy to test it out. |
consolidation/annotated-command#207 is the consolidation/annotated-command PR. It still needs tests, and Robo still needs changes to make this PR work correctly. Work in progress. |
Here's the Robo PR: Does not do anything yet except this should allow |
The existing PRs are not rigorous enough yet to work correctly e.g. with most hooks. Still working on improving this. |
The quest to enable robust testing methods is always a worthy pursuit. I did not have an opportunity yesterday to get to testing your modifications, unfortunately work got in the way. Sometimes I just wish I could contribute to open source as my job... Per your last comment, are your thoughts that the work done so far permits CommandTester to be used in a way that gives the expected results for my usecase (e.g. using the same input/output streams in the interact hook + command callback)? You're saying that the input/output streams aren't consolidated across all command hooks yet (validate, initialize, option, etc..)? |
I haven't tried to use CommandTester yet. I'm still fixing bugs with the Robo integration of that PR as I find them. |
I haven't looked at your changes yet, and I haven't written any tests of my own to prove it yet either, but I believe that #675 basically works for what it was intended to do -- re-inject $input and $output as provided to methods such as |
I just skimmed your Robo modifications, and they look good in concept. I think that what we need in terms of an API is a simple method (in Runner or elsewhere) to initialize the Robo DI container and return the Symfony Application object. Then the test can call I'm still not sure that there is any need to return the commandfile instance itself directly. If folks call methods of the commandfile, then they subvert hooks and other processing. I think direct calls to With a one or two-line change to use that suggested API, then I think that your CommandTester trait is spot on. |
I made a 4.2 release of consolidation/annotated-command and updated #675 to use it. |
I added a Runner method for returning an application, meant to be used by CommandTesterTrait for getting a command and running it through CommandTester. CommandTesterTrait setup method now gets the runner ready to use: Execute method using application getter in CommandTesterTrait: the application getter function added to Runner: Working very well. I can't think of any drawbacks. Just saw your note about releasing 4.2 of annotated-command and updating #675. I will update my codebase accordingly... right after I get some lunch 👍 |
I merged #675, so at this point you could make a PR off of the main branch. |
getAppForTesting looks about right. Just a couple comments:
|
Bonus points for adding at least one CommandTester-based test to Robo itself. |
I had a similar thought process. If I only care about testing a command from a single file, then why go through the command file discovery process when I can just hand it the file. I think this is a good suggestion. Honestly, I would have done it if I wasn't so tunnel visioned into getting a passing test...
Challenge accepted. |
Just noting that #675 appears to still be open. It also does not seem to contain any new commits since Feb 1 2018 https://github.com/consolidation/Robo/pull/675/commits. |
Definitely don't need it to accomplish what we're trying to accomplish in this issue! I was just following up since you mentioned it was merged, and it was not merged :) |
Cool, thanks. I just grabbed the wrong number from the wrong open tab. 😝 |
Hey Greg,
What's the best way to go about testing custom Robo Scripts, or anything extending
\Robo\Tasks
?For example, say I wanted to assert the
foo
method saidThis is a Robo script, $name
in https://github.com/consolidation/Robo/blob/master/examples/robo.script ?Or do any unit/functional tests exist that I can look at that test https://github.com/consolidation/Robo/blob/master/examples/src/Robo/Plugin/Commands/ExampleCommands.php ?
Thanks!
The text was updated successfully, but these errors were encountered: