If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
What about debugging in JavaScript? Change your scenario so it fails: change the "Name" field to look for a non-existent "Product Name":
... lines 1 - 20 | |
Scenario: Add a new product | |
... lines 22 - 25 | |
And I fill in "Product Name" with "Veloci-chew toy" | |
... lines 27 - 34 |
Run it:
./vendor/bin/behat features/product_admin.feature:20
Here's the problem: you can try to watch the browser, but it happens so quickly that it's hard to see what went wrong. In the terminal, the error tells us that there isn't a field called "Product Name", but with nothing else to help. Was there an error on the page? Are we on the wrong page? Is the field calling something else? Why won't someone tell us what's going on!?
Let me show you the master debugging tool. Google for behatch contexts.
This is an open source library that has a bunch of useful contexts - classes like
FeatureContext
and MinkContext
with free definitions. For example, this has a
BrowserContext
you could bring into your project to gain a bunch of useful definitions.
I don't use this library directly, but I do steal from it. The DebugContext
class
has one of my favorite definitions: iPutABreakPoint()
. Copy that and drop it into
our FeatureContext
file:
... lines 1 - 140 | |
/** | |
* Pauses the scenario until the user presses a key. Useful when debugging a scenario. | |
* | |
* @Then (I )break | |
*/ | |
public function iPutABreakpoint() | |
{ | |
fwrite(STDOUT, "\033[s \033[93m[Breakpoint] Press \033[1;93m[RETURN]\033[0;93m to continue...\033[0m"); | |
while (fgets(STDIN, 1024) == '') {} | |
fwrite(STDOUT, "\033[u"); | |
return; | |
} | |
... lines 153 - 188 |
Or you could even create your own DebugContext
if you wanted to organize things a bit.
Shorten this to "I break". To use this, add this language directly above the "Product Name"
step that's failing:
... lines 1 - 20 | |
Scenario: Add a new product | |
... lines 22 - 25 | |
And break | |
And I fill in "Product Name" with "Veloci-chew toy" | |
... lines 28 - 35 |
The "I" part of this language is optional. Head back to the terminal to try this:
./vendor/bin/behat features/product_admin.feature:20
This time, the modal pops open, and the browser freezes. The terminal just says: "Press [RETURN] to continue..." That's right: it's waiting for us to look at the page and debug the issue. Once we know what the problem is, hit enter to let it finish. This is my favorite way to debug!
But there are more cool things, like iSaveAScreenshotIn()
. Copy that definition and
paste it into FeatureContext
. Change the language to "I save a screenshot to" and
remove $this->screenshotDir
thing since we don't have that. To save screenshots to
the root of your project, replace it with __DIR__'/../../'
:
... lines 1 - 153 | |
/** | |
* Saving a screenshot | |
* | |
* @When I save a screenshot to :filename | |
*/ | |
public function iSaveAScreenshotIn($filename) | |
{ | |
sleep(1); | |
$this->saveScreenshot($filename, __DIR__.'/../..'); | |
} | |
... lines 164 - 199 |
In the scenario add:
... lines 1 - 20 | |
Scenario: Add a new product | |
... lines 22 - 25 | |
And I save a screenshot to "shot.png" | |
And I fill in "Product Name" with "Veloci-chew toy" | |
... lines 28 - 35 |
Run it!
./vendor/bin/behat features/product_admin.feature:20
The modal opens and it still fails at the "New Product" step. But now we have a
fancy new shot.png
file at the root of the project that shows exactly what things
looked like when the test failed. Woah.
If you're using continuous integration to run your tests - which you should be! -
this can help you figure out why a test failed, which is normally pretty hard
to debug. By using the hook system - something like @AfterScenario
- you could
automatically save a screenshot on every failure. Check out our blog post about that:
Behat on CircleCI with Failure Screenshots.
Anyways, remove this line and change "Product Name" back to "Name" so that the scenario passes again:
... lines 1 - 20 | |
Scenario: Add a new product | |
... lines 22 - 25 | |
And I fill in "Name" with "Veloci-chew toy" | |
... lines 27 - 34 |
Hey Murad,
You just need to configure taking screenshots on failures, see https://symfonycasts.com/sc... . And of course, use different file names to avoid overriding screenshots.
Cheers!
We are using Jenkins for CI, how can I configure taking screenshots considering Jenkins instead of CircleCI?
Thank you
The logic should be the same but you may have to tweak the code in order to satisfy Jenkins needs
// composer.json
{
"require": {
"php": ">=5.4.0, <7.3.0",
"symfony/symfony": "^2.7", // v2.7.4
"twig/twig": "^1.22", // v1.22.1
"sensio/framework-extra-bundle": "^3.0", // v3.0.16
"doctrine/doctrine-bundle": "^1.5", // v1.5.1
"doctrine/orm": "^2.5", // v2.5.1
"doctrine/doctrine-fixtures-bundle": "^2.2", // v2.2.1
"behat/symfony2-extension": "^2.0" // v2.0.0
},
"require-dev": {
"behat/mink-extension": "^2.0", // v2.0.1
"behat/mink-goutte-driver": "^1.1", // v1.1.0
"behat/mink-selenium2-driver": "^1.2", // v1.2.0
"phpunit/phpunit": "^4.8" // 4.8.18
}
}
Hi all,
What if 2 test fails, how can we take 2 or more screenshots from different feature files?
Thank you.