MDL-81889 tool_generator: add examples to behat steps

The tool_generator creates a testing scenario that can execute
all steps from behat_data_generators (with some limitations),
change admin settings and delete courses and users to cleanup
the created entities. However, this list of valid steps will
change over time and it will be great if all available steps
are listed with examples.
This commit is contained in:
ferranrecio
2024-08-12 12:25:46 +02:00
parent a75365f2e4
commit a2ed8a036d
12 changed files with 226 additions and 3 deletions
+2
View File
@@ -90,6 +90,8 @@ class behat_admin extends behat_base {
* @Given /^the following config values are set as admin:$/
* @param TableNode $table
*/
#[\core\attribute\example('And the following config values are set as admin:
| sendcoursewelcomemessage | 0 | enrol_manual |')]
public function the_following_config_values_are_set_as_admin(TableNode $table) {
if (!$data = $table->getRowsHash()) {
@@ -22,6 +22,7 @@ use behat_base;
use behat_course;
use behat_general;
use behat_user;
use core\attribute_helper;
use Behat\Gherkin\Parser;
use Behat\Gherkin\Lexer;
use Behat\Gherkin\Keywords\ArrayKeywords;
@@ -135,6 +136,14 @@ class runner {
}
}
/**
* Get all valid steps.
* @return array the valid steps.
*/
public function get_valid_steps(): array {
return array_values($this->validsteps);
}
/**
* Scan a generator to get all valid steps.
* @param behat_data_generators $generator the generator to scan.
@@ -164,11 +173,17 @@ class runner {
if (!$given) {
return null;
}
return (object)[
$result = (object)[
'given' => $given,
'name' => $method->getName(),
'generator' => $behatclass,
'example' => null,
];
$reference = $method->getDeclaringClass()->getName() . '::' . $method->getName();
if ($attribute = attribute_helper::instance($reference, \core\attribute\example::class)) {
$result->example = (string) $attribute->example;
}
return $result;
}
/**
@@ -0,0 +1,78 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_generator\output;
use templatable;
use tool_generator\local\testscenario\runner;
/**
* Class stepsinformation
*
* @package tool_generator
* @copyright 2024 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class stepsinformation implements templatable, \renderable {
/**
* Constructor.
*
* @param runner $runner the scenario runner
*/
public function __construct(
/** @var runner the runner instance. */
public runner $runner
) {
}
/**
* Export this data so it can be used as the context for a mustache template (core/inplace_editable).
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @return \stdClass data context for a mustache template
*/
public function export_for_template(\renderer_base $output): \stdClass {
$steps = [];
$validsteps = $this->runner->get_valid_steps();
foreach ($validsteps as $step) {
$steps[] = (object)[
'given' => $this->highlight_params($step->given),
'example' => $step->example,
];
}
return (object) [
'steps' => $steps,
];
}
/**
* Highlight the parameters in a step.
*
* @param string $step the step to highlight
* @return string the step with the parameters highlighted
*/
private function highlight_params(string $step): string {
$step = htmlentities($step);
// Highlight params starting with ":".
$step = preg_replace('/:(\w+)/', '<strong>$0</strong>', $step);
// Highlight params enclosed in "(?P<...>)".
$step = preg_replace('/\(\?P&lt;(\w+)&gt;((?:[^"]|\\")*)\)/', '<strong>$0</strong>', $step);
return $step;
}
}
@@ -97,10 +97,14 @@ $string['sitesize_4'] = 'XL (~10GB; 1065 courses, created in ~5 hours)';
$string['sitesize_5'] = 'XXL (~20GB; 4177 courses, created in ~10 hours)';
$string['size'] = 'Size of course';
$string['smallfiles'] = 'Small files';
$string['step_example'] = 'Step example:';
$string['targetcourse'] = 'Test target course';
$string['testscenario'] = 'Create testing scenarios';
$string['testscenario_description'] = 'Creating testing scenarios uses a limited feature files syntax to create all necessary elements to run a manual test.';
$string['testscenario_filedesc'] = 'The upload feature files can only contain scenarios with core_data_generator steps. It is not yet compatible with scenario outlines. All scenarios will be executed at once but background steps will be ignored.';
$string['testscenario_filedesc'] = 'The upload feature files can only contain scenarios with core_data_generator steps or some specific steps that do not require selenium. All scenarios will be executed at once except the ones with @cleanup tag.';
$string['testscenario_filedesc_cleanup'] = 'Scenarios with @cleanup tag will be executed only if the "Execute" setting
is set to "Cleanup". To execute the cleanup via CLI, you can use the --cleanup option.';
$string['testscenario_filedesc_list'] = 'This is the list of steps that can be used in the test scenario feature file:';
$string['testscenario_errorparsing'] = 'Error parsing feature file: {$a}';
$string['testscenario_file'] = 'Feature file';
$string['testscenario_invalidfile'] = 'The file format is not valid or contains invalid steps.';
+2 -1
View File
@@ -25,6 +25,7 @@
use tool_generator\local\testscenario\runner;
use tool_generator\form\featureimport;
use tool_generator\output\parsingresult;
use tool_generator\output\stepsinformation;
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -54,7 +55,7 @@ try {
die;
}
echo $output->paragraph(get_string('testscenario_filedesc', 'tool_generator'));
echo $output->render(new stepsinformation($runner));
$mform = new featureimport();
@@ -0,0 +1,59 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template tool_generator/stepsinformation
Template with the available steps for the generator tool.
Example context (json):
{
"steps": [
{
"given": "I do something with <strong>:param</strong>",
"example": "example code"
},
{
"given": "I do another thing with <strong>:param</strong>"
}
]
}
}}
<div class="border rounded border-info mb-3 p-2" id="stepsinformation">
{{< core/showmore }}
{{$collapsedcontent}}
{{#str}} testscenario_filedesc, tool_generator {{/str}}
{{/collapsedcontent}}
{{$expandedcontent}}
<p>{{#str}} testscenario_filedesc, tool_generator {{/str}}</p>
<p>{{#str}} testscenario_filedesc_cleanup, tool_generator {{/str}}</p>
<p>{{#str}} testscenario_filedesc_list, tool_generator {{/str}}</p>
<ul class="list-group">
{{#steps}}
<li class="list-group-item">
{{{given}}}
{{#example}}
<div class="alert alert-info mb-0 mt-2" role="alert" style="overflow: auto;">
<div class="font-weight-bold mr-2 ">{{#str}} step_example, tool_generator {{/str}}</div>
<pre class="mb-0">{{example}}</pre>
</div>
{{/example}}
</li>
{{/steps}}
</ul>
{{/expandedcontent}}
{{/core/showmore }}
</div>
@@ -96,3 +96,16 @@ Feature: Create testing scenarios using generators
And I should not see "Course cleanup" in the "course-listing" "region"
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I should not see "Teacher Test1"
Scenario: All available steps are listed in the tool to create testing scenarios
Given I log in as "admin"
When I navigate to "Development > Create testing scenarios" in site administration
Then I should see "This is the list of steps that can be used in the test scenario feature file"
And I should see "And the following \"activities\" exist"
And I should see "And \"5\" \"course enrolments\" exist with the following data"
And I should see "And the following \"course\" exists"
And I should see "And the following config values are set as admin"
And I should see "I enable \"subsection\" \"mod\" plugin"
And I should see "I disable \"page\" \"mod\" plugin"
And I should see "And the course \"Course test\" is deleted"
And I should see "And the user student1 is deleted"
+1
View File
@@ -1159,6 +1159,7 @@ class behat_course extends behat_base {
* @Given the course :coursefullname is deleted
* @param string $coursefullname
*/
#[\core\attribute\example('And the course "Course test" is deleted')]
public function the_course_is_deleted($coursefullname) {
delete_course($this->get_course_id($coursefullname), false);
fix_course_sortorder();
+33
View File
@@ -0,0 +1,33 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core\attribute;
/**
* An string attribute used to add an example of use of an object.
*
* @package core
* @copyright 2024 Ferran Recio <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
#[\Attribute]
class example {
public function __construct(
/** @var string the example text. */
public readonly string $example,
) {
}
}
+14
View File
@@ -84,6 +84,10 @@ class behat_data_generators extends behat_base {
* @param string $entitytype The name of the type entity to add
* @param TableNode $data
*/
#[\core\attribute\example('And the following "activities" exist:
| activity | name | intro | course | idnumber | section | visible |
| assign | Activity sample 1 | Test assignment | C1 | sample1 | 1 | 1 |
| assign | Activity sample 2 | Test assignment | C1 | sample2 | 1 | 0 |')]
public function the_following_entities_exist($entitytype, TableNode $data) {
if (isset($this->movedentitytypes[$entitytype])) {
$entitytype = $this->movedentitytypes[$entitytype];
@@ -101,6 +105,10 @@ class behat_data_generators extends behat_base {
* @param int $count
* @param TableNode $data
*/
#[\core\attribute\example('And "5" "course enrolments" exist with the following data:
| user | student[count] |
| course | C1 |
| role | student |')]
public function the_following_repeated_entities_exist(string $entitytype, int $count, TableNode $data): void {
$rows = $data->getRowsHash();
@@ -130,6 +138,12 @@ class behat_data_generators extends behat_base {
* @param string $entitytype The name of the type entity to add
* @param TableNode $data
*/
#[\core\attribute\example('And the following "course" exists:
| fullname | Course test |
| shortname | C1 |
| category | 0 |
| numsections | 3 |
| initsections | 1 |')]
public function the_following_entity_exists($entitytype, TableNode $data) {
if (isset($this->movedentitytypes[$entitytype])) {
$entitytype = $this->movedentitytypes[$entitytype];
+2
View File
@@ -2366,6 +2366,7 @@ EOF;
* @param string $plugin Plugin we look for
* @param string $plugintype The type of the plugin
*/
#[\core\attribute\example('I enable "subsection" "mod" plugin')]
public function i_enable_plugin($plugin, $plugintype) {
$class = core_plugin_manager::resolve_plugininfo_class($plugintype);
$class::enable_plugin($plugin, true);
@@ -2378,6 +2379,7 @@ EOF;
* @param string $plugin Plugin we look for
* @param string $plugintype The type of the plugin
*/
#[\core\attribute\example('I disable "page" "mod" plugin')]
public function i_disable_plugin($plugin, $plugintype) {
$class = core_plugin_manager::resolve_plugininfo_class($plugintype);
$class::enable_plugin($plugin, false);
+1
View File
@@ -58,6 +58,7 @@ class behat_user extends behat_base {
* @Given the user :identifier is deleted
* @param string $identifier
*/
#[\core\attribute\example('And the user student1 is deleted')]
public function the_user_is_deleted($identifier) {
global $DB;
$userid = $this->get_user_id_by_identifier($identifier);