[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/behat/classes/ -> behat_config_manager.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Utils to set Behat config
  19   *
  20   * @package    core
  21   * @category   test
  22   * @copyright  2012 David Monllaó
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  require_once (__DIR__ . '/../lib.php');
  29  require_once (__DIR__ . '/behat_command.php');
  30  require_once (__DIR__ . '/../../testing/classes/tests_finder.php');
  31  
  32  /**
  33   * Behat configuration manager
  34   *
  35   * Creates/updates Behat config files getting tests
  36   * and steps from Moodle codebase
  37   *
  38   * @package    core
  39   * @category   test
  40   * @copyright  2012 David Monllaó
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class behat_config_manager {
  44  
  45      /**
  46       * Updates a config file
  47       *
  48       * The tests runner and the steps definitions list uses different
  49       * config files to avoid problems with concurrent executions.
  50       *
  51       * The steps definitions list can be filtered by component so it's
  52       * behat.yml is different from the $CFG->dirroot one.
  53       *
  54       * @param  string $component Restricts the obtained steps definitions to the specified component
  55       * @param  string $testsrunner If the config file will be used to run tests
  56       * @return void
  57       */
  58      public static function update_config_file($component = '', $testsrunner = true) {
  59          global $CFG;
  60  
  61          // Behat must have a separate behat.yml to have access to the whole set of features and steps definitions.
  62          if ($testsrunner === true) {
  63              $configfilepath = behat_command::get_behat_dir() . '/behat.yml';
  64          } else {
  65              // Alternative for steps definitions filtering, one for each user.
  66              $configfilepath = self::get_steps_list_config_filepath();
  67          }
  68  
  69          // Gets all the components with features.
  70          $features = array();
  71          $components = tests_finder::get_components_with_tests('features');
  72          if ($components) {
  73              foreach ($components as $componentname => $path) {
  74                  $path = self::clean_path($path) . self::get_behat_tests_path();
  75                  if (empty($featurespaths[$path]) && file_exists($path)) {
  76  
  77                      // Standarizes separator (some dirs. comes with OS-dependant separator).
  78                      $uniquekey = str_replace('\\', '/', $path);
  79                      $featurespaths[$uniquekey] = $path;
  80                  }
  81              }
  82              $features = array_values($featurespaths);
  83          }
  84  
  85          // Optionally include features from additional directories.
  86          if (!empty($CFG->behat_additionalfeatures)) {
  87              $features = array_merge($features, array_map("realpath", $CFG->behat_additionalfeatures));
  88          }
  89  
  90          // Gets all the components with steps definitions.
  91          $stepsdefinitions = array();
  92          $steps = self::get_components_steps_definitions();
  93          if ($steps) {
  94              foreach ($steps as $key => $filepath) {
  95                  if ($component == '' || $component === $key) {
  96                      $stepsdefinitions[$key] = $filepath;
  97                  }
  98              }
  99          }
 100  
 101          // We don't want the deprecated steps definitions here.
 102          if (!$testsrunner) {
 103              unset($stepsdefinitions['behat_deprecated']);
 104          }
 105  
 106          // Behat config file specifing the main context class,
 107          // the required Behat extensions and Moodle test wwwroot.
 108          $contents = self::get_config_file_contents($features, $stepsdefinitions);
 109  
 110          // Stores the file.
 111          if (!file_put_contents($configfilepath, $contents)) {
 112              behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $configfilepath . ' can not be created');
 113          }
 114  
 115      }
 116  
 117      /**
 118       * Gets the list of Moodle steps definitions
 119       *
 120       * Class name as a key and the filepath as value
 121       *
 122       * Externalized from update_config_file() to use
 123       * it from the steps definitions web interface
 124       *
 125       * @return array
 126       */
 127      public static function get_components_steps_definitions() {
 128  
 129          $components = tests_finder::get_components_with_tests('stepsdefinitions');
 130          if (!$components) {
 131              return false;
 132          }
 133  
 134          $stepsdefinitions = array();
 135          foreach ($components as $componentname => $componentpath) {
 136              $componentpath = self::clean_path($componentpath);
 137  
 138              if (!file_exists($componentpath . self::get_behat_tests_path())) {
 139                  continue;
 140              }
 141              $diriterator = new DirectoryIterator($componentpath . self::get_behat_tests_path());
 142              $regite = new RegexIterator($diriterator, '|behat_.*\.php$|');
 143  
 144              // All behat_*.php inside behat_config_manager::get_behat_tests_path() are added as steps definitions files.
 145              foreach ($regite as $file) {
 146                  $key = $file->getBasename('.php');
 147                  $stepsdefinitions[$key] = $file->getPathname();
 148              }
 149          }
 150  
 151          return $stepsdefinitions;
 152      }
 153  
 154      /**
 155       * Returns the behat config file path used by the steps definition list
 156       *
 157       * @return string
 158       */
 159      public static function get_steps_list_config_filepath() {
 160          global $USER;
 161  
 162          // We don't cygwin-it as it is called using exec() which uses cmd.exe.
 163          $userdir = behat_command::get_behat_dir() . '/users/' . $USER->id;
 164          make_writable_directory($userdir);
 165  
 166          return $userdir . '/behat.yml';
 167      }
 168  
 169      /**
 170       * Returns the behat config file path used by the behat cli command.
 171       *
 172       * @return string
 173       */
 174      public static function get_behat_cli_config_filepath() {
 175          global $CFG;
 176  
 177          $command = $CFG->behat_dataroot . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . 'behat.yml';
 178  
 179          // Cygwin uses linux-style directory separators.
 180          if (testing_is_cygwin()) {
 181              $command = str_replace('\\', '/', $command);
 182          }
 183  
 184          return $command;
 185      }
 186  
 187      /**
 188       * Behat config file specifing the main context class,
 189       * the required Behat extensions and Moodle test wwwroot.
 190       *
 191       * @param array $features The system feature files
 192       * @param array $stepsdefinitions The system steps definitions
 193       * @return string
 194       */
 195      protected static function get_config_file_contents($features, $stepsdefinitions) {
 196          global $CFG;
 197  
 198          // We require here when we are sure behat dependencies are available.
 199          require_once($CFG->dirroot . '/vendor/autoload.php');
 200  
 201          // It is possible that it has no value as we don't require a full behat setup to list the step definitions.
 202          if (empty($CFG->behat_wwwroot)) {
 203              $CFG->behat_wwwroot = 'http://itwillnotbeused.com';
 204          }
 205  
 206          $basedir = $CFG->dirroot . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'behat';
 207          $config = array(
 208              'default' => array(
 209                  'paths' => array(
 210                      'features' => $basedir . DIRECTORY_SEPARATOR . 'features',
 211                      'bootstrap' => $basedir . DIRECTORY_SEPARATOR . 'features' . DIRECTORY_SEPARATOR . 'bootstrap',
 212                  ),
 213                  'context' => array(
 214                      'class' => 'behat_init_context'
 215                  ),
 216                  'extensions' => array(
 217                      'Behat\MinkExtension\Extension' => array(
 218                          'base_url' => $CFG->behat_wwwroot,
 219                          'goutte' => null,
 220                          'selenium2' => null
 221                      ),
 222                      'Moodle\BehatExtension\Extension' => array(
 223                          'formatters' => array(
 224                              'moodle_progress' => 'Moodle\BehatExtension\Formatter\MoodleProgressFormatter'
 225                          ),
 226                          'features' => $features,
 227                          'steps_definitions' => $stepsdefinitions
 228                      )
 229                  ),
 230                  'formatter' => array(
 231                      'name' => 'moodle_progress'
 232                  )
 233              )
 234          );
 235  
 236          // In case user defined overrides respect them over our default ones.
 237          if (!empty($CFG->behat_config)) {
 238              $config = self::merge_config($config, $CFG->behat_config);
 239          }
 240  
 241          return Symfony\Component\Yaml\Yaml::dump($config, 10, 2);
 242      }
 243  
 244      /**
 245       * Overrides default config with local config values
 246       *
 247       * array_merge does not merge completely the array's values
 248       *
 249       * @param mixed $config The node of the default config
 250       * @param mixed $localconfig The node of the local config
 251       * @return mixed The merge result
 252       */
 253      protected static function merge_config($config, $localconfig) {
 254  
 255          if (!is_array($config) && !is_array($localconfig)) {
 256              return $localconfig;
 257          }
 258  
 259          // Local overrides also deeper default values.
 260          if (is_array($config) && !is_array($localconfig)) {
 261              return $localconfig;
 262          }
 263  
 264          foreach ($localconfig as $key => $value) {
 265  
 266              // If defaults are not as deep as local values let locals override.
 267              if (!is_array($config)) {
 268                  unset($config);
 269              }
 270  
 271              // Add the param if it doesn't exists or merge branches.
 272              if (empty($config[$key])) {
 273                  $config[$key] = $value;
 274              } else {
 275                  $config[$key] = self::merge_config($config[$key], $localconfig[$key]);
 276              }
 277          }
 278  
 279          return $config;
 280      }
 281  
 282      /**
 283       * Cleans the path returned by get_components_with_tests() to standarize it
 284       *
 285       * @see tests_finder::get_all_directories_with_tests() it returns the path including /tests/
 286       * @param string $path
 287       * @return string The string without the last /tests part
 288       */
 289      protected final static function clean_path($path) {
 290  
 291          $path = rtrim($path, DIRECTORY_SEPARATOR);
 292  
 293          $parttoremove = DIRECTORY_SEPARATOR . 'tests';
 294  
 295          $substr = substr($path, strlen($path) - strlen($parttoremove));
 296          if ($substr == $parttoremove) {
 297              $path = substr($path, 0, strlen($path) - strlen($parttoremove));
 298          }
 299  
 300          return rtrim($path, DIRECTORY_SEPARATOR);
 301      }
 302  
 303      /**
 304       * The relative path where components stores their behat tests
 305       *
 306       * @return string
 307       */
 308      protected final static function get_behat_tests_path() {
 309          return DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'behat';
 310      }
 311  
 312  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1