Example #1
0
 /**
  * Lists the available steps definitions
  *
  * @param string $type
  * @param string $component
  * @param string $filter
  * @return string
  */
 public static function stepsdefinitions($type, $component, $filter)
 {
     // We don't require the test environment to be enabled to list the steps definitions
     // so test writers can more easily set up the environment.
     behat_command::check_behat_setup();
     // The loaded steps depends on the component specified.
     behat_config_manager::update_config_file($component, false);
     // The Moodle\BehatExtension\HelpPrinter\MoodleDefinitionsPrinter will parse this search format.
     if ($type) {
         $filter .= '&&' . $type;
     }
     if ($filter) {
         $filteroption = ' -d "' . $filter . '"';
     } else {
         $filteroption = ' -di';
     }
     // Get steps definitions from Behat.
     $options = ' --config="' . behat_config_manager::get_steps_list_config_filepath() . '" ' . $filteroption;
     list($steps, $code) = behat_command::run($options);
     if ($steps) {
         $stepshtml = implode('', $steps);
     }
     if (empty($stepshtml)) {
         $stepshtml = get_string('nostepsdefinitions', 'tool_behat');
     }
     return $stepshtml;
 }
Example #2
0
 /**
  * Returns behat_config_util.
  *
  * @return behat_config_util
  */
 private static function get_behat_config_util()
 {
     if (!self::$behatconfigutil) {
         self::$behatconfigutil = new behat_config_util();
     }
     return self::$behatconfigutil;
 }
Example #3
0
require_once __DIR__ . '/../../../../lib/behat/lib.php';
require_once __DIR__ . '/../../../../lib/behat/classes/behat_command.php';
require_once __DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php';
// CLI options.
list($options, $unrecognized) = cli_get_params(array('help' => false, 'install' => false, 'drop' => false, 'enable' => false, 'disable' => false, 'diag' => false, 'parallel' => 0, 'maxruns' => false, 'updatesteps' => false, 'fromrun' => 1, 'torun' => 0), array('h' => 'help', 'j' => 'parallel', 'm' => 'maxruns'));
// Checking util.php CLI script usage.
$help = "\nBehat utilities to manage the test environment\n\nOptions:\n--install      Installs the test environment for acceptance tests\n--drop         Drops the database tables and the dataroot contents\n--enable       Enables test environment and updates tests list\n--disable      Disables test environment\n--diag         Get behat test environment status code\n-j, --parallel Number of parallel behat run operation\n-m, --maxruns  Max parallel processes to be executed at one time.\n--updatesteps  Update feature step file.\n\n-h, --help     Print out this help\n\nExample from Moodle root directory:\n\$ php admin/tool/behat/cli/util.php --enable --parallel=4\n\nMore info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests\n";
if (!empty($options['help'])) {
    echo $help;
    exit(0);
}
$cwd = getcwd();
// For drop option check if parallel site.
if (empty($options['parallel']) && $options['drop']) {
    // Get parallel run info from first run.
    $options['parallel'] = behat_config_manager::get_parallel_test_runs($options['fromrun']);
}
// If not a parallel site then open single run.
if (empty($options['parallel'])) {
    chdir(__DIR__);
    // Check if behat is initialised, if not exit.
    passthru("php util_single_run.php --diag", $status);
    if ($status) {
        exit($status);
    }
    $cmd = commands_to_execute($options);
    $processes = cli_execute_parallel(array($cmd), __DIR__);
    $status = print_sequential_output($processes, false);
    chdir($cwd);
    exit($status);
}
Example #4
0
/**
 * Signal handler for terminal exit.
 *
 * @param int $signal signal number.
 */
