See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
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 * Behat command utils 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 30 /** 31 * Behat command related utils 32 * 33 * @package core 34 * @category test 35 * @copyright 2013 David MonllaĆ³ 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class behat_command { 39 40 /** 41 * Docs url 42 */ 43 const DOCS_URL = 'https://moodledev.io/general/development/tools/behat'; 44 45 /** 46 * Ensures the behat dir exists in moodledata 47 * 48 * @return string Full path 49 */ 50 public static function get_parent_behat_dir() { 51 global $CFG; 52 53 // If not set then return empty string. 54 if (!isset($CFG->behat_dataroot_parent)) { 55 return ""; 56 } 57 58 return $CFG->behat_dataroot_parent; 59 } 60 61 /** 62 * Ensures the behat dir exists in moodledata 63 * @param int $runprocess run process for which behat dir is returned. 64 * @return string Full path 65 */ 66 public static function get_behat_dir($runprocess = 0) { 67 global $CFG; 68 69 // If not set then return empty string. 70 if (!isset($CFG->behat_dataroot)) { 71 return ""; 72 } 73 74 // If $CFG->behat_parallel_run starts with index 0 and $runprocess for parallel run starts with 1. 75 if (!empty($runprocess) && isset($CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'])) { 76 $behatdir = $CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'] . '/behat';; 77 } else { 78 $behatdir = $CFG->behat_dataroot . '/behat'; 79 } 80 81 if (!is_dir($behatdir)) { 82 if (!mkdir($behatdir, $CFG->directorypermissions, true)) { 83 behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Directory ' . $behatdir . ' can not be created'); 84 } 85 } 86 87 if (!is_writable($behatdir)) { 88 behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Directory ' . $behatdir . ' is not writable'); 89 } 90 91 return $behatdir; 92 } 93 94 /** 95 * Returns the executable path 96 * 97 * Allows returning a customized command for cygwin when the 98 * command is just displayed, when using exec(), system() and 99 * friends we stay with DIRECTORY_SEPARATOR as they use the 100 * normal cmd.exe (in Windows). 101 * 102 * @param bool $custombyterm If the provided command should depend on the terminal where it runs 103 * @param bool $parallelrun If parallel run is installed. 104 * @param bool $absolutepath return command with absolute path. 105 * @return string 106 */ 107 public final static function get_behat_command($custombyterm = false, $parallerun = false, $absolutepath = false) { 108 109 $separator = DIRECTORY_SEPARATOR; 110 $exec = 'behat'; 111 112 // Cygwin uses linux-style directory separators. 113 if ($custombyterm && testing_is_cygwin()) { 114 $separator = '/'; 115 116 // MinGW can not execute .bat scripts. 117 if (!testing_is_mingw()) { 118 $exec = 'behat.bat'; 119 } 120 } 121 122 // If relative path then prefix relative path. 123 if ($absolutepath) { 124 $pathprefix = testing_cli_argument_path('/'); 125 if (!empty($pathprefix)) { 126 $pathprefix .= $separator; 127 } 128 } else { 129 $pathprefix = ''; 130 } 131 132 if (!$parallerun) { 133 $command = $pathprefix . 'vendor' . $separator . 'bin' . $separator . $exec; 134 } else { 135 $command = 'php ' . $pathprefix . 'admin' . $separator . 'tool' . $separator . 'behat' . $separator . 'cli' 136 . $separator . 'run.php'; 137 } 138 return $command; 139 } 140 141 /** 142 * Runs behat command with provided options 143 * 144 * Execution continues when the process finishes 145 * 146 * @param string $options Defaults to '' so tests would be executed 147 * @return array CLI command outputs [0] => string, [1] => integer 148 */ 149 public final static function run($options = '') { 150 global $CFG; 151 152 $currentcwd = getcwd(); 153 chdir($CFG->dirroot); 154 exec(self::get_behat_command() . ' ' . $options, $output, $code); 155 chdir($currentcwd); 156 157 return array($output, $code); 158 } 159 160 /** 161 * Checks if behat is set up and working 162 * 163 * Notifies failures both from CLI and web interface. 164 * 165 * It checks behat dependencies have been installed and runs 166 * the behat help command to ensure it works as expected 167 * 168 * @return int Error code or 0 if all ok 169 */ 170 public static function behat_setup_problem() { 171 global $CFG; 172 173 // Moodle setting. 174 if (!self::are_behat_dependencies_installed()) { 175 176 // Returning composer error code to avoid conflicts with behat and moodle error codes. 177 self::output_msg(get_string('errorcomposer', 'tool_behat')); 178 return TESTING_EXITCODE_COMPOSER; 179 } 180 181 // Behat test command. 182 $dirrootconfigpath = $CFG->dirroot . DIRECTORY_SEPARATOR . 'behat.yml'; 183 if (file_exists($dirrootconfigpath)) { 184 self::output_msg(get_string('warndirrootconfigfound', 'tool_behat', $dirrootconfigpath)); 185 } 186 list($output, $code) = self::run(" --help"); 187 188 if ($code != 0) { 189 190 // Returning composer error code to avoid conflicts with behat and moodle error codes. 191 self::output_msg(get_string('errorbehatcommand', 'tool_behat', self::get_behat_command())); 192 return TESTING_EXITCODE_COMPOSER; 193 } 194 195 // No empty values. 196 if (empty($CFG->behat_dataroot) || empty($CFG->behat_prefix) || empty($CFG->behat_wwwroot)) { 197 self::output_msg(get_string('errorsetconfig', 'tool_behat')); 198 return BEHAT_EXITCODE_CONFIG; 199 200 } 201 202 // Not repeated values. 203 // We only need to check this when the behat site is not running as 204 // at this point, when it is running, all $CFG->behat_* vars have 205 // already been copied to $CFG->dataroot, $CFG->prefix and $CFG->wwwroot. 206 $phpunitprefix = empty($CFG->phpunit_prefix) ? '' : $CFG->phpunit_prefix; 207 $behatdbname = empty($CFG->behat_dbname) ? $CFG->dbname : $CFG->behat_dbname; 208 $phpunitdbname = empty($CFG->phpunit_dbname) ? $CFG->dbname : $CFG->phpunit_dbname; 209 $behatdbhost = empty($CFG->behat_dbhost) ? $CFG->dbhost : $CFG->behat_dbhost; 210 $phpunitdbhost = empty($CFG->phpunit_dbhost) ? $CFG->dbhost : $CFG->phpunit_dbhost; 211 212 $samedataroot = $CFG->behat_dataroot == $CFG->dataroot; 213 $samedataroot = $samedataroot || (!empty($CFG->phpunit_dataroot) && $CFG->phpunit_dataroot == $CFG->behat_dataroot); 214 $samewwwroot = $CFG->behat_wwwroot == $CFG->wwwroot; 215 $sameprefix = ($CFG->behat_prefix == $CFG->prefix && $behatdbname == $CFG->dbname && $behatdbhost == $CFG->dbhost); 216 $sameprefix = $sameprefix || ($CFG->behat_prefix == $phpunitprefix && $behatdbname == $phpunitdbname && 217 $behatdbhost == $phpunitdbhost); 218 if (!defined('BEHAT_SITE_RUNNING') && ($samedataroot || $samewwwroot || $sameprefix)) { 219 self::output_msg(get_string('erroruniqueconfig', 'tool_behat')); 220 return BEHAT_EXITCODE_CONFIG; 221 } 222 223 // Checking behat dataroot existence otherwise echo about admin/tool/behat/cli/init.php. 224 if (!empty($CFG->behat_dataroot)) { 225 $CFG->behat_dataroot = realpath($CFG->behat_dataroot); 226 } 227 if (empty($CFG->behat_dataroot) || !is_dir($CFG->behat_dataroot) || !is_writable($CFG->behat_dataroot)) { 228 self::output_msg(get_string('errordataroot', 'tool_behat')); 229 return BEHAT_EXITCODE_CONFIG; 230 } 231 232 return 0; 233 } 234 235 /** 236 * Has the site installed composer. 237 * @return bool 238 */ 239 public static function are_behat_dependencies_installed() { 240 if (!is_dir(__DIR__ . '/../../../vendor/behat')) { 241 return false; 242 } 243 return true; 244 } 245 246 /** 247 * Outputs a message. 248 * 249 * Used in CLI + web UI methods. Stops the 250 * execution in web. 251 * 252 * @param string $msg 253 * @return void 254 */ 255 protected static function output_msg($msg) { 256 global $CFG, $PAGE; 257 258 // If we are using the web interface we want pretty messages. 259 if (!CLI_SCRIPT) { 260 261 $renderer = $PAGE->get_renderer('tool_behat'); 262 echo $renderer->render_error($msg); 263 264 // Stopping execution. 265 exit(1); 266 267 } else { 268 269 // We continue execution after this. 270 $clibehaterrorstr = "Ensure you set \$CFG->behat_* vars in config.php " . 271 "and you ran admin/tool/behat/cli/init.php.\n" . 272 "More info in " . self::DOCS_URL; 273 274 echo 'Error: ' . $msg . "\n\n" . $clibehaterrorstr; 275 } 276 } 277 278 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body