/** * Determine the full pathname to store a failure-related dump. * * This is used for content such as the DOM, and screenshots. * * @param AfterStepScope $scope scope passed by event after step. * @param String $filetype The file suffix to use. Limited to 4 chars. */ protected function get_faildump_filename(AfterStepScope $scope, $filetype) { global $CFG; // All the contentdumps should be in the same parent dir. if (!($faildumpdir = self::get_run_faildump_dir())) { $faildumpdir = self::$faildumpdirname = date('Ymd_His'); $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; if (!is_dir($dir) && !mkdir($dir, $CFG->directorypermissions, true)) { // It shouldn't, we already checked that the directory is writable. throw new Exception('No directories can be created inside $CFG->behat_faildump_path, check the directory permissions.'); } } else { // We will always need to know the full path. $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; } // The scenario title + the failed step text. // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format. $filename = $scope->getFeature()->getTitle() . '_' . $scope->getStep()->getText(); $filename = preg_replace('/([^a-zA-Z0-9\\_]+)/', '-', $filename); // File name limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file. // extension as we allow .png for images and .html for DOM contents. $filename = substr($filename, 0, 245) . '_' . $scope->getStep()->getLine() . '.' . $filetype; return array($dir, $filename); }
/** * Take screenshot when a step fails. * * @throws Exception * @param StepEvent $event */ protected function take_screenshot(StepEvent $event) { global $CFG; // Goutte can't save screenshots. if (!$this->running_javascript()) { return false; } // All the run screenshots in the same parent dir. if (!$screenshotsdirname = self::get_run_screenshots_dir()) { $screenshotsdirname = self::$screenshotsdirname = date('Ymd_His'); $dir = $CFG->behat_screenshots_path . DIRECTORY_SEPARATOR . $screenshotsdirname; if (!mkdir($dir, $CFG->directorypermissions, true)) { // It shouldn't, we already checked that the directory is writable. throw new Exception('No directories can be created inside $CFG->behat_screenshots_path, check the directory permissions.'); } } else { // We will always need to know the full path. $dir = $CFG->behat_screenshots_path . DIRECTORY_SEPARATOR . $screenshotsdirname; } // The scenario title + the failed step text. // We want a i-am-the-scenario-title_i-am-the-failed-step.png format. $filename = $event->getStep()->getParent()->getTitle() . '_' . $event->getStep()->getText(); $filename = preg_replace('/([^a-zA-Z0-9\_]+)/', '-', $filename) . '.png'; $this->saveScreenshot($filename, $dir); }
/** * Sets featurefile name, which is used by test plan generator. * * @param FeatureEvent $event event fired before feature. * @throws coding_exception If here we are not using the test database it should be because of a coding error * @BeforeFeature */ public static function before_feature(FeatureEvent $event) { self::$featurefile = $event->getFeature()->getFile(); preg_match('/^.*\\/(\\w*)\\.feature/i', self::$featurefile, $matches); self::$featurefile = $matches[1]; self::$threadgroupname = $event->getFeature()->getTitle(); }
/** * Determine the full pathname to store a failure-related dump. * * This is used for content such as the DOM, and screenshots. * * @param StepEvent $event * @param String $filetype The file suffix to use. */ protected function get_faildump_filename(StepEvent $event, $filetype) { global $CFG; // All the contentdumps should be in the same parent dir. if (!($faildumpdir = self::get_run_faildump_dir())) { $faildumpdir = self::$faildumpdirname = date('Ymd_His'); $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; if (!is_dir($dir) && !mkdir($dir, $CFG->directorypermissions, true)) { // It shouldn't, we already checked that the directory is writable. throw new Exception('No directories can be created inside $CFG->behat_faildump_path, check the directory permissions.'); } } else { // We will always need to know the full path. $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; } // The scenario title + the failed step text. // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format. $filename = $event->getStep()->getParent()->getTitle() . '_' . $event->getStep()->getText(); $filename = preg_replace('/([^a-zA-Z0-9\\_]+)/', '-', $filename) . '.' . $filetype; return array($dir, $filename); }
/** * Resets the test environment. * * @throws coding_exception If here we are not using the test database it should be because of a coding error * @BeforeScenario */ public function before_scenario($event) { global $DB, $SESSION, $CFG; // As many checks as we can. if (!defined('BEHAT_TEST') || !defined('BEHAT_SITE_RUNNING') || php_sapi_name() != 'cli' || !behat_util::is_test_mode_enabled() || !behat_util::is_test_site()) { throw new coding_exception('Behat only can modify the test database and the test dataroot!'); } try { $session = $this->getSession(); } catch (CurlExec $e) { // Exception thrown by WebDriver, so only @javascript tests will be caugth; in // behat_util::is_server_running() we already checked that the server is running. $moreinfo = 'More info in ' . behat_command::DOCS_URL . '#Running_tests'; $msg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo; throw new Exception($msg); } catch (UnknownError $e) { // Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions. $this->throw_unknown_exception($e); } // We need the Mink session to do it and we do it only before the first scenario. if (self::is_first_scenario()) { behat_selectors::register_moodle_selectors($session); } // Avoid some notices / warnings. $SESSION = new stdClass(); behat_util::reset_database(); behat_util::reset_dataroot(); accesslib_clear_all_caches(true); // Reset the nasty strings list used during the last test. nasty_strings::reset_used_strings(); // Assing valid data to admin user (some generator-related code needs a valid user). $user = $DB->get_record('user', array('username' => 'admin')); session_set_user($user); // Reset the browser if specified in config.php. if (!empty($CFG->behat_restart_browser_after) && $this->running_javascript()) { $now = time(); if (self::$lastbrowsersessionstart + $CFG->behat_restart_browser_after < $now) { $session->restart(); self::$lastbrowsersessionstart = $now; } } // Start always in the the homepage. try { // Let's be conservative as we never know when new upstream issues will affect us. $session->visit($this->locate_path('/')); } catch (UnknownError $e) { $this->throw_unknown_exception($e); } // Checking that the root path is a Moodle test site. if (self::is_first_scenario()) { $notestsiteexception = new Exception('The base URL (' . $CFG->wwwroot . ') is not a behat test site, ' . 'ensure you started the built-in web server in the correct directory or your web server is correctly started and set up'); $this->find("xpath", "//head/child::title[normalize-space(.)='" . behat_util::BEHATSITENAME . "']", $notestsiteexception); self::$initprocessesfinished = true; } }