function signal_handler($signal)
{
    switch ($signal) {
        case SIGTERM:
        case SIGKILL:
        case SIGINT:
            // Remove site symlink if necessary.
            behat_config_manager::drop_parallel_site_links();
            exit(1);
    }
}
Example #5
0
 /**
  * Parse $CFG->behat_config and return the array with required config structure for behat.yml
  *
  * @param string $profile profile name
  * @param array $values values for profile
  * @return array
  */
 public function get_behat_config_for_profile($profile, $values)
 {
     // Only add profile which are compatible with Behat 3.x
     // Just check if any of Bheat 2.5 config is set. Not checking for 3.x as it might have some other configs
     // Like : rerun_cache etc.
     if (!isset($values['filters']['tags']) && !isset($values['extensions']['Behat\\MinkExtension\\Extension'])) {
         return array($profile => $values);
     }
     // Parse 2.5 format and get related values.
     $oldconfigvalues = array();
     if (isset($values['extensions']['Behat\\MinkExtension\\Extension'])) {
         $extensionvalues = $values['extensions']['Behat\\MinkExtension\\Extension'];
         if (isset($extensionvalues['selenium2']['browser'])) {
             $oldconfigvalues['browser'] = $extensionvalues['selenium2']['browser'];
         }
         if (isset($extensionvalues['selenium2']['wd_host'])) {
             $oldconfigvalues['wd_host'] = $extensionvalues['selenium2']['wd_host'];
         }
         if (isset($extensionvalues['capabilities'])) {
             $oldconfigvalues['capabilities'] = $extensionvalues['capabilities'];
         }
     }
     if (isset($values['filters']['tags'])) {
         $oldconfigvalues['tags'] = $values['filters']['tags'];
     }
     if (!empty($oldconfigvalues)) {
         behat_config_manager::$autoprofileconversion = true;
         return $this->get_behat_profile($profile, $oldconfigvalues);
     }
     // If nothing set above then return empty array.
     return array();
 }
Example #6
0
 /**
  * Enables test mode
  *
  * It uses CFG->behat_dataroot
  *
  * Starts the test mode checking the composer installation and
  * the test environment and updating the available
  * features and steps definitions.
  *
  * Stores a file in dataroot/behat to allow Moodle to switch
  * to the test environment when using cli-server.
  * @param bool $themesuitewithallfeatures if only theme specific features need to be included in the suite.
  * @param string $tags comma separated tag, which will be given preference while distributing features in parallel run.
  * @param int $parallelruns number of parallel runs.
  * @param int $run current run.
  * @throws coding_exception
  * @return void
  */
 public static function start_test_mode($themesuitewithallfeatures = false, $tags = '', $parallelruns = 0, $run = 0)
 {
     global $CFG;
     if (!defined('BEHAT_UTIL')) {
         throw new coding_exception('This method can be only used by Behat CLI tool');
     }
     // Checks the behat set up and the PHP version.
     if ($errorcode = behat_command::behat_setup_problem()) {
         exit($errorcode);
     }
     // Check that test environment is correctly set up.
     self::test_environment_problem();
     // Updates all the Moodle features and steps definitions.
     behat_config_manager::update_config_file('', true, $tags, $themesuitewithallfeatures, $parallelruns, $run);
     if (self::is_test_mode_enabled()) {
         return;
     }
     $contents = '$CFG->behat_wwwroot, $CFG->behat_prefix and $CFG->behat_dataroot' . ' are currently used as $CFG->wwwroot, $CFG->prefix and $CFG->dataroot';
     $filepath = self::get_test_file_path();
     if (!file_put_contents($filepath, $contents)) {
         behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $filepath . ' can not be created');
     }
 }
Example #7
0
 /**
  * Allow access to protected method
  * @see parent::get_config_file_contents()
  * @param array $features
  * @param array $stepsdefinitions
  * @return string
  */
 public static function get_config_file_contents($features, $stepsdefinitions)
 {
     return parent::get_config_file_contents($features, $stepsdefinitions);
 }
