/** * Take a screenshot when a step fails * * @param StepEvent $event * * @AfterStep */ public function takeScreenshotAfterFailedStep(StepEvent $event) { if ($event->getResult() === StepEvent::FAILED) { $driver = $this->getSession()->getDriver(); $rootDir = dirname($this->getParameter('kernel.root_dir')); $filePath = $event->getLogicalParent()->getFile(); $stepStats = ['scenario_file' => substr($filePath, strlen($rootDir) + 1), 'scenario_line' => $event->getLogicalParent()->getLine(), 'scenario_label' => $event->getLogicalParent()->getTitle(), 'exception' => $event->getException()->getMessage(), 'step_line' => $event->getStep()->getLine(), 'step_label' => $event->getStep()->getText(), 'status' => 'failed']; if ($driver instanceof Selenium2Driver) { $dir = getenv('WORKSPACE'); $buildUrl = getenv('BUILD_URL'); if (false !== $dir) { $dir = sprintf('%s/app/build/screenshots', $dir); } else { $dir = '/tmp/behat/screenshots'; } $lineNum = $event->getStep()->getLine(); $filename = strstr($event->getLogicalParent()->getFile(), 'features/'); $filename = sprintf('%s.%d.png', str_replace('/', '__', $filename), $lineNum); $path = sprintf('%s/%s', $dir, $filename); $fs = new \Symfony\Component\Filesystem\Filesystem(); $fs->dumpFile($path, $driver->getScreenshot()); if (false !== $dir) { $path = sprintf('%s/artifact/app/build/screenshots/%s', $buildUrl, $filename); } $stepStats['screenshot'] = $path; $this->getMainContext()->addErrorMessage("Step {$lineNum} failed, screenshot available at {$path}"); } if ('JENKINS' === getenv('BEHAT_CONTEXT')) { echo sprintf("[1;37m##glados_step##%s##glados_step##[0m\n", json_encode($stepStats)); } } }
public function takeScreenshot(StepEvent $event) { $driver = $this->getSession()->getDriver(); // quit silently when unsupported if (!$driver instanceof Selenium2Driver) { return; } $parent = $event->getLogicalParent(); $feature = $parent->getFeature(); $step = $event->getStep(); $screenshotPath = null; $path = $this->getMainContext()->getScreenshotPath(); if (!$path) { return; } // quit silently when path is not set \Filesystem::makeFolder($path); $path = realpath($path); if (!file_exists($path)) { file_put_contents('php://stderr', sprintf('"%s" is not valid directory and failed to create it' . PHP_EOL, $path)); return; } if (file_exists($path) && !is_dir($path)) { file_put_contents('php://stderr', sprintf('"%s" is not valid directory' . PHP_EOL, $path)); return; } if (file_exists($path) && !is_writable($path)) { file_put_contents('php://stderr', sprintf('"%s" directory is not writable' . PHP_EOL, $path)); return; } $path = sprintf('%s/%s_%d.png', $path, basename($feature->getFile()), $step->getLine()); $screenshot = $driver->getWebDriverSession()->screenshot(); file_put_contents($path, base64_decode($screenshot)); file_put_contents('php://stderr', sprintf('Saving screenshot into %s' . PHP_EOL, $path)); }
/** * Return recorded events * * @return array */ public function getEvents() { $events = $this->getEventRecorder()->rip(); foreach ($events as $key => $eventTurple) { list($name, $event) = $eventTurple; if ($event instanceof StepEvent) { $event = new StepEvent($event->getStep(), $event->getLogicalParent(), new NullContext(), $event->getResult(), null, $event->getException() ? new WorkerException($event->getException()->getMessage()) : null, $event->getSnippet()); } if ($event instanceof OutlineExampleEvent) { $event = new OutlineExampleEvent($event->getOutline(), $event->getIteration(), new NullContext(), $event->getResult(), $event->isSkipped()); } if ($event instanceof ScenarioEvent) { $event = new ScenarioEvent($event->getScenario(), new NullContext(), $event->getResult(), $event->isSkipped()); } $event->setDispatcher(new NullEventDispatcher()); $events[$key] = array($name, $event); } return $events; }
/** * Searches and runs provided step delegating all the process to the parent class * * Method overwritten to look for: * - Moodle exceptions * - Moodle debugging() calls * - PHP debug messages (depends on the PHP debug level) * * @param StepNode $step step node * @return StepEvent */ protected function executeStep(StepNode $step) { // Redirect to the parent to run the step. $afterEvent = parent::executeStep($step); // Catch Moodle Behat skip exception. if ($afterEvent->getException() instanceof SkippedException) { return new StepEvent($afterEvent->getStep(), $afterEvent->getLogicalParent(), $afterEvent->getContext(), StepEvent::SKIPPED, $afterEvent->getDefinition(), $afterEvent->getException(), null); } // We set $this->dispatchafterstep to true when a step is in the lower level // but if a step is throwing an exception it doesn't arrive to the point where // we set dispatchafterstep to true and the event is not dispatched; here we // set it but we also check failredstep so the parent steps (in a chain) don't // continue dispatching the event. if ($afterEvent->getResult() !== StepEvent::PASSED && $this->failedstep === false) { $this->dispatchafterstep = true; } // Extra step, looking for a moodle exception, a debugging() message or a PHP debug message. $checkingStep = new StepNode('Then', self::EXCEPTIONS_STEP_TEXT, $step->getLine()); $afterExceptionCheckingEvent = parent::executeStep($checkingStep); // If it find something wrong we overwrite the original step result. if ($afterExceptionCheckingEvent->getResult() == StepEvent::FAILED) { // Creating a mix of both StepEvents to report about it as a failure in the original step. $afterEvent = new StepEvent($afterEvent->getStep(), $afterEvent->getLogicalParent(), $afterEvent->getContext(), $afterExceptionCheckingEvent->getResult(), $afterEvent->getDefinition(), $afterExceptionCheckingEvent->getException(), null); } return $afterEvent; }
/** * Take a screenshot when a step fails * * @param StepEvent $event * * @AfterStep */ public function takeScreenshotAfterFailedStep(StepEvent $event) { if ($event->getResult() === StepEvent::FAILED) { $driver = $this->getSession()->getDriver(); if ($driver instanceof Selenium2Driver) { $dir = getenv('WORKSPACE'); $buildUrl = getenv('BUILD_URL'); if (false !== $dir) { $dir = sprintf('%s/app/build/screenshots', $dir); } else { $dir = '/tmp/behat/screenshots'; } $lineNum = $event->getStep()->getLine(); $filename = strstr($event->getLogicalParent()->getFile(), 'features/'); $filename = sprintf('%s.%d.png', str_replace('/', '__', $filename), $lineNum); $path = sprintf('%s/%s', $dir, $filename); $fs = new \Symfony\Component\Filesystem\Filesystem(); $fs->dumpFile($path, $driver->getScreenshot()); if (false !== $dir) { $path = sprintf('%s/artifact/app/build/screenshots/%s', $buildUrl, $filename); } $this->addErrorMessage("Step {$lineNum} failed, screenshot available at {$path}"); } } }
public function afterStep(StepEvent $event) { if (!$this->valid()) { return false; } $result = $event->getContext()->getSession()->evaluateScript("return window.s"); if ($result) { $title = $event->getLogicalParent()->getTitle(); $subtitle = $this->getStepText($event); $this->collectResult($title, $subtitle, $result); } }