MDL-37046 behat: Restricting the execution to the built-in server
authorDavid Monllao <davidm@moodle.com>
Mon, 12 Nov 2012 09:30:31 +0000 (17:30 +0800)
committerDavid Monllao <davidm@moodle.com>
Tue, 29 Jan 2013 00:40:36 +0000 (08:40 +0800)
admin/tool/behat/cli/util.php
admin/tool/behat/locallib.php
lib/setup.php

index 963d0d7..fe6dfc8 100644 (file)
@@ -52,12 +52,12 @@ Ensure the user who executes the action has permissions over behat installation
 Options:
 --stepsdefinitions   Displays the available steps definitions (accepts --filter=\"\" option to restrict the list to the matching definitions)
 --runtests           Runs the tests (accepts --tags=\"\" option to execute only the matching tests and --extra=\"\" to specify extra behat options)
---testenvironment    Switches between the real and the test environment (accepts value 'enable' or 'disable', for example --testenvironment=\"enable\"
+--testenvironment    Allows the test environment to be accesses through the built-in server (accepts value 'enable' or 'disable')
 
 -h, --help     Print out this help
 
 Example from Moodle root directory:
-\$ php admin/tool/behat/cli/util.php --runtests --tags=\"tool_behat\" --extra=\"--format junit --out /path/report.html\"
+\$ php admin/tool/behat/cli/util.php --runtests --tags=\"tool_behat\"
 ";
 
 if (!empty($options['help'])) {
index aa732c7..1037dc7 100644 (file)
@@ -29,8 +29,6 @@ require_once($CFG->libdir . '/phpunit/classes/tests_finder.php');
 /**
  * Behat commands manager
  *
- * CLI + web execution
- *
  * @package    tool_behat
  * @copyright  2012 David MonllaĆ³
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -46,11 +44,7 @@ class tool_behat {
 
         $html = self::get_header();
         $html .= self::get_info();
-
-        if (!self::is_test_environment_running()) {
-            $html .= self::get_steps_definitions_form();
-        }
-
+        $html .= self::get_steps_definitions_form();
         $html .= self::get_footer();
 
         echo $html;
@@ -122,7 +116,10 @@ class tool_behat {
     }
 
     /**
-     * Switches from and to the regular environment to the testing environment
+     * Allows / disables the test environment to be accesses through the built-in server
+     *
+     * Built-in server must be started separately
+     *
      * @param string $testenvironment enable|disable
      */
     public static function switchenvironment($testenvironment = false) {
@@ -134,22 +131,30 @@ class tool_behat {
         }
 
         if ($testenvironment == 'enable') {
-            self::enable_test_environment();
+            self::start_test_mode();
         } else if ($testenvironment == 'disable') {
-            self::disable_test_environment();
+            self::stop_test_mode();
         }
     }
 
     /**
      * Runs the acceptance tests
+     *
+     * It starts test mode and runs the built-in php
+     * CLI server and stops it all then it's done
+     *
      * @param string $tags Restricts the executed tests to the ones that matches the tags
      * @param string $extra Extra CLI behat options
      */
     public static function runtests($tags = false, $extra = false) {
         global $CFG;
 
+        // Checks that the behat reference is properly set up
         self::check_behat_setup();
 
+        // Check that PHPUnit test environment is correctly set up.
+        self::test_environment_problem();
+
         self::update_config_file();
 
         @set_time_limit(0);
@@ -168,29 +173,26 @@ class tool_behat {
             $extra = '';
         }
 
-        // Switching database and dataroot to test environment.
-        self::enable_test_environment();
-        $currentcwd = getcwd();
+        // Starts built-in server and inits test mode
+        self::start_test_mode();
+        $server = self::start_test_server();
 
+        // Runs the tests switching the current working directory to CFG->behatpath.
+        $currentcwd = getcwd();
         chdir($CFG->behatpath);
         ob_start();
         passthru('bin/behat --ansi --config="' . self::get_behat_config_filepath() .'" ' . $tagsoption . ' ' .$extra, $code);
         $output = ob_get_contents();
         ob_end_clean();
-
-        // Switching back to regular environment.
-        self::disable_test_environment();
         chdir($currentcwd);
 
+        // Stops built-in server and stops test mode
+        self::stop_test_server($server[0], $server[1]);
+        self::stop_test_mode();
+
         // Output.
         echo self::get_header();
         echo $output;
-
-        // Dirty hack to avoid behat bad HTML structure when test execution throws an exception and there are skipped steps.
-        if (strstr($output, 'class="skipped"') != false) {
-            echo '</ol></div></div></div></body></html>';
-        }
-
         echo self::get_footer();
     }
 
@@ -210,7 +212,7 @@ class tool_behat {
     bootstrap: ' . $behatpath . '/features/bootstrap
   extensions:
     Behat\MinkExtension\Extension:
-      base_url: ' . $CFG->wwwroot . '
+      base_url: ' . $CFG->test_wwwroot . '
       goutte: ~
       selenium2: ~
     Sanpi\Behatch\Extension:
@@ -302,7 +304,10 @@ class tool_behat {
     }
 
     /**
-     * Checks the behat setup
+     * Checks if behat is set up and working
+     *
+     * It checks the behatpath setting value and runs the
+     * behat help command to ensure it works as expected
      */
     private static function check_behat_setup() {
         global $CFG;
@@ -330,24 +335,23 @@ class tool_behat {
     }
 
     /**
-     * Enables test mode checking the test environment setup
+     * Enables test mode
      *
-     * Stores a file in dataroot/behat to allow Moodle switch to
-     * test database and dataroot before the initial set up
+     * Stores a file in dataroot/behat to
+     * allow Moodle to switch to the test
+     * database and dataroot before the initial setup
      *
      * @throws file_exception
+     * @return array
      */
-    private static function enable_test_environment() {
+    private static function start_test_mode() {
         global $CFG;
 
-        if (self::is_test_environment_enabled()) {
+        if (self::is_test_mode_enabled()) {
             debugging('Test environment was already enabled');
             return;
         }
 
-        // Check that PHPUnit test environment is correctly set up.
-        self::test_environment_problem();
-
         $behatdir = self::get_behat_dir();
 
         $contents = '$CFG->phpunit_prefix and $CFG->phpunit_dataroot are currently used as $CFG->prefix and $CFG->dataroot';
@@ -358,14 +362,37 @@ class tool_behat {
         chmod($filepath, $CFG->directorypermissions);
     }
 
+    /**
+     * Runs the php built-in server
+     * @return array The process running the server and the pipes array
+     */
+    private static function start_test_server() {
+        global $CFG;
+
+        $descriptorspec = array(
+            array("pipe", "r"),
+            array("pipe", "w"),
+            array("pipe", "a")
+        );
+
+        $server = str_replace('http://', '', $CFG->test_wwwroot);
+        $process = proc_open('php -S ' . $server, $descriptorspec, $pipes, $CFG->dirroot);
+
+        if (!is_resource($process)) {
+            print_error('testservercantrun');
+        }
+
+        return array($process, $pipes);
+    }
+
     /**
      * Disables test mode
      */
-    private static function disable_test_environment() {
+    private static function stop_test_mode() {
 
         $testenvfile = self::get_test_filepath();
 
-        if (!self::is_test_environment_enabled()) {
+        if (!self::is_test_mode_enabled()) {
             debugging('Test environment was already disabled');
         } else {
             if (!unlink($testenvfile)) {
@@ -374,6 +401,27 @@ class tool_behat {
         }
     }
 
+    /**
+     * Stops the built-in server
+     *
+     * @param resource $process
+     * @param array $pipes IN, OUT and error pipes
+     */
+    private static function stop_test_server($process, $pipes) {
+
+        if (is_resource($process)) {
+
+            // Closing pipes.
+            fclose($pipes[0]);
+            fclose($pipes[1]);
+            fclose($pipes[2]);
+
+            // Closing process.
+            proc_terminate($process);
+            proc_close($process);
+        }
+    }
+
     /**
      * Checks whether test environment is enabled or disabled
      *
@@ -382,7 +430,7 @@ class tool_behat {
      *
      * @return bool
      */
-    private static function is_test_environment_enabled() {
+    private static function is_test_mode_enabled() {
 
         $testenvfile = self::get_test_filepath();
         if (file_exists($testenvfile)) {
@@ -399,7 +447,7 @@ class tool_behat {
     private static function is_test_environment_running() {
         global $CFG;
 
-        if (!empty($CFG->originaldataroot)) {
+        if (!empty($CFG->originaldataroot) && php_sapi_name() === 'cli-server') {
             return true;
         }
 
index 5d04c22..edf0ebb 100644 (file)
@@ -90,8 +90,15 @@ if (!isset($CFG->wwwroot) or $CFG->wwwroot === 'http://example.com/moodle') {
     exit(1);
 }
 
-// If acceptance testing mode is enabled use test database and dataroot
-if (file_exists($CFG->dataroot . '/behat/test_environment_enabled.txt')) {
+// Default URL for acceptance testing.
+if (!isset($CFG->test_wwwroot)) {
+    $CFG->test_wwwroot = 'http://localhost:8000';
+}
+
+// Switch to test site only when test environment is enabled.
+if ((php_sapi_name() === 'cli-server' || defined('BEHAT_RUNNING')) && 
+        file_exists($CFG->dataroot . '/behat/test_environment_enabled.txt')) {
+    $CFG->wwwroot = $CFG->test_wwwroot;
     $CFG->passwordsaltmain = 'phpunit';
     $CFG->originaldataroot = $CFG->dataroot;
     $CFG->prefix = $CFG->phpunit_prefix;