Example #8
0
require_once $CFG->libdir . '/behat/classes/util.php';
require_once $CFG->libdir . '/behat/classes/behat_command.php';
// Run command (only one per time).
if ($options['install']) {
    behat_util::install_site();
    mtrace("Acceptance tests site installed");
} else {
    if ($options['drop']) {
        // Ensure no tests are running.
        test_lock::acquire('behat');
        behat_util::drop_site();
        mtrace("Acceptance tests site dropped");
    } else {
        if ($options['enable']) {
            behat_util::start_test_mode();
            $runtestscommand = behat_command::get_behat_command(true) . ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
            mtrace("Acceptance tests environment enabled, to run the tests use:\n " . $runtestscommand);
        } else {
            if ($options['disable']) {
                behat_util::stop_test_mode();
                mtrace("Acceptance tests environment disabled");
            } else {
                if ($options['diag']) {
                    $code = behat_util::get_behat_status();
                    exit($code);
                } else {
                    echo $help;
                }
            }
        }
    }
                if ($options['diag']) {
                    $code = behat_util::get_behat_status();
                    exit($code);
                } else {
                    if ($options['updatesteps']) {
                        if (defined('BEHAT_FEATURE_STEP_FILE') && BEHAT_FEATURE_STEP_FILE) {
                            $behatstepfile = BEHAT_FEATURE_STEP_FILE;
                        } else {
                            echo "BEHAT_FEATURE_STEP_FILE is not set, please ensure you set this to writable file" . PHP_EOL;
                            exit(1);
                        }
                        // Rewrite config file to ensure we have all the features covered.
                        behat_config_manager::update_config_file();
                        // Run behat command to get steps in feature files.
                        $featurestepscmd = behat_command::get_behat_command(true);
                        $featurestepscmd .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
                        $featurestepscmd .= ' --dry-run --format=moodle_step_count';
                        $processes = cli_execute_parallel(array($featurestepscmd), __DIR__ . "/../../../../");
                        $status = print_update_step_output(array_pop($processes), $behatstepfile);
                        exit($status);
                    } else {
                        echo $help;
                        exit(1);
                    }
                }
            }
        }
    }
}
exit(0);
/**
 /**
  * Updates a config file
  *
  * @param  array $featurestoadd list of features to add.
  * @param string $proxy proxy url which will be used for test plan generation example: "localhost:9090"
  * @return void
  */
 protected static function update_config_file($featurestoadd, $proxy = "")
 {
     global $CFG;
     // Behat must have a separate behat.yml to have access to the whole set of features and steps definitions.
     $configfilepath = self::get_tool_dir() . DIRECTORY_SEPARATOR . 'behat.yml';
     $featurepath = self::get_tool_dir();
     // Gets all the components with features.
     $featureslist = glob("{$featurepath}/*.feature");
     $features = array();
     foreach ($featurestoadd as $featuretoadd) {
         $feature = preg_grep('/.\\/' . $featuretoadd . '\\.feature/', $featureslist);
         if (!empty($feature)) {
             if (count($feature) > 1) {
                 echo "Found more then 1 feature for the requested order set: ", $featuretoadd . PHP_EOL;
             }
             $features = array_merge($features, $feature);
         }
     }
     // Gets all the components with steps definitions.
     $stepsdefinitions = array();
     $steps = \behat_config_manager::get_components_steps_definitions();
     if ($steps) {
         foreach ($steps as $key => $filepath) {
             $stepsdefinitions[$key] = $filepath;
         }
     }
     // We don't want the deprecated steps definitions here.
     unset($stepsdefinitions['behat_deprecated']);
     // Remove default hooks.
     unset($stepsdefinitions['behat_hooks']);
     // Add generator contexts.
     $classname = get_called_class();
     preg_match('/.*\\\\([a-z-_]+)\\\\[a-z]+$/i', $classname, $behatcontextdir);
     $contexts = glob(__DIR__ . "/../" . $behatcontextdir[1] . "/classes/behat_*.php");
     foreach ($contexts as $context) {
         preg_match('/.*\\/(behat_[a-z_].*)\\.php$/', $context, $matches);
         $classname = $matches[1];
         $stepsdefinitions[$classname] = $context;
     }
     // Add any other context file defined in config.
     $generatorconfig = self::get_config();
     foreach ($featurestoadd as $featurename) {
         if (!empty($generatorconfig[$featurename]['contextpath'])) {
             if (!is_array($generatorconfig[$featurename]['contextpath'])) {
                 $customcontextspaths = array($generatorconfig[$featurename]['contextpath']);
             } else {
                 $customcontextspaths = $generatorconfig[$featurename]['contextpath'];
             }
             foreach ($customcontextspaths as $customcontextpath) {
                 preg_match('/.*\\/(behat_[a-z_].*)\\.php$/', $customcontextpath, $matches);
                 $classname = $matches[1];
                 $stepsdefinitions[$classname] = $customcontextpath;
             }
         }
     }
     // Behat config file specifing the main context class,
     // the required Behat extensions and Moodle test wwwroot.
     $contents = self::get_config_file_contents($features, $stepsdefinitions, $proxy);
     // Stores the file.
     if (!file_put_contents($configfilepath, $contents)) {
         self::performance_exception('File ' . $configfilepath . ' can not be created');
     }
 }
