PageRenderTime 56ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/tests/behat/behat_data_generators.php

https://bitbucket.org/moodle/moodle
PHP | 173 lines | 62 code | 12 blank | 99 comment | 12 complexity | d20c2746823f790c2e5a005587e765d7 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  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. * Data generators for acceptance testing.
  18. *
  19. * @package core
  20. * @category test
  21. * @copyright 2012 David MonllaĆ³
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
  25. require_once(__DIR__ . '/../../behat/behat_base.php');
  26. use Behat\Gherkin\Node\TableNode as TableNode;
  27. use Behat\Behat\Tester\Exception\PendingException as PendingException;
  28. /**
  29. * Class to set up quickly a Given environment.
  30. *
  31. * The entry point is the Behat steps:
  32. * the following "entity types" exist:
  33. * | test | data |
  34. *
  35. * Entity type will either look like "users" or "activities" for core entities, or
  36. * "mod_forum > subscription" or "core_message > message" for entities belonging
  37. * to components.
  38. *
  39. * Generally, you only need to specify properties relevant to your test,
  40. * and everything else gets set to sensible defaults.
  41. *
  42. * The actual generation of entities is done by {@link behat_generator_base}.
  43. * There is one subclass for each component, e.g. {@link behat_core_generator}
  44. * or {@link behat_mod_quiz_generator}. To see the types of entity
  45. * that can be created for each component, look at the arrays returned
  46. * by the get_creatable_entities() method in each class.
  47. *
  48. * @package core
  49. * @category test
  50. * @copyright 2012 David MonllaĆ³
  51. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  52. */
  53. class behat_data_generators extends behat_base {
  54. /**
  55. * Convert legacy entity names to the new component-specific form.
  56. *
  57. * In the past, there was no support for plugins, and everything that
  58. * could be created was handled by the core generator. Now, we can
  59. * support plugins, and so some thing should probably be moved.
  60. *
  61. * For example, in the future we should probably add
  62. * 'message contacts' => 'core_message > contact'] to
  63. * this array, and move generation of message contact
  64. * from core to core_message.
  65. *
  66. * @var array old entity type => new entity type.
  67. */
  68. protected $movedentitytypes = [
  69. ];
  70. /**
  71. * Creates the specified elements.
  72. *
  73. * See the class comment for an overview.
  74. *
  75. * @Given /^the following "(?P<element_string>(?:[^"]|\\")*)" exist:$/
  76. *
  77. * @param string $entitytype The name of the type entity to add
  78. * @param TableNode $data
  79. */
  80. public function the_following_entities_exist($entitytype, TableNode $data) {
  81. if (isset($this->movedentitytypes[$entitytype])) {
  82. $entitytype = $this->movedentitytypes[$entitytype];
  83. }
  84. list($component, $entity) = $this->parse_entity_type($entitytype);
  85. $this->get_instance_for_component($component)->generate_items($entity, $data);
  86. }
  87. /**
  88. * Creates the specified element.
  89. *
  90. * See the class comment for an overview.
  91. *
  92. * @Given the following :entitytype exists:
  93. *
  94. * @param string $entitytype The name of the type entity to add
  95. * @param TableNode $data
  96. */
  97. public function the_following_entity_exists($entitytype, TableNode $data) {
  98. if (isset($this->movedentitytypes[$entitytype])) {
  99. $entitytype = $this->movedentitytypes[$entitytype];
  100. }
  101. list($component, $entity) = $this->parse_entity_type($entitytype);
  102. $this->get_instance_for_component($component)->generate_items($entity, $data, true);
  103. }
  104. /**
  105. * Parse a full entity type like 'users' or 'mod_forum > subscription'.
  106. *
  107. * E.g. parsing 'course' gives ['core', 'course'] and
  108. * parsing 'core_message > message' gives ['core_message', 'message'].
  109. *
  110. * @param string $entitytype the entity type
  111. * @return string[] with two elements, component and entity type.
  112. */
  113. protected function parse_entity_type(string $entitytype): array {
  114. $dividercount = substr_count($entitytype, ' > ');
  115. if ($dividercount === 0) {
  116. return ['core', $entitytype];
  117. } else if ($dividercount === 1) {
  118. list($component, $type) = explode(' > ', $entitytype);
  119. if ($component === 'core') {
  120. throw new coding_exception('Do not specify the component "core > ..." for entity types.');
  121. }
  122. return [$component, $type];
  123. } else {
  124. throw new coding_exception('The entity type must be in the form ' .
  125. '"{entity-type}" for core entities, or "{component} > {entity-type}" ' .
  126. 'for entities belonging to other components. ' .
  127. 'For example "users" or "mod_forum > subscriptions".');
  128. }
  129. }
  130. /**
  131. * Get an instance of the appropriate subclass of this class for a given component.
  132. *
  133. * @param string $component The name of the component to generate entities for.
  134. * @return behat_generator_base the subclass of this class for the requested component.
  135. */
  136. protected function get_instance_for_component(string $component): behat_generator_base {
  137. global $CFG;
  138. // Ensure the generator class is loaded.
  139. require_once($CFG->libdir . '/behat/classes/behat_generator_base.php');
  140. if ($component === 'core') {
  141. $lib = $CFG->libdir . '/behat/classes/behat_core_generator.php';
  142. } else {
  143. $dir = core_component::get_component_directory($component);
  144. $lib = $dir . '/tests/generator/behat_' . $component . '_generator.php';
  145. if (!$dir || !is_readable($lib)) {
  146. throw new coding_exception("Component {$component} does not support " .
  147. "behat generators yet. Missing {$lib}.");
  148. }
  149. }
  150. require_once($lib);
  151. // Create an instance.
  152. $componentclass = "behat_{$component}_generator";
  153. if (!class_exists($componentclass)) {
  154. throw new PendingException($component .
  155. ' does not yet support the Behat data generator mechanism. Class ' .
  156. $componentclass . ' not found in file ' . $lib . '.');
  157. }
  158. $instance = new $componentclass($component);
  159. return $instance;
  160. }
  161. }