MDL-43450 behat: Improving error messages
[moodle.git] / lib / behat / classes / behat_command.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once(__DIR__ . '/../lib.php');
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 {
40     /**
41      * Docs url
42      */
43     const DOCS_URL = 'http://docs.moodle.org/dev/Acceptance_testing';
45     /**
46      * Ensures the behat dir exists in moodledata
47      * @return string Full path
48      */
49     public static function get_behat_dir() {
50         global $CFG;
52         $behatdir = $CFG->behat_dataroot . '/behat';
54         if (!is_dir($behatdir)) {
55             if (!mkdir($behatdir, $CFG->directorypermissions, true)) {
56                 behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Directory ' . $behatdir . ' can not be created');
57             }
58         }
60         if (!is_writable($behatdir)) {
61             behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Directory ' . $behatdir . ' is not writable');
62         }
64         return $behatdir;
65     }
67     /**
68      * Returns the executable path
69      *
70      * Allows returning a customized command for cygwin when the
71      * command is just displayed, when using exec(), system() and
72      * friends we stay with DIRECTORY_SEPARATOR as they use the
73      * normal cmd.exe (in Windows).
74      *
75      * @param  bool $custombyterm  If the provided command should depend on the terminal where it runs
76      * @return string
77      */
78     public final static function get_behat_command($custombyterm = false) {
80         $separator = DIRECTORY_SEPARATOR;
81         $exec = 'behat';
83         // Cygwin uses linux-style directory separators.
84         if ($custombyterm && testing_is_cygwin()) {
85             $separator = '/';
87             // MinGW can not execute .bat scripts.
88             if (!testing_is_mingw()) {
89                 $exec = 'behat.bat';
90             }
91         }
92         return 'vendor' . $separator . 'bin' . $separator . $exec;
93     }
95     /**
96      * Runs behat command with provided options
97      *
98      * Execution continues when the process finishes
99      *
100      * @param  string $options  Defaults to '' so tests would be executed
101      * @return array            CLI command outputs [0] => string, [1] => integer
102      */
103     public final static function run($options = '') {
104         global $CFG;
106         $currentcwd = getcwd();
107         chdir($CFG->dirroot);
108         exec(self::get_behat_command() . ' ' . $options, $output, $code);
109         chdir($currentcwd);
111         return array($output, $code);
112     }
114     /**
115      * Checks if behat is set up and working
116      *
117      * Notifies failures both from CLI and web interface.
118      *
119      * It checks behat dependencies have been installed and runs
120      * the behat help command to ensure it works as expected
121      *
122      * @return int Error code or 0 if all ok
123      */
124     public static function behat_setup_problem() {
125         global $CFG;
127         // Moodle setting.
128         if (!self::are_behat_dependencies_installed()) {
130             // Returning composer error code to avoid conflicts with behat and moodle error codes.
131             self::output_msg(get_string('errorcomposer', 'tool_behat'));
132             return BEHAT_EXITCODE_COMPOSER;
133         }
135         // Behat test command.
136         list($output, $code) = self::run(' --help');
138         if ($code != 0) {
140             // Returning composer error code to avoid conflicts with behat and moodle error codes.
141             self::output_msg(get_string('errorbehatcommand', 'tool_behat', self::get_behat_command()));
142             return BEHAT_EXITCODE_COMPOSER;
143         }
145         if (empty($CFG->behat_dataroot) || empty($CFG->behat_prefix) || empty($CFG->behat_wwwroot)) {
146             self::output_msg(get_string('errorsetconfig', 'tool_behat'));
147             return BEHAT_EXITCODE_CONFIG;
148         }
150         // Checking behat dataroot existence otherwise echo about admin/tool/behat/cli/init.php.
151         if (!empty($CFG->behat_dataroot)) {
152             $CFG->behat_dataroot = realpath($CFG->behat_dataroot);
153         }
154         if (empty($CFG->behat_dataroot) || !is_dir($CFG->behat_dataroot) || !is_writable($CFG->behat_dataroot)) {
155             self::output_msg(get_string('errordataroot', 'tool_behat'));
156             return BEHAT_EXITCODE_CONFIG;
157         }
159         return 0;
160     }
162     /**
163      * Has the site installed composer with --dev option
164      * @return bool
165      */
166     public static function are_behat_dependencies_installed() {
167         if (!is_dir(__DIR__ . '/../../../vendor/behat')) {
168             return false;
169         }
170         return true;
171     }
173     /**
174      * Outputs a message.
175      *
176      * Used in CLI + web UI methods. Stops the
177      * execution in web.
178      *
179      * @param string $msg
180      * @return void
181      */
182     protected static function output_msg($msg) {
183         global $CFG, $PAGE;
185         // If we are using the web interface we want pretty messages.
186         if (!CLI_SCRIPT) {
188             $renderer = $PAGE->get_renderer('tool_behat');
189             echo $renderer->render_error($msg);
191             // Stopping execution.
192             exit(1);
194         } else {
196             // We continue execution after this.
197             $clibehaterrorstr = "Ensure you set \$CFG->behat_* vars in config.php " .
198                 "and you ran admin/tool/behat/cli/init.php.\n" .
199                 "More info in " . self::DOCS_URL . "#Installation\n\n";
201             echo 'Error: ' . $msg . "\n\n" . $clibehaterrorstr;
202         }
203     }