Example #11
0
                 echo PHP_EOL . PHP_EOL;
             }
             $status = (bool) $status || (bool) $exitcode;
         }
     }
 } else {
     if ($options['updatesteps']) {
         // Rewrite config file to ensure we have all the features covered.
         if (empty($options['parallel'])) {
             behat_config_manager::update_config_file('', true, '', $options['run-with-theme'], false, false);
         } else {
             // Update config file, ensuring we have up-to-date behat.yml.
             for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
                 $CFG->behatrunprocess = $i;
                 // Update config file for each run.
                 behat_config_manager::update_config_file('', true, '', $options['run-with-theme'], $options['parallel'], $i);
             }
             unset($CFG->behatrunprocess);
         }
         // Do it sequentially as it's fast and need to be displayed nicely.
         foreach (array_chunk($cmds, 1, true) as $cmd) {
             $processes = cli_execute_parallel($cmd, __DIR__);
             print_sequential_output($processes);
         }
         exit(0);
     } else {
         // We should never reach here.
         echo $help;
         exit(1);
     }
 }
Example #12
0
/**
 * Web interface to list and filter steps
 *
 * @package    tool_behat
 * @copyright  2012 David MonllaĆ³
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require __DIR__ . '/../../../config.php';
require_once $CFG->libdir . '/adminlib.php';
require_once $CFG->dirroot . '/' . $CFG->admin . '/tool/behat/locallib.php';
require_once $CFG->libdir . '/behat/classes/behat_config_manager.php';
$filter = optional_param('filter', '', PARAM_ALPHANUMEXT);
$type = optional_param('type', false, PARAM_ALPHAEXT);
$component = optional_param('component', '', PARAM_ALPHAEXT);
admin_externalpage_setup('toolbehat');
// Getting available steps definitions from behat.
$steps = tool_behat::stepsdefinitions($type, $component, $filter);
// Form.
$componentswithsteps = array('' => get_string('allavailablesteps', 'tool_behat'));
// Complete the components list with the moodle steps definitions.
$components = behat_config_manager::get_components_steps_definitions();
if ($components) {
    foreach ($components as $component => $filepath) {
        // TODO Use a class static attribute instead of the class name.
        $componentswithsteps[$component] = 'Moodle ' . substr($component, 6);
    }
}
$form = new steps_definitions_form(null, array('components' => $componentswithsteps));
// Output contents.
$renderer = $PAGE->get_renderer('tool_behat');
echo $renderer->render_stepsdefinitions($steps, $form);
Example #13
0
                 echo PHP_EOL . PHP_EOL;
             }
             $status = (bool) $status || (bool) $exitcode;
         }
     }
 } else {
     if ($options['updatesteps']) {
         // Rewrite config file to ensure we have all the features covered.
         if (empty($options['parallel'])) {
             behat_config_manager::update_config_file('', true, '', $options['add-core-features-to-theme'], false, false);
         } else {
             // Update config file, ensuring we have up-to-date behat.yml.
             for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
                 $CFG->behatrunprocess = $i;
                 // Update config file for each run.
                 behat_config_manager::update_config_file('', true, $options['optimize-runs'], $options['add-core-features-to-theme'], $options['parallel'], $i);
             }
             unset($CFG->behatrunprocess);
         }
         // Do it sequentially as it's fast and need to be displayed nicely.
         foreach (array_chunk($cmds, 1, true) as $cmd) {
             $processes = cli_execute_parallel($cmd, __DIR__);
             print_sequential_output($processes);
         }
         exit(0);
     } else {
         // We should never reach here.
         echo $help;
         exit(1);
     }
 }
Example #14
0
                 echo $processes[$name]->getErrorOutput();
                 echo PHP_EOL . PHP_EOL;
             }
             $status = (bool) $status || (bool) $exitcode;
         }
     }
 } else {
     if ($options['updatesteps']) {
         // Rewrite config file to ensure we have all the features covered.
         if (empty($options['parallel'])) {
             behat_config_manager::update_config_file();
         } else {
             // Update config file, ensuring we have up-to-date behat.yml.
             for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
                 $CFG->behatrunprocess = $i;
                 behat_config_manager::update_config_file();
             }
             unset($CFG->behatrunprocess);
         }
         // Do it sequentially as it's fast and need to be displayed nicely.
         foreach (array_chunk($cmds, 1, true) as $cmd) {
             $processes = cli_execute_parallel($cmd, __DIR__);
             print_sequential_output($processes);
         }
         exit(0);
     } else {
         // We should never reach here.
         echo $help;
         exit(1);
     }
 }