MDL-43439 behat: Save the screenshots to the specified location
authorDavid Monllao <davidm@moodle.com>
Mon, 6 Jan 2014 08:33:11 +0000 (16:33 +0800)
committerDavid Monllao <davidm@moodle.com>
Tue, 14 Jan 2014 07:17:28 +0000 (15:17 +0800)
config-dist.php
lib/tests/behat/behat_hooks.php

index 964a646..6733547 100644 (file)
@@ -654,6 +654,10 @@ $CFG->admin = 'admin';
 // Example:
 //   $CFG->behat_additionalfeatures = array('/home/developer/code/wipfeatures');
 //
+// You can make behat save a screenshot when a scenario fails.
+// Example:
+//   $CFG->behat_screenshots_path = '/my/path/to/save/screenshots';
+//
 //=========================================================================
 // 12. DEVELOPER DATA GENERATOR
 //=========================================================================
index 430ed4f..a4c76ac 100644 (file)
@@ -77,6 +77,13 @@ class behat_hooks extends behat_base {
      */
     protected static $currentstepexception = null;
 
+    /**
+     * If we are saving screenshots on failures we should use the same parent dir during a run.
+     *
+     * @var The parent dir name
+     */
+    protected static $screenshotsdirname = false;
+
     /**
      * Gives access to moodle codebase, ensures all is ready and sets up the test lock.
      *
@@ -134,6 +141,10 @@ class behat_hooks extends behat_base {
             // Store the initial browser session opening.
             self::$lastbrowsersessionstart = time();
         }
+
+        if (!empty($CFG->behat_screenshots_path) && !is_writable($CFG->behat_screenshots_path)) {
+            throw new Exception('You set $CFG->behat_screenshots_path to a non-writable directory');
+        }
     }
 
     /**
@@ -258,6 +269,13 @@ class behat_hooks extends behat_base {
      * @AfterStep @javascript
      */
     public function after_step_javascript($event) {
+        global $CFG;
+
+        // Save a screenshot if the step failed.
+        if (!empty($CFG->behat_screenshots_path) &&
+                $event->getResult() === StepEvent::FAILED) {
+            $this->take_screenshot($event);
+        }
 
         try {
             $this->wait_for_pending_js();
@@ -279,18 +297,49 @@ class behat_hooks extends behat_base {
     }
 
     /**
-     * Take screenshot when step fails.
-     * Screenshot is saved at /tmp/
+     * Getter for self::$screenshotsdirname
      *
-     * @AfterStep
+     * @return string
      */
-    public function take_screenshot_after_failed_step(Behat\Behat\Event\StepEvent $event) {
+    protected function get_run_screenshots_dir() {
+        return self::$screenshotsdirname;
+    }
+
+    /**
+     * Take screenshot when a step fails.
+     *
+     * @throws Exception
+     * @param StepEvent $event
+     */
+    protected function take_screenshot(StepEvent $event) {
         global $CFG;
 
-        if (!empty($CFG->behat_screenshot_after_failure) &&
-                $event->getResult() === Behat\Behat\Event\StepEvent::FAILED) {
-            $this->saveScreenshot();
+        // 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('Y-m-d_Hi');
+
+            $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);
     }
 
     /**