<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Davmon</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Davmon"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Davmon"/>
	<updated>2026-06-05T02:46:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=46820</id>
		<title>Setting up xhprof on Moodle</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=46820"/>
		<updated>2014-11-14T02:26:25Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following instructions are for setting up xhprof for Moodle under a Ubuntu/Debian environment. The process should be similar for other linux enviroments, but will need some tweaking if you wish to do this under windows. Please update this document if you find any major problems.&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Linux==&lt;br /&gt;
&lt;br /&gt;
===Debian/Ubuntu package===&lt;br /&gt;
 apt-get install php5-xhprof&lt;br /&gt;
The current LTS Ubuntu package is version 0.9.4-1build1&lt;br /&gt;
&lt;br /&gt;
===Build manually===&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
mkdir ~/src/&lt;br /&gt;
cd ~/src/&lt;br /&gt;
wget http://pecl.php.net/get/xhprof-0.9.2.tgz&lt;br /&gt;
tar xvf xhprof-0.9.2.tgz&lt;br /&gt;
cd xhprof-0.9.2/extension/&lt;br /&gt;
phpize&lt;br /&gt;
./configure&lt;br /&gt;
make&lt;br /&gt;
sudo make install&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: The version downloaded via these instructions is not compatible with PHP 5.4 - instead you should download the latest version of the code from https://github.com/facebook/xhprof (before following the instructions from &#039;cd xhprof-0.9.2/extension/&#039; onwards). &lt;br /&gt;
&lt;br /&gt;
Note: It is available now, the 0.9.3 version from the pecl website. You can run wget http://pecl.php.net/get/xhprof-0.9.3.tgz, if you have PHP 5.4 version.&lt;br /&gt;
&lt;br /&gt;
Add the following to the apache version of you php.ini file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
[xhprof]&lt;br /&gt;
extension=xhprof.so&lt;br /&gt;
xhprof.output_dir=&amp;quot;/var/tmp/xhprof&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restart Apache&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
sudo service apache2 restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a file in your web root that makes a call to phpinfo(); and then view the result in your browser to make sure that xhprof is enabled in PHP. Checking the output of &#039;&#039;&#039;php -m&#039;&#039;&#039; would also work if you are sure that the command line version of PHP uses the same php.ini file as your web server.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting===&lt;br /&gt;
If you see a &#039;&#039;&#039;failed to shell execute cmd=&amp;quot; dot -Tpng&#039;&#039;&#039; error when you follow the &#039;&#039;&#039;View Full Callgraph&#039;&#039;&#039; link you may need to install graphviz (&#039;&#039;&#039;sudo apt-get install graphviz&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Windows==&lt;br /&gt;
&lt;br /&gt;
You will need to download PHP extensions compiled for your version of PHP. [http://dev.freshsite.pl/php-extensions/xhprof.html Here is one source...]&lt;br /&gt;
&lt;br /&gt;
Extract the contained dll file to the ext directory of your server. With XAMPP this is in xampp\php\ext&lt;br /&gt;
&lt;br /&gt;
Add a line to your php.ini file that matches dll filename you are using. This goes in the Dynamic Extensions section.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
extension=xhprof_0.10.3_php54_vc9.dll&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stop and restart Apache through your server control interface. If it complains, you probably don&#039;t have the correct extension for your version of PHP, or the extension entry in your php.ini file doesn&#039;t match the dll file.&lt;br /&gt;
&lt;br /&gt;
To test that the extension is installed, log in to Moodle as an administrator and navigate to Administration &amp;gt; Site administration &amp;gt; Server &amp;gt; PHP info. Search for information about the xhprof extension. It should be present and enabled.&lt;br /&gt;
&lt;br /&gt;
==Configuring Moodle to use xhprof==&lt;br /&gt;
[[Image:profilingOption.png|thumb|left|The profiling option is displayed when the php xhprof extension is installed]]&lt;br /&gt;
[[Image:profilingOutput.png|thumb|right|Tabular profiling output produced by xhprof]]&lt;br /&gt;
[[Image:callgraph.png|thumb|right|An example call graph showing slow parts of the profiled run]]&lt;br /&gt;
Once the xhprof php extension is correctly installed you will find a new &amp;quot;Profiling&amp;quot; option available under Settings &amp;gt; Site administration &amp;gt; Development&lt;br /&gt;
&lt;br /&gt;
When you load the profiling settings page you are confronted with several options. In order to get xhprof up and running with minimal fuss you mearly need to check the &amp;quot;Enable profiling&amp;quot; box and set a path that you wish to be profiled. You can simply set this to a wildcard using the asterisk symbol (&#039;&#039;&#039;*&#039;&#039;&#039;) while you are testing profiling. Afterwards you can come back and set this to a more restrictive setting once you know profiling is working. Note the paths need to be specified relative to your Moodle directory and not the web root.&lt;br /&gt;
&lt;br /&gt;
After you have enabled profiling you should load some pages within the &amp;quot;Profile these&amp;quot; filter that you set in the step above. Once you have done these go to Settings &amp;gt; Site administration &amp;gt; Development &amp;gt; Profiling runs and you should see a list of the pages you visited. Clicking on one of these and then clicking on the &amp;quot;View profiling details&amp;quot; will take you to a profiling table full of helpful stats for tracking down slow pages and functions. You can get an even more ineresting breakdown of this by then clicking on the &amp;quot;View Full Callgraph&amp;quot; link. This callgraph makes it easy to see where the slow parts of each particular run are and functions which individually may not take a long time to run but which are run thousands of times and thus resulting in a great deal of slowdown.&lt;br /&gt;
[[Image:profilingSettings.png|frame|center|Enabling profiling and setting it to run on all pages via a wildcard]]&lt;br /&gt;
[[Image:profilingRuns.png|frame|left|A profiling runs option can be seen after enabling profiling]]&lt;br /&gt;
&lt;br /&gt;
==Using XHProf==&lt;br /&gt;
&lt;br /&gt;
MDL-39443 shows the kind of thing that can be done using XHProf.&lt;br /&gt;
&lt;br /&gt;
[http://tjhunt.blogspot.co.uk/2013/05/performance-testing-moodle.html This blog post] talks about the process.&lt;br /&gt;
&lt;br /&gt;
Since Moodle 2.5.1 it&#039;s possible to export and import any profiling run. That enables some interesting uses like, comparisons along the time, between different systems and sharing or runs in other systems like the Tracker when optimization issues are being fixed.&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46587</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46587"/>
		<updated>2014-10-27T01:01:57Z</updated>

		<summary type="html">&lt;p&gt;Davmon: https://tracker.moodle.org/browse/MDL-44523&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters - indicating &#039;c&#039;reate, &#039;r&#039;ead, &#039;u&#039;pdate or &#039;d&#039;elete operation. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. In a few cases, the educational level of an event depends on the context (site, course...) and/or the role (admin, teacher...) in these cases the selected educational level should be the most usual use case of that event. The event itself has a static educational level. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the logging subsystem, and cannot be used later when logged event is displayed.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
It is important to trigger individual events for each and every action, bulk events are very strongly discouraged because existing observers would not receive important information. Changes from one to many would break backwards compatibility with observers and reporting.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=46586</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=46586"/>
		<updated>2014-10-27T00:56:29Z</updated>

		<summary type="html">&lt;p&gt;Davmon: https://tracker.moodle.org/browse/MDL-44619&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
Note that these snippets are only examples and may not work.&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I set the following fields to these values:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;User Blog&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behavior driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Verify your installation ==&lt;br /&gt;
* Test your installation by browsing your /admin/tool/behat/index.php page.&lt;br /&gt;
If you are using MAMP/WAMP/XAMPP and don&#039;t get the report working... then you need to ensure that your web servers knows where the PHP executable (commad line) is. To do that, edit the &amp;quot;envvars&amp;quot; file (usually under library/bin) and add to $PATH the path to your php executable. Then restart the apache server and try again.&lt;br /&gt;
For example, for MAMP you probably need to add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
# Adding MAMP binaries communicate where CLI is&lt;br /&gt;
PATH=&amp;quot;/Applications/MAMP/bin/php/php5.x.y/bin:$PATH&amp;quot;; export PATH &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
at the end of MAMP/Library/bin/envvars.&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_faildump_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [https://github.com/moodlehq/moodle-behat-extension Moodle behat extension] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
* This interface only works on sites where Behat is installed. If you are using the local PHP server, for example, you can access it on that site at http://localhost:8000 (log in as admin/admin).&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
** If your scenario outline consists of many steps it may be useful to add a comment with the number of steps. If the the test fails behat will tell you in which step overall and you will have to divide by the number of steps of the scenario to know in which example. &lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A field value&#039;&#039;&#039;; There are many different field types, if an argument requires a field value the expected value will depend on the field type:&lt;br /&gt;
** Text-based fields: It expects the text. This includes textareas, input type text, input type password...&lt;br /&gt;
** Checkbox: It expects 1 to check and for checked and &amp;quot;&amp;quot; to uncheck or for unchecked&lt;br /&gt;
** Select: It expects the option text or the option value. In case you interact with a multi-select you should specify the options separating them with commas. For example: &#039;&#039;&#039;option1, option2, option3&#039;&#039;&#039;&lt;br /&gt;
** Radio: The text of the radio option&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** filemanager - for searching a filemanager by it&#039;s id or label&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exist:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exist:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exist:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exist:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exist:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exist:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exist:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Roles&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses a one of the following roles as archetype: manager, coursecreator, editingteacher, teacher, student, guest, user and frontpage&lt;br /&gt;
  Given the following &amp;quot;roles&amp;quot; exist:&lt;br /&gt;
    | shortname | name          | description | archetype      |&lt;br /&gt;
    | custom1   | Custom Role 1 |             | editingteacher |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exist:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exist:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exist:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exist:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exist:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exist:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
== Browser specific fixes ==&lt;br /&gt;
&lt;br /&gt;
When running acceptance tests in conjunction with Selenium against Chrome, IE, or Safari there is a fix for the navigation bar that gets applied in order to avoid errors arising from a bug in the webdrivers for those browsers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;The issue&amp;lt;/b&amp;gt;: When an acceptance test goes to interact with an element on the page it first ensures that the element in the view-port and if not scrolls the browser to get the element into the view-port. If you are running against Chrome, IE, or Safari the browser scrolls the element only just inside the view-port. It doesn&#039;t however allow for any fixed position elements such as the navigation bar.&lt;br /&gt;
What happens: In some situations these browsers scroll up to reach a button, however not enough as the button ends up behind the navigation bar and cannot be interacted with.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Our solution&amp;lt;/b&amp;gt;: We can not change browser driver behaviour so we have integrated a work around. When running acceptance tests against one of these browsers we change the position attribute of the navigation bar from fixed to absolute. This is not ideal as it is not how the user experiences the site, however it allows us to run the full acceptance test suite against these browsers so we allowed it. A notice will be displayed when you start an acceptance test run if the browser specific fixes have been applied. See MDL-47734 / MDL-45231 for more details.&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=44157</id>
		<title>Acceptance testing/Contributing automated tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=44157"/>
		<updated>2014-03-13T10:13:22Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Automating a test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The issue MDLQA-1 contains testing tasks required to manually test many of the features and functions of Moodle.&lt;br /&gt;
&lt;br /&gt;
We are aiming to automate as many of these tests as possible using Moodle&#039;s new behat-based testing framework, so that they can be run weekly, and so that real users can focus on more exploratory testing instead. Currently there are over 400 MDLQA tests, so help in automating them is much appreciated!&lt;br /&gt;
&lt;br /&gt;
==Automating a test==&lt;br /&gt;
&lt;br /&gt;
# Choose a test from this list [[Acceptance_testing/Contributing_automated_tests#Quick_start:_Test_automating|quick tests to automate]] or from here if the previous list is empty: [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Blocker Top priority MDLQA tests to be automated].&lt;br /&gt;
# Create a new MDL issue with summary &#039;Automate MDLQA-wxyz&#039; and component &#039;Automated functional tests&#039; and any MDLQA component such as &#039;Forum&#039; which is also an MDL component.&lt;br /&gt;
# Add the &#039;&#039;&#039;mdlqa_conversion&#039;&#039;&#039; label to the new MDL issue&lt;br /&gt;
# Link to the MDLQA test by selecting &#039;Will help resolve&#039; as the link type.&lt;br /&gt;
# Follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
# Include &#039;MDLQA-wxyz&#039; and a short description of what is being automated to the commit message/s where the .feature files are added/edited.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Many thanks for helping with test automating!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: Once the &#039;Top priority MDLQA tests to be automated&#039; list is reduced to zero, choose a test from the following lists:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Critical Secondary priority MDLQA tests to be automated]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Major More secondary priority MDLQA tests to be automated]&lt;br /&gt;
&lt;br /&gt;
==Quick start: Test automating==&lt;br /&gt;
&lt;br /&gt;
To skip steps 1. to 3. above, simply choose an issue from this list: [https://tracker.moodle.org/issues/?jql=labels%20%3D%20&#039;mdlqa_conversion&#039;%20and%20status%20%3D%20&#039;open&#039; Quick start test automating issues] and then follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
&lt;br /&gt;
==Tests which cannot be automated==&lt;br /&gt;
&lt;br /&gt;
Certain tests cannot be automated, as they require integration with other systems, code base modifications or other actions outside the browser scope.&lt;br /&gt;
&lt;br /&gt;
Existing tests which have been identified as such are:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Minor MDLQA tests which are a challenge to automate]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Trivial MDLQA tests impossible to automate]&lt;br /&gt;
&lt;br /&gt;
New features and improvements which cannot have an automated test written for them should be labelled [https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required] and detailed testing instructions provided which can then be used when writing a new MDLQA test.&lt;br /&gt;
&lt;br /&gt;
==Removing automated tests from the list of manual QA tests==&lt;br /&gt;
&lt;br /&gt;
When a test is automated, it needs to be moved from MDLQA-1 to MDLQA-5249.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44149</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44149"/>
		<updated>2014-03-11T08:20:30Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
Note that these snippets are only examples and may not work.&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [https://github.com/moodlehq/moodle-behat-extension Moodle behat extension] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
** If your scenario outline consists of many steps it may be useful to add a comment with the number of steps. If the the test fails behat will tell you in which step overall and you will have to divide by the number of steps of the scenario to know in which example. &lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A field value&#039;&#039;&#039;; There are many different field types, if an argument requires a field value the expected value will depend on the field type:&lt;br /&gt;
** Text-based fields: It expects the text. This includes textareas, input type text, input type password...&lt;br /&gt;
** Checkbox: It expects 1 to check and for checked and &amp;quot;&amp;quot; to uncheck or for unchecked&lt;br /&gt;
** Select: It expects the option text or the option value. In case you interact with a multi-select you should specify the options separating them with commas. For example: &#039;&#039;&#039;option1, option2, option3&#039;&#039;&#039;&lt;br /&gt;
** Radio: The text of the radio option&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exist:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exist:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exist:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exist:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exist:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exist:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exist:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Roles&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses a one of the following roles as archetype: manager, coursecreator, editingteacher, teacher, student, guest, user and frontpage&lt;br /&gt;
  Given the following &amp;quot;roles&amp;quot; exist:&lt;br /&gt;
    | shortname | name          | description | archetype      |&lt;br /&gt;
    | custom1   | Custom Role 1 |             | editingteacher |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exist:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exist:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exist:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exist:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exist:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exist:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44127</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44127"/>
		<updated>2014-03-10T07:45:18Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Providing values to steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [https://github.com/moodlehq/moodle-behat-extension Moodle behat extension] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
** If your scenario outline consists of many steps it may be useful to add a comment with the number of steps. If the the test fails behat will tell you in which step overall and you will have to divide by the number of steps of the scenario to know in which example. &lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A field value&#039;&#039;&#039;; There are many different field types, if an argument requires a field value the expected value will depend on the field type:&lt;br /&gt;
** Text-based fields: It expects the text. This includes textareas, input type text, input type password...&lt;br /&gt;
** Checkbox: It expects 1 to check and for checked and &amp;quot;&amp;quot; to uncheck or for unchecked&lt;br /&gt;
** Select: It expects the option text or the option value. In case you interact with a multi-select you should specify the options separating them with commas. For example: &#039;&#039;&#039;option1, option2, option3&#039;&#039;&#039;&lt;br /&gt;
** Radio: The text of the radio option&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exist:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exist:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exist:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exist:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exist:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exist:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exist:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Roles&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses a one of the following roles as archetype: manager, coursecreator, editingteacher, teacher, student, guest, user and frontpage&lt;br /&gt;
  Given the following &amp;quot;roles&amp;quot; exist:&lt;br /&gt;
    | shortname | name          | description | archetype      |&lt;br /&gt;
    | custom1   | Custom Role 1 |             | editingteacher |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exist:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exist:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exist:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exist:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exist:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exist:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44126</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44126"/>
		<updated>2014-03-10T07:38:18Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Available elements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [https://github.com/moodlehq/moodle-behat-extension Moodle behat extension] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
** If your scenario outline consists of many steps it may be useful to add a comment with the number of steps. If the the test fails behat will tell you in which step overall and you will have to divide by the number of steps of the scenario to know in which example. &lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exist:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exist:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exist:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exist:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exist:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exist:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exist:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Roles&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses a one of the following roles as archetype: manager, coursecreator, editingteacher, teacher, student, guest, user and frontpage&lt;br /&gt;
  Given the following &amp;quot;roles&amp;quot; exist:&lt;br /&gt;
    | shortname | name          | description | archetype      |&lt;br /&gt;
    | custom1   | Custom Role 1 |             | editingteacher |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exist:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exist:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exist:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exist:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exist:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exist:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44097</id>
		<title>Acceptance testing/Contributing to Moodle behat extension</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44097"/>
		<updated>2014-03-07T07:33:28Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project according to Moodle HQ integration workflow.&lt;br /&gt;
&lt;br /&gt;
We use https://github.com/moodlehq/moodle-behat-extension as vendor/moodlehq/behat-extension official repository, we must not redo git history nor update where git tags points to, so we will only members of integration team will push to https://github.com/moodlehq/moodle-behat-extension once the code has been reviewed and sent to integration.&lt;br /&gt;
&lt;br /&gt;
Full integration workflow when including changes in https://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
* Developer forks git://github.com/moodlehq/moodle-behat-extension and creates a MDL-XXXXX in his/her fork to work on a patch&lt;br /&gt;
* Developer pushes changes to his/her repository&lt;br /&gt;
* Developer updates moodle&#039;s composer.json changing the repository URL to his/her own repository URL and moodlehq/behat-extension version pointing to MDL-XXXXX branch (read https://getcomposer.org/doc/articles/aliases.md#branch-alias for more info)&lt;br /&gt;
* Developer sends the issue to peer review&lt;br /&gt;
** A member of the integration team will review the changes in moodle-behat-extension&lt;br /&gt;
** Here there may be multiple iterations moving from development in progress to peer reviewing&lt;br /&gt;
* Once the issue is ready to be sent for integration the developer amends the commit changing composer.json to his/her own repository to make it point again to the official moodlehq repository, and changes moodlehq/behat-extension version for the next https://github.com/moodlehq/moodle-behat-extension tag&lt;br /&gt;
** The tag will depend on the major Moodle branch the developer is targeting, tags follows v1.XY.N format, where XY is the major moodle version (the next one if master) and N is an incremental integer&lt;br /&gt;
* A member of the integration team will create the appropriate tag in git://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
** In case there is more than one issue integrated the same week only one tag will be created&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Extend moodle-behat-extension to fit your needs ==&lt;br /&gt;
The moodle-behat-extension version that Moodle uses to run behat is specified in composer.json, to use your own repository and/or another tag/branch you should modify $CFG-&amp;gt;dirroot/composer.json.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44096</id>
		<title>Acceptance testing/Contributing to Moodle behat extension</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44096"/>
		<updated>2014-03-07T07:03:01Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project according to Moodle HQ integration workflow.&lt;br /&gt;
&lt;br /&gt;
We use https://github.com/moodlehq/moodle-behat-extension as vendor/moodlehq/behat-extension official repository, we must not redo git history nor update where git tags points to, so we will only members of integration team will push to https://github.com/moodlehq/moodle-behat-extension once the code has been reviewed and sent to integration.&lt;br /&gt;
&lt;br /&gt;
Full integration workflow when including changes in https://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
* Developer forks git://github.com/moodlehq/moodle-behat-extension and creates a MDL-XXXXX in his/her fork to work on a patch&lt;br /&gt;
* Developer pushes changes to his/her repository&lt;br /&gt;
* Developer updates moodle&#039;s composer.json changing the repository URL to his/her own repository URL and moodlehq/behat-extension version pointing to MDL-XXXXX branch (read https://getcomposer.org/doc/articles/aliases.md#branch-alias for more info)&lt;br /&gt;
* Developer sends the issue to peer review&lt;br /&gt;
** A member of the integration team will review the changes in moodle-behat-extension&lt;br /&gt;
** Here there may be multiple iterations moving from development in progress to peer reviewing&lt;br /&gt;
* Once the issue is ready to be sent for integration the developer amends the commit changing composer.json to his/her own repository, and changes it for the next https://github.com/moodlehq/moodle-behat-extension tag&lt;br /&gt;
** The tag will depend on the major Moodle branch the developer is targeting, tags follows v1.XY.N format, where XY is the major moodle version (the next one if master) and N is an incremental integer&lt;br /&gt;
* A member of the integration team will create the appropriate tag in git://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
** In case there is more than one issue integrated the same week only one tag will be created&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Extend moodle-behat-extension to fit your needs ==&lt;br /&gt;
The moodle-behat-extension version that Moodle uses to run behat is specified in composer.json, to use your own repository and/or another tag/branch you should modify $CFG-&amp;gt;dirroot/composer.json.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44083</id>
		<title>Acceptance testing/Contributing to Moodle behat extension</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44083"/>
		<updated>2014-03-06T07:40:46Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project according to Moodle HQ integration workflow.&lt;br /&gt;
&lt;br /&gt;
We use https://github.com/moodlehq/moodle-behat-extension as vendor/moodlehq/behat-extension official repository, we must not redo git history nor update where git tags points to, so we will only members of integration team will push to https://github.com/moodlehq/moodle-behat-extension once the code has been reviewed and sent to integration.&lt;br /&gt;
&lt;br /&gt;
Full integration workflow when including changes in https://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
* Developer forks git://github.com/moodlehq/moodle-behat-extension and creates a MDL-XXXXX in his/her fork to work on a patch&lt;br /&gt;
* Developer pushes changes to his/her repository&lt;br /&gt;
* Developer updates moodle&#039;s composer.json changing the repository URL to his/her own repository URL and moodlehq/behat-extension version pointing to MDL-XXXXX branch (read https://getcomposer.org/doc/articles/aliases.md#branch-alias for more info)&lt;br /&gt;
* Developer sends the issue to peer review&lt;br /&gt;
** A member of the integration team will review the changes in moodle-behat-extension&lt;br /&gt;
** Here there may be multiple iterations moving from development in progress to peer reviewing&lt;br /&gt;
* Once the issue is ready to be sent for integration the developer amends the commit changing composer.json to his/her own repository, and changes it for the next https://github.com/moodlehq/moodle-behat-extension tag&lt;br /&gt;
** The tag will depend on the major Moodle branch the developer is targeting, tags follows v1.XY.N format, where XY is the major moodle version (the next one if master) and N is an incremental integer&lt;br /&gt;
* A member of the integration team will create the appropriate tag in git://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
** In case there is more than one issue integrated the same week only one tag will be created&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Extend moodle-behat-extension to fit your needs ==&lt;br /&gt;
The moodle-behat-extension version that Moodle uses to run behat is specified in composer.json, to use your own repository and/or another tag/branch you should modify $CFG-&amp;gt;dirroot/composer.json.&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44080</id>
		<title>Acceptance testing/Contributing to Moodle behat extension</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44080"/>
		<updated>2014-03-06T07:28:40Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project according to Moodle HQ integration workflow.&lt;br /&gt;
&lt;br /&gt;
We use https://github.com/moodlehq/moodle-behat-extension as vendor/moodlehq/behat-extension official repository, we must not redo git history nor update where git tags points to, so we will only members of integration team will push to https://github.com/moodlehq/moodle-behat-extension once the code has been reviewed and sent to integration.&lt;br /&gt;
&lt;br /&gt;
Full integration workflow when including changes in https://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
* Developer forks git://github.com/moodlehq/moodle-behat-extension and creates a MDL-XXXXX in his/her fork to work on a patch&lt;br /&gt;
* Developer pushes changes to his/her repository&lt;br /&gt;
* Developer updates moodle&#039;s composer.json changing the repository URL to his/her own repository URL and moodlehq/behat-extension version pointing to MDL-XXXXX branch (read https://getcomposer.org/doc/articles/aliases.md#branch-alias for more info)&lt;br /&gt;
* Developer sends the issue to peer review&lt;br /&gt;
** Here there may be multiple iterations moving from development in progress to peer reviewing&lt;br /&gt;
* Once the issue is ready to be sent for integration the developer amends the commit changing composer.json to his/her own repository, and changes it for the next https://github.com/moodlehq/moodle-behat-extension tag&lt;br /&gt;
** The tag will depend on the major Moodle branch the developer is targeting, tags follows v1.XY.N format, where XY is the major moodle version (the next one if master) and N is an incremental integer&lt;br /&gt;
* Integration team will create the appropriate tag in git://github.com/moodlehq/moodle-behat-extension&lt;br /&gt;
** In case there is more than one issue integrated the same week only one tag will be created&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Extend moodle-behat-extension to fit your needs ==&lt;br /&gt;
The moodle-behat-extension version that Moodle uses to run behat is specified in composer.json, to use your own repository and/or another tag/branch you should modify $CFG-&amp;gt;dirroot/composer.json.&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44075</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44075"/>
		<updated>2014-03-06T05:29:33Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Contributing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [https://github.com/moodlehq/moodle-behat-extension Moodle behat extension] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44074</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44074"/>
		<updated>2014-03-06T05:28:11Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
You can contribute the effort to automatically test all of Moodle&#039;s functionalities, please follow the [[contributor guide|https://docs.moodle.org/dev/Acceptance_testing/Contributing_automated_tests]]. Here you can find information about [[Acceptance_testing#Writing_features|how to write new features]] and [[Acceptance_testing#Adding_steps_definitions|how to write new step definitions]] if your changes requires a base change in the [[https://github.com/moodlehq/moodle-behat-extension|Moodle behat extension]] you can find here how to do it following the integration workflow: https://docs.moodle.org/dev/Acceptance_testing/Contributing_to_Moodle_behat_extension.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44073</id>
		<title>Acceptance testing/Contributing to Moodle behat extension</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_to_Moodle_behat_extension&amp;diff=44073"/>
		<updated>2014-03-06T05:18:15Z</updated>

		<summary type="html">&lt;p&gt;Davmon: Created page with &amp;quot;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document explains how to contribute to https://github.com/moodlehq/moodle-behat-extension project.&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44047</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=44047"/>
		<updated>2014-03-04T05:34:56Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* See also */ Removing link to MDL-37046 as it is outdated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* (See http://www.installationpage.com/selenium/how-to-run-selenium-headless-firefox-in-ubuntu/ for running &#039;headless&#039; Firefox and xvfm in a server environment)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43741</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43741"/>
		<updated>2014-02-10T09:12:59Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using features not supported by all browsers and also limitations that some browsers have; refer to the following table to know which browsers can run which tags:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|Bug in phantomjs (@_bug_phantomjs)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&amp;amp;&amp;amp;~@_alert&amp;amp;&amp;amp;~@_bug_phantomjs&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alert&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43716</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43716"/>
		<updated>2014-02-04T08:08:23Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Compatibility */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using features not supported by all browsers and also limitations that some browsers have; refer to the following table to know which browsers can run which tags:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|Bug in phantomjs (@_bug_phantomjs)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&amp;amp;&amp;amp;~@_bug_phantomjs&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alert&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43715</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43715"/>
		<updated>2014-02-04T08:06:28Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Compatibility */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using features not supported by all browsers and also limitations that some browsers have; refer to the following table to know which browsers can run which tags:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|Bug in phantomjs (@_bug_phantomjs)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&amp;amp;&amp;amp;~@_bug_phantomjs&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alert&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43686</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43686"/>
		<updated>2014-01-31T09:20:18Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Providing values to steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s English name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43685</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43685"/>
		<updated>2014-01-31T04:57:23Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using features not supported by all browsers and also limitations that some browsers have; refer to the following table to know which browsers can run which tags:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|Bug in phantomjs (@_bug_phantomjs)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&amp;amp;&amp;amp;~@_bug_phantomjs&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alert&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43658</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43658"/>
		<updated>2014-01-28T07:07:53Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Advanced usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Save screenshots of failures&#039;&#039;&#039;. You can use $CFG-&amp;gt;behat_screenshots_path to specify a directory where behat will generate a screenshot with the browser state each time a scenario fails. This is useful to detect where the problem was and work on a solution.&lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43657</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43657"/>
		<updated>2014-01-28T07:02:53Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Moodle configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alert&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_file_upload&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43656</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43656"/>
		<updated>2014-01-28T07:00:23Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_file_upload&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43655</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43655"/>
		<updated>2014-01-28T06:57:44Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Writing features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag according to https://docs.moodle.org/dev/Acceptance_testing#Tests_filters&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43654</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43654"/>
		<updated>2014-01-28T06:56:31Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Tests filters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_file_upload&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_alert&#039;&#039;&#039;: All the tests that involves Javascript dialogs (alerts, confirms...) are using a feature that is OS-dependant and out of the browser scope, so they should be tag appropriately as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_window&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; step should be tagged as not all browsers manage them properly.&lt;br /&gt;
* &#039;&#039;&#039;@_switch_iframe&#039;&#039;&#039;: All the tests that are using the &#039;&#039;&#039;I switch to &amp;quot;NAME&amp;quot; window&#039;&#039;&#039; steps should be tagged as it is an advanced feature and some browsers may have problems dealing with them&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43653</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43653"/>
		<updated>2014-01-28T06:50:34Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Compatibility */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_file_upload)&lt;br /&gt;
|Browser dialogs (@_alert)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alerts&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43652</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43652"/>
		<updated>2014-01-28T06:38:08Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_only_local&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43651</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43651"/>
		<updated>2014-01-28T06:37:36Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and automatically test them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate user interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describe Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;). Each feature file is composed of many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed of steps (for example  &#039;&#039;I press &amp;quot;Post to forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into a PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
These features are executed nightly on the HQ servers using all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and to test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** (Moodle 2.7 onwards) Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. If you use the built-in PHP server use &amp;quot;http://localhost:8000&amp;quot; or the value you set when you started it.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_only_local&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== How can you tell if Selenium is running? ===&lt;br /&gt;
&lt;br /&gt;
Try going to http://localhost:4444/selenium-server/. If Selenium is not running, nothing will happen. You will get a time-out. If selenium is running, you will get a 404 error page saying powered by Jetty at the bottom.&lt;br /&gt;
&lt;br /&gt;
=== How can I stop Selenium? ===&lt;br /&gt;
&lt;br /&gt;
Go to the URL http://localhost:4444/selenium-server/driver/?cmd=shutDownSeleniumServer. I think when it works it outputs &amp;quot;OKOK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Behat tells me that lots of steps are undefined ===&lt;br /&gt;
&lt;br /&gt;
You probably forgot the --config option in the behat command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also == &lt;br /&gt;
&lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43560</id>
		<title>Acceptance testing/Contributing automated tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43560"/>
		<updated>2014-01-16T11:05:11Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Quick start: Test automating */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The issue MDLQA-1 contains testing tasks required to manually test many of the features and functions of Moodle.&lt;br /&gt;
&lt;br /&gt;
We are aiming to automate as many of these tests as possible using Moodle&#039;s new behat-based testing framework, so that they can be run weekly, and so that real users can focus on more exploratory testing instead. Currently there are over 400 MDLQA tests, so help in automating them is much appreciated!&lt;br /&gt;
&lt;br /&gt;
==Automating a test==&lt;br /&gt;
&lt;br /&gt;
# Choose a test from this list: [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Blocker Top priority MDLQA tests to be automated].&lt;br /&gt;
# Create a new MDL issue with summary &#039;Automate MDLQA-wxyz&#039; and component &#039;Automated functional tests&#039; and any MDLQA component such as &#039;Forum&#039; which is also an MDL component.&lt;br /&gt;
# Add the &#039;&#039;&#039;mdlqa_conversion&#039;&#039;&#039; label to the new MDL issue&lt;br /&gt;
# Link to the MDLQA test by selecting &#039;Will help resolve&#039; as the link type.&lt;br /&gt;
# Follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
# Include &#039;MDLQA-wxyz&#039; and a short description of what is being automated to the commit message/s where the .feature files are added/edited.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Many thanks for helping with test automating!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: Once the &#039;Top priority MDLQA tests to be automated&#039; list is reduced to zero, choose a test from the following lists:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Critical Secondary priority MDLQA tests to be automated]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Major More secondary priority MDLQA tests to be automated]&lt;br /&gt;
&lt;br /&gt;
==Quick start: Test automating==&lt;br /&gt;
&lt;br /&gt;
To skip steps 1. to 3. above, simply choose an issue from this list: [https://tracker.moodle.org/issues/?jql=labels%20%3D%20&#039;mdlqa_conversion&#039;%20and%20status%20%3D%20&#039;open&#039; Quick start test automating issues] and then follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
&lt;br /&gt;
==Tests which cannot be automated==&lt;br /&gt;
&lt;br /&gt;
Certain tests cannot be automated, as they require integration with other systems, code base modifications or other actions outside the browser scope.&lt;br /&gt;
&lt;br /&gt;
Existing tests which have been identified as such are:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Minor MDLQA tests which are a challenge to automate]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Trivial MDLQA tests impossible to automate]&lt;br /&gt;
&lt;br /&gt;
New features and improvements which cannot have an automated test written for them should be labelled [https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required] and detailed testing instructions provided which can then be used when writing a new MDLQA test.&lt;br /&gt;
&lt;br /&gt;
==Removing automated tests from the list of manual QA tests==&lt;br /&gt;
&lt;br /&gt;
When a test is automated, it needs to be moved from MDLQA-1 to MDLQA-5249.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43559</id>
		<title>Acceptance testing/Contributing automated tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43559"/>
		<updated>2014-01-16T11:00:36Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Automating a test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The issue MDLQA-1 contains testing tasks required to manually test many of the features and functions of Moodle.&lt;br /&gt;
&lt;br /&gt;
We are aiming to automate as many of these tests as possible using Moodle&#039;s new behat-based testing framework, so that they can be run weekly, and so that real users can focus on more exploratory testing instead. Currently there are over 400 MDLQA tests, so help in automating them is much appreciated!&lt;br /&gt;
&lt;br /&gt;
==Automating a test==&lt;br /&gt;
&lt;br /&gt;
# Choose a test from this list: [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Blocker Top priority MDLQA tests to be automated].&lt;br /&gt;
# Create a new MDL issue with summary &#039;Automate MDLQA-wxyz&#039; and component &#039;Automated functional tests&#039; and any MDLQA component such as &#039;Forum&#039; which is also an MDL component.&lt;br /&gt;
# Add the &#039;&#039;&#039;mdlqa_conversion&#039;&#039;&#039; label to the new MDL issue&lt;br /&gt;
# Link to the MDLQA test by selecting &#039;Will help resolve&#039; as the link type.&lt;br /&gt;
# Follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
# Include &#039;MDLQA-wxyz&#039; and a short description of what is being automated to the commit message/s where the .feature files are added/edited.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Many thanks for helping with test automating!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: Once the &#039;Top priority MDLQA tests to be automated&#039; list is reduced to zero, choose a test from the following lists:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Critical Secondary priority MDLQA tests to be automated]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Major More secondary priority MDLQA tests to be automated]&lt;br /&gt;
&lt;br /&gt;
==Quick start: Test automating==&lt;br /&gt;
&lt;br /&gt;
To skip steps 1. to 3. above, simply choose an issue from this list: [https://tracker.moodle.org/issues/?jql=Component%20%3D%20%22Automated%20functional%20tests%22%20AND%20status%20%3D%20Open%20and%20created%20%3E%3D%20%222013-10-11%22%20and%20summary%20%7E%20%22Automate%22 Quick start test automating issues] and then follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
&lt;br /&gt;
==Tests which cannot be automated==&lt;br /&gt;
&lt;br /&gt;
Certain tests cannot be automated, as they require integration with other systems, code base modifications or other actions outside the browser scope.&lt;br /&gt;
&lt;br /&gt;
Existing tests which have been identified as such are:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Minor MDLQA tests which are a challenge to automate]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Trivial MDLQA tests impossible to automate]&lt;br /&gt;
&lt;br /&gt;
New features and improvements which cannot have an automated test written for them should be labelled [https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required] and detailed testing instructions provided which can then be used when writing a new MDLQA test.&lt;br /&gt;
&lt;br /&gt;
==Removing automated tests from the list of manual QA tests==&lt;br /&gt;
&lt;br /&gt;
When a test is automated, it needs to be moved from MDLQA-1 to MDLQA-5249.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43558</id>
		<title>Acceptance testing/Contributing automated tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43558"/>
		<updated>2014-01-16T10:59:46Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Automating a test */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The issue MDLQA-1 contains testing tasks required to manually test many of the features and functions of Moodle.&lt;br /&gt;
&lt;br /&gt;
We are aiming to automate as many of these tests as possible using Moodle&#039;s new behat-based testing framework, so that they can be run weekly, and so that real users can focus on more exploratory testing instead. Currently there are over 400 MDLQA tests, so help in automating them is much appreciated!&lt;br /&gt;
&lt;br /&gt;
==Automating a test==&lt;br /&gt;
&lt;br /&gt;
# Choose a test from this list: [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Blocker Top priority MDLQA tests to be automated].&lt;br /&gt;
# Create a new MDL issue with summary &#039;Automate MDLQA-wxyz&#039; and component &#039;Automated functional tests&#039; and any MDLQA component such as &#039;Forum&#039; which is also an MDL component.&lt;br /&gt;
# Add the &#039;&#039;&#039;mdlqa_conversion&#039;&#039;&#039; label&lt;br /&gt;
# Link to the MDLQA test by selecting &#039;Will help resolve&#039; as the link type.&lt;br /&gt;
# Follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
# Include &#039;MDLQA-wxyz&#039; and a short description of what is being automated to the commit message/s where the .feature files are added/edited.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Many thanks for helping with test automating!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: Once the &#039;Top priority MDLQA tests to be automated&#039; list is reduced to zero, choose a test from the following lists:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Critical Secondary priority MDLQA tests to be automated]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Major More secondary priority MDLQA tests to be automated]&lt;br /&gt;
&lt;br /&gt;
==Quick start: Test automating==&lt;br /&gt;
&lt;br /&gt;
To skip steps 1. to 3. above, simply choose an issue from this list: [https://tracker.moodle.org/issues/?jql=Component%20%3D%20%22Automated%20functional%20tests%22%20AND%20status%20%3D%20Open%20and%20created%20%3E%3D%20%222013-10-11%22%20and%20summary%20%7E%20%22Automate%22 Quick start test automating issues] and then follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
&lt;br /&gt;
==Tests which cannot be automated==&lt;br /&gt;
&lt;br /&gt;
Certain tests cannot be automated, as they require integration with other systems, code base modifications or other actions outside the browser scope.&lt;br /&gt;
&lt;br /&gt;
Existing tests which have been identified as such are:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Minor MDLQA tests which are a challenge to automate]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Trivial MDLQA tests impossible to automate]&lt;br /&gt;
&lt;br /&gt;
New features and improvements which cannot have an automated test written for them should be labelled [https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required] and detailed testing instructions provided which can then be used when writing a new MDLQA test.&lt;br /&gt;
&lt;br /&gt;
==Removing automated tests from the list of manual QA tests==&lt;br /&gt;
&lt;br /&gt;
When a test is automated, it needs to be moved from MDLQA-1 to MDLQA-5249.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Tracker_issue_labels&amp;diff=43557</id>
		<title>Tracker issue labels</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Tracker_issue_labels&amp;diff=43557"/>
		<updated>2014-01-16T10:57:23Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Labels */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Moodle Tracker allows issues to be &amp;quot;labelled&amp;quot; with tags.  This page lists common labels that we use to flag aspects about our MDL issues (bugs and feature requests about Moodle itself).&lt;br /&gt;
&lt;br /&gt;
Note: Labels can only be added by a user with permission to edit an issue i.e. the issue reporter, members of the developers group, or members of certain other groups.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
&lt;br /&gt;
;triaged: Generally this is only set by the [[Bug triage|triaging team]].  It indicated that the issue has been confirmed, with basic fields like &amp;quot;Severity&amp;quot; checked and is now ready for a developer to look at.&lt;br /&gt;
;mdlqa:  Used to flag that an issue is a direct result of a Moodle QA test, conducted just before major releases.  The bug should also be LINKED to the original MDLQA test, so that developers/integrators can reset the original MDLQA test (for re-testing) when the MDL issue is fixed.&lt;br /&gt;
;mdlqa_conversion: Used to flag MDL issues that are converting MDLQA issues to behat features&lt;br /&gt;
;[https://tracker.moodle.org/issues/?jql=labels%20%3D%20unit_test_required unit_test_required]: Used to flag issues that should have their own unit tests.&lt;br /&gt;
;[https://tracker.moodle.org/issues/?jql=labels%20%3D%20acceptance_test_required acceptance_test_required]: Used to flag issues that should be regularly tested using the behat framework (https://docs.moodle.org/dev/Acceptance_testing). Before a major release these issues will be reviewed and new feature files will be added.&lt;br /&gt;
;[https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required]: Used to flag issues that should be regularly tested in future MDLQA tests.  QA people will look for issues with this label periodically when creating new tests.&lt;br /&gt;
;[https://tracker.moodle.org/issues/?jql=labels%20%3D%20docs_required docs_required]:  Used to flag issues that have created a need for documentation work, such as new pages, changes, or even being added to upcoming release notes.  Docs people will look for these issues periodically when working on documentation, removing the label once documentation has been written.&lt;br /&gt;
;dev_docs_required ([https://tracker.moodle.org/issues/?jql=labels%20in%20(dev_docs_required) all] | [https://tracker.moodle.org/issues/?jql=labels%20in%20(dev_docs_required)%20AND%20assignee%20%3D%20currentUser() yours]):  Used to flag issues that need to be noted in the dev docs. The responsibility of creating/updating Dev docs falls to the developer assigned to each relevant issue. When the issue is resolved, documentation should be created/updated, an appropriate URL should be added to the &#039;&#039;Documentation link&#039;&#039; field of the issue and the &#039;&#039;dev_docs_required&#039;&#039; label should be removed from the issue.&lt;br /&gt;
;integration_held: Used to flag issues already sent to integration that, for any cause, have been postponed to next cycles. Used only by integrators when there is some dependency or time-period causing one issue not being immediately integrable. Must be cleaned when the held is over.&lt;br /&gt;
;security_held: Used to flag security issues that have been reviewed by integrators already but held from integration repository. These issues must be cleared during point releases.&lt;br /&gt;
;partner: Moodle Partners apply this label to flag issues that are important to their clients.  The Moodle HQ dev team takes this label into consideration when setting roadmap and bug fixing priorities.&lt;br /&gt;
;patch: This label indicates that a solution (patch) has been attached to the issue. However, if you can, it may be better to submit the issue for peer review, rather than using this label. This is useful to component leads and Moodle HQ when deciding what to work on next.&lt;br /&gt;
;[https://tracker.moodle.org/issues/?jql=labels%20%3D%20ui_change ui_change]: Used to identify issues that affect the interface presented to users. This label will usually be added together with the &#039;&#039;docs_required label&#039;&#039;, but the &#039;&#039;ui_change&#039;&#039; will remain permanently with the issue, while the &#039;&#039;docs_required&#039;&#039; label is removed after docs are created. This label is searched for during the preparation of release notes.&lt;br /&gt;
;api_change: Used to identify API changes. This label will usually be added together with the &#039;&#039;dev_docs_required label&#039;&#039;, but the &#039;&#039;api_change&#039;&#039; will remain permanently with the issue, while the &#039;&#039;dev_docs_required&#039;&#039; label is removed after docs are created. This label is searched for during the preparation of release notes.&lt;br /&gt;
;lost_functionality: Used to identify issues describing functionality which was available in an earlier version but which is no longer available in the latest version.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
*[[Tracker]]&lt;br /&gt;
* [[Bug triage]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tracker]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43556</id>
		<title>Acceptance testing/Contributing automated tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Contributing_automated_tests&amp;diff=43556"/>
		<updated>2014-01-16T10:22:57Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The issue MDLQA-1 contains testing tasks required to manually test many of the features and functions of Moodle.&lt;br /&gt;
&lt;br /&gt;
We are aiming to automate as many of these tests as possible using Moodle&#039;s new behat-based testing framework, so that they can be run weekly, and so that real users can focus on more exploratory testing instead. Currently there are over 400 MDLQA tests, so help in automating them is much appreciated!&lt;br /&gt;
&lt;br /&gt;
==Automating a test==&lt;br /&gt;
&lt;br /&gt;
# Choose a test from this list: [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Blocker Top priority MDLQA tests to be automated].&lt;br /&gt;
# Create a new MDL issue with summary &#039;Automate MDLQA-wxyz&#039; and component &#039;Automated functional tests&#039; and any MDLQA component such as &#039;Forum&#039; which is also an MDL component.&lt;br /&gt;
# Link to the MDLQA test by selecting &#039;Will help resolve&#039; as the link type.&lt;br /&gt;
# Follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
# Include &#039;MDLQA-wxyz&#039; and a short description of what is being automated to the commit message/s where the .feature files are added/edited.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Many thanks for helping with test automating!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: Once the &#039;Top priority MDLQA tests to be automated&#039; list is reduced to zero, choose a test from the following lists:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Critical Secondary priority MDLQA tests to be automated]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Major More secondary priority MDLQA tests to be automated]&lt;br /&gt;
&lt;br /&gt;
==Quick start: Test automating==&lt;br /&gt;
&lt;br /&gt;
To skip steps 1. to 3. above, simply choose an issue from this list: [https://tracker.moodle.org/issues/?jql=Component%20%3D%20%22Automated%20functional%20tests%22%20AND%20status%20%3D%20Open%20and%20created%20%3E%3D%20%222013-10-11%22%20and%20summary%20%7E%20%22Automate%22 Quick start test automating issues] and then follow the instructions provided in the section &#039;Writing features&#039; in the [[Acceptance testing#Writing_features|Acceptance testing guide]].&lt;br /&gt;
&lt;br /&gt;
==Tests which cannot be automated==&lt;br /&gt;
&lt;br /&gt;
Certain tests cannot be automated, as they require integration with other systems, code base modifications or other actions outside the browser scope.&lt;br /&gt;
&lt;br /&gt;
Existing tests which have been identified as such are:&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Minor MDLQA tests which are a challenge to automate]&lt;br /&gt;
* [https://tracker.moodle.org/issues/?jql=parent%20%3D%20%4DDLQA-1%20and%20priority%20%3D%20Trivial MDLQA tests impossible to automate]&lt;br /&gt;
&lt;br /&gt;
New features and improvements which cannot have an automated test written for them should be labelled [https://tracker.moodle.org/issues/?jql=labels%20%3D%20qa_test_required qa_test_required] and detailed testing instructions provided which can then be used when writing a new MDLQA test.&lt;br /&gt;
&lt;br /&gt;
==Removing automated tests from the list of manual QA tests==&lt;br /&gt;
&lt;br /&gt;
When a test is automated, it needs to be moved from MDLQA-1 to MDLQA-5249.&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43555</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43555"/>
		<updated>2014-01-16T10:22:28Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_only_local)&lt;br /&gt;
|Browser dialogs (@_alerts)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alerts&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;br /&gt;
[[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43554</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43554"/>
		<updated>2014-01-16T10:22:03Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_only_local)&lt;br /&gt;
|Browser dialogs (@_alerts)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alerts&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Category:Behat&amp;diff=43553</id>
		<title>Category:Behat</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Category:Behat&amp;diff=43553"/>
		<updated>2014-01-16T10:21:01Z</updated>

		<summary type="html">&lt;p&gt;Davmon: Created page with &amp;quot;Pages with behat information&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pages with behat information&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43511</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43511"/>
		<updated>2014-01-09T10:48:48Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/release-1.8.html&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_only_local)&lt;br /&gt;
|Browser dialogs (@_alerts)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alerts&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43510</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43510"/>
		<updated>2014-01-09T10:46:13Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/release-1.8.html&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_upload)&lt;br /&gt;
|Browser dialogs (@_alerts)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Moodle configuration ==&lt;br /&gt;
You need to tell behat what browser do you want to run and where it is. The best option could be to use behat profiles (http://docs.behat.org/guides/7.config.html#profiles).&lt;br /&gt;
&lt;br /&gt;
The profiles can be specified in config.php through $CFG-&amp;gt;behat_config like all other behat.yml specific configurations. &lt;br /&gt;
&lt;br /&gt;
This is an example of $CFG-&amp;gt;behat_config to run behat in multiple environments (Windows, Linux and OSx) to cover all the supported browsers. Note that we are using multiple servers so we skip the tests that involves files uploads when using a remote server.&lt;br /&gt;
&lt;br /&gt;
    // Note that in this case $linuxip is the local server.&lt;br /&gt;
    // Set servers IPs.&lt;br /&gt;
    $linuxip = &#039;127.0.0.1&#039;;&lt;br /&gt;
    $windowsip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $osxip = &#039;192.168.xxx.xxx&#039;;&lt;br /&gt;
    $CFG-&amp;gt;behat_config = array(&lt;br /&gt;
        &#039;phantomjs-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
           &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
               &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                   &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                       &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                   )&lt;br /&gt;
               )&lt;br /&gt;
           )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;chrome-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-linux&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $linuxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;firefox-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;firefox&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;safari-osx&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_alerts&amp;amp;&amp;amp;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;safari&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $osxip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;ie-win&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;filters&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;tags&#039; =&amp;gt; &#039;~@_switch_window&amp;amp;&amp;amp;~@_only_local&#039;&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                        &#039;browser&#039; =&amp;gt; &#039;iexplore&#039;,&lt;br /&gt;
                        &#039;wd_host&#039; =&amp;gt; &#039;http://&#039; . $windowsip . &#039;:4444/wd/hub&#039;&lt;br /&gt;
                    )&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    );&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43509</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43509"/>
		<updated>2014-01-09T10:38:43Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page complements [[Acceptance testing]] providing info about how to run the acceptance tests suite in different browsers.&lt;br /&gt;
&lt;br /&gt;
== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/release-1.8.html&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== PhantomJS ===&lt;br /&gt;
&lt;br /&gt;
PhantomJS is different as it is a headless browser as it is quite faster than other drivers, it doesn&#039;t need a GUI to run and can execute JS, it doesn&#039;t even need to be used through Selenium (you can do it though) and you can do it&lt;br /&gt;
&lt;br /&gt;
* Download PhantomJS: http://phantomjs.org/download.html&lt;br /&gt;
* /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Note that 4444 is the default port used by Selenium so you must specify another one if you want to run them together and specify the port in $CFG-&amp;gt;behat_config.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Selenium in Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
  # PhantomJS&lt;br /&gt;
  /path/to/your/phantomjs/bin/phantomjs --webdriver=4444&lt;br /&gt;
&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_upload)&lt;br /&gt;
|Browser dialogs (@_alerts)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;No&amp;lt;/span&amp;gt;&lt;br /&gt;
|&amp;lt;span style=&amp;quot;color:#0f0&amp;quot;&amp;gt;Yes&amp;lt;/span&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43508</id>
		<title>Acceptance testing/Browsers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing/Browsers&amp;diff=43508"/>
		<updated>2014-01-09T10:27:08Z</updated>

		<summary type="html">&lt;p&gt;Davmon: Created page with &amp;quot;== Drivers ==  There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:  * Firefox - https://code.google.com/...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Drivers ==&lt;br /&gt;
&lt;br /&gt;
There are Selenium drivers (http://docs.seleniumhq.org/projects/webdriver/) to run acceptance tests in different browsers:&lt;br /&gt;
&lt;br /&gt;
* Firefox - https://code.google.com/p/selenium/wiki/FirefoxDriver&lt;br /&gt;
* Chrome - https://code.google.com/p/selenium/wiki/ChromeDriver&lt;br /&gt;
* Safari - https://code.google.com/p/selenium/wiki/SafariDriver&lt;br /&gt;
* Internet Explorer - https://code.google.com/p/selenium/wiki/InternetExplorerDriver&lt;br /&gt;
* PhantomJS (Webkit) - http://phantomjs.org/release-1.8.html&lt;br /&gt;
* Android - https://code.google.com/p/selenium/wiki/AndroidDriver&lt;br /&gt;
* IPhone - https://code.google.com/p/selenium/wiki/IPhoneDriver&lt;br /&gt;
&lt;br /&gt;
Each driver should be downloaded and Selenium .jar should be started specifying the path to the driver; depending on the driver there could be other requirements. &lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
  # Linux (firefox by default + chrome)&lt;br /&gt;
  java -jar /opt/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/opt/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # OSx (firefox &amp;amp; safari by default + chrome)&lt;br /&gt;
  java -jar /Users/moodle/Downloads/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/Users/moodle/Downloads/chromedriver&lt;br /&gt;
&lt;br /&gt;
  # Windows (started using git bash) (firefox by default + chrome + internet explorer)&lt;br /&gt;
  java -jar /c/seleniumdrivers/selenium-server-standalone.jar -Dwebdriver.chrome.driver=/c/seleniumdrivers/chromedriver.exe -Dwebdriver.ie.driver=/c/seleniumdrivers/IEDriverServer.exe&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
&lt;br /&gt;
Not all the drivers can execute all of Moodle&#039;s step definitions; we tagged the step definitions that are using feature not supported by all browsers or that should be considered:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|File uploads (@_upload)&lt;br /&gt;
|Switch window (@_switch_window)&lt;br /&gt;
|Switch frame (@_switch_iframe)&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|Yes&lt;br /&gt;
|Yes&lt;br /&gt;
|Yes&lt;br /&gt;
|-&lt;br /&gt;
|Chrome&lt;br /&gt;
|Yes&lt;br /&gt;
|No&lt;br /&gt;
|Yes&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|Yes&lt;br /&gt;
|Yes&lt;br /&gt;
|Yes&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|Yes&lt;br /&gt;
|No&lt;br /&gt;
|Yes&lt;br /&gt;
|-&lt;br /&gt;
|PhantomJS&lt;br /&gt;
|No&lt;br /&gt;
|No&lt;br /&gt;
|Yes&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43507</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43507"/>
		<updated>2014-01-09T09:59:05Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Run behat using different browsers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and how we automatically test all of them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate users interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describes Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;), each feature file is composed by many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed by steps (for example  &#039;&#039;I press &amp;quot;Post to Forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into an PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
This features are executed nightly in the HQ servers with all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. Use &amp;quot;http://localhost:8000&amp;quot; if you use built-in PHP server.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_only_local&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
Following these instructions you can run behat in Firefox browser through Selenium, but you can run behat using different browsers through Selenium and even use phantomjs (Webkit). [[Acceptance_testing/Browsers|More info]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
== Links == &lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43506</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43506"/>
		<updated>2014-01-09T09:58:15Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and how we automatically test all of them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate users interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describes Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;), each feature file is composed by many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed by steps (for example  &#039;&#039;I press &amp;quot;Post to Forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into an PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
This features are executed nightly in the HQ servers with all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. Use &amp;quot;http://localhost:8000&amp;quot; if you use built-in PHP server.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_only_local&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Run behat using different browsers ==&lt;br /&gt;
&lt;br /&gt;
[[Acceptance_testing/Browsers|Information about how to run behat using other browsers]]&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
== Links == &lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43483</id>
		<title>Acceptance testing</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Acceptance_testing&amp;diff=43483"/>
		<updated>2014-01-02T03:56:27Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This page describes how we describe Moodle&#039;s functionalities and how we automatically test all of them.&lt;br /&gt;
&lt;br /&gt;
Behat is a behavioural driven development (BDD) tool written in PHP, it can parse a human-readable list of sentences (called steps) and execute actions in a browser using Selenium or other tools to simulate users interactions.&lt;br /&gt;
&lt;br /&gt;
For technical info: [[Behat integration]]&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
Behat parses and executes features files which describes Moodle&#039;s features (for example &#039;&#039;Post in a forum&#039;&#039;), each feature file is composed by many scenarios (for example &#039;&#039;Add a post to a discussion&#039;&#039; or &#039;&#039;Create a new discussion&#039;&#039;), and finally each scenario is composed by steps (for example  &#039;&#039;I press &amp;quot;Post to Forum&amp;quot;&#039;&#039; or &#039;&#039;I should see &amp;quot;My post title&amp;quot;&#039;&#039;). When the feature file is executed, every step internally is translated into an PHP method and is executed.&lt;br /&gt;
&lt;br /&gt;
This features are executed nightly in the HQ servers with all the supported databases (MySQL, PostgreSQL, MSSQL and Oracle) and with different browsers (Firefox, Internet Explorer, Safari and Chrome) to avoid regressions and test new functionalities.&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
* There is a closed list of steps to use in the features, a feature written with the basic (or low-level) steps looks like this:&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that The 3 sentences below &#039;&#039;Feature: Login&#039;&#039; are only information about what we want to test.&lt;br /&gt;
&lt;br /&gt;
These are simple scenarios, but most of Moodle&#039;s functionalities would require a huge list of this steps to test a scenario, imagine a &#039;&#039;Add a post to a discussion&#039;&#039; scenario; you need to login, create a course, create a user and enrol it in the course... Most of this steps is not what we intend to test in a &#039;&#039;Post in a forum&#039;&#039; feature, Moodle provides extra steps to quickly set up the context required to test a Moodle feature, for example:&lt;br /&gt;
&lt;br /&gt;
  @mod @mod_forum&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Add forum activities and discussions&lt;br /&gt;
    In order to discuss topics with other users&lt;br /&gt;
    As a moodle teacher&lt;br /&gt;
    I need to add forum activities to moodle courses&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Add a forum and a discussion&lt;br /&gt;
      &#039;&#039;&#039;Given&#039;&#039;&#039; the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
        | username | firstname | lastname | email |&lt;br /&gt;
        | teacher1 | Teacher | 1 | teacher1@asd.com |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
        | fullname | shortname | category |&lt;br /&gt;
        | Course 1 | C1 | 0 |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
        | user | course | role |&lt;br /&gt;
        | teacher1 | C1 | editingteacher |&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I log in as &amp;quot;teacher1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I follow &amp;quot;Course 1&amp;quot;&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I turn editing mode on&lt;br /&gt;
      &#039;&#039;&#039;And&#039;&#039;&#039; I add a &amp;quot;Forum&amp;quot; to section &amp;quot;1&amp;quot; and I fill the form with:&lt;br /&gt;
        | Forum name | Test forum name |&lt;br /&gt;
        | Forum type | Standard forum for general use |&lt;br /&gt;
        | Description | Test forum description |&lt;br /&gt;
      &#039;&#039;&#039;When&#039;&#039;&#039; I add a new discussion to &amp;quot;Test forum name&amp;quot; forum with:&lt;br /&gt;
        | Subject | Forum post subject |&lt;br /&gt;
        | Message | This is the body |&lt;br /&gt;
      &#039;&#039;&#039;Then&#039;&#039;&#039; I should see &amp;quot;Test forum name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Note that:&lt;br /&gt;
&lt;br /&gt;
* Each scenario is executed in an isolated testing environment, so the first step begins with an empty moodle site and what you set up in an scenario (like the &#039;&#039;Test forum name&#039;&#039; forum in the example above) is cleaned up after the scenario execution&lt;br /&gt;
* The prefixes &amp;quot;Given&amp;quot;, &amp;quot;When&amp;quot; and &amp;quot;Then&amp;quot; are only informative and they are used to define the context (Given), specify the action (When) and check the results (Then), using them properly helps to understand what the scenario is testing.&lt;br /&gt;
&lt;br /&gt;
== Quick start ==&lt;br /&gt;
&lt;br /&gt;
This is a quick introduction to write a functional test (acceptance tests) using steps in a development/testing site, please DON&#039;T USE THIS IN A PRODUCTION SITE.&lt;br /&gt;
&lt;br /&gt;
To let you experience the pleasure of watching a feature file doing &amp;quot;your work&amp;quot; automatically in a real browser, this guide includes 2 optional steps to download Selenium and run it in another CLI.&lt;br /&gt;
&lt;br /&gt;
# Open a command line interface&lt;br /&gt;
# &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
# Edit config.php adding the following lines before the lib/setup.php include&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;$CFG-&amp;gt;behat_prefix = &#039;b_&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_dataroot = &#039;/path/to/your/behat/dataroot/directory&#039;;&lt;br /&gt;
$CFG-&amp;gt;behat_wwwroot = &#039;http://127.0.0.1&#039;; // must be different from wwwroot&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039; (In case you have problems read https://docs.moodle.org/dev/Acceptance_testing#Installation)&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
# Download selenium-server-standalone-2.NN.N.jar from http://seleniumhq.org/download/, under &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
# Open another command line interface and run &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
# You just ran the current Moodle tests, now let&#039;s add your own test, add a blog entry for example&lt;br /&gt;
# Browse to your $CFG-&amp;gt;behat_wwwroot, this is an empty test site and it is reset before each test (called scenario)&lt;br /&gt;
# From this point follow the steps you would follow to add manually a blog entry (login credentials are admin/admin)&lt;br /&gt;
# When you are done go to &#039;Site administration&#039; -&amp;gt; &#039;Development&#039; -&amp;gt; &#039;Acceptance testing&#039;, you will find the list of &amp;quot;actions&amp;quot; that can be run automatically, you can filter them to find what do you need to do (more steps can be added if you need, more info in https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions)&lt;br /&gt;
# To &#039;add a blog entry&#039; we need to:&lt;br /&gt;
## Log in the system as a valid user&lt;br /&gt;
## Expand &#039;My profile&#039; node of the navigation block&lt;br /&gt;
## Expand the &#039;Blogs&#039; node of the navigation block&lt;br /&gt;
## Follow he &#039;Add a new entry&#039; link&lt;br /&gt;
## Fill the moodle form with values for &#039;Entry title&#039; and &#039;Blog entry body&#039;&lt;br /&gt;
## Press the &#039;Save changes&#039; button&lt;br /&gt;
## Verify you see the values you entered in the form and verify you are not in the form page&lt;br /&gt;
# This translated to steps is:&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
And I fill the moodle form with:&lt;br /&gt;
  | Entry title | I&#039;m the name |&lt;br /&gt;
  | Blog entry body | I&#039;m the description |&lt;br /&gt;
When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
Then I should see &amp;quot;Blog entries&amp;quot;&lt;br /&gt;
And I should see &amp;quot;I&#039;m the description&amp;quot;&lt;br /&gt;
And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# We need to wrap this steps following the behaviour driven development guidelines (more info in https://docs.moodle.org/dev/Acceptance_testing#Writing_features)&lt;br /&gt;
#: &amp;lt;code language=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
@core @core_blog&lt;br /&gt;
Feature: Add a blog entry&lt;br /&gt;
  In order to let the world know about me&lt;br /&gt;
  As a user&lt;br /&gt;
  I need to write blog entries&lt;br /&gt;
&lt;br /&gt;
  @javascript&lt;br /&gt;
  Scenario: Add a blog entry with valid data&lt;br /&gt;
    Given I log in as &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I expand &amp;quot;My profile&amp;quot; node&lt;br /&gt;
    And I expand &amp;quot;Blogs&amp;quot; node&lt;br /&gt;
    And I follow &amp;quot;Add a new entry&amp;quot;&lt;br /&gt;
    And I fill the moodle form with:&lt;br /&gt;
      | Entry title | I&#039;m the name |&lt;br /&gt;
      | Blog entry body | I&#039;m the description |&lt;br /&gt;
    When I press &amp;quot;Save changes&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;View all of my entries&amp;quot;&lt;br /&gt;
    And I should see &amp;quot;I&#039;m a description&amp;quot;&lt;br /&gt;
    And I should not see &amp;quot;Required&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# And save it into a file, in this case &#039;&#039;&#039;blog/tests/behat/add_entry.feature&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;  (This will update the available tests and steps definitions)&lt;br /&gt;
# &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/behat/dataroot/directory/behat/behat.yml --tags @core_blog&#039;&#039;&#039;&lt;br /&gt;
# Selenium will open a browser (firefox by default) and you will see how the steps you have been writting are executed&lt;br /&gt;
&lt;br /&gt;
You can also try to expand non existing nodes or change the &#039;Then&#039; assertions to get a beautiful failure.&lt;br /&gt;
&lt;br /&gt;
For detailed steps and/or troubleshooting:&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Running_tests&lt;br /&gt;
* https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* PHP 5.4 (see https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for PHP 5.3, only for non-production sites)&lt;br /&gt;
* Other dependencies are managed by the composer installer&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
* Edit config.php&lt;br /&gt;
** Use $CFG-&amp;gt;behat_dataroot to set the directory where behat test environment dataroot will be stored, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_dataroot = &#039;/your/directory/path&#039;;&#039;&#039;&#039;. Ensure the directory can be created or have write permissions&lt;br /&gt;
** Use $CFG-&amp;gt;behat_prefix to set the database prefix of the behat test environment database tables, something like &#039;&#039;&#039;$CFG-&amp;gt;behat_prefix = &#039;behat_&#039;;&#039;&#039;&#039;&lt;br /&gt;
** Use $CFG-&amp;gt;behat_wwwroot to set address to be used to access behat instance. It has to be different from $CFG-&amp;gt;wwwroot, you can use for example localhost, 127.0.0.1 or any custom local host name specified in you /etc/hosts. Use &amp;quot;http://localhost:8000&amp;quot; if you use built-in PHP server.&lt;br /&gt;
* Download composer&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;&lt;br /&gt;
*** If you don&#039;t have curl installed or you have problems running &#039;&#039;&#039;curl http://getcomposer.org/installer | php&#039;&#039;&#039;:&lt;br /&gt;
**** Download &#039;&#039;&#039;http://getcomposer.org/installer&#039;&#039;&#039;&lt;br /&gt;
**** Store it in /your/moodle/dirroot/composerinstaller.php for example&lt;br /&gt;
**** Run it from /your/moodle/dirroot with &#039;&#039;&#039;php composerinstaller.php&#039;&#039;&#039;, you can delete this file after running the next step (&#039;&#039;&#039;php composer.phar update --dev&#039;&#039;&#039;)&lt;br /&gt;
* Install behat dependencies and enable the test environment&lt;br /&gt;
** &#039;&#039;&#039;cd /your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039;&lt;br /&gt;
* (Optional) If you want to run tests that involves Javascript (most of them) you will also need Selenium&lt;br /&gt;
** Download it from http://seleniumhq.org/download/, named &amp;quot;Selenium server (formerly the Selenium RC Server)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Running tests ==&lt;br /&gt;
# (Optional) Start the PHP built-in web server if you configured the $CFG-&amp;gt;behat_wwwroot to use it:&lt;br /&gt;
#* Open a command line interface and &#039;&#039;&#039;cd /to/your/moodle/dirroot&#039;&#039;&#039;&lt;br /&gt;
#* &#039;&#039;&#039;php -S localhost:8000&#039;&#039;&#039; (This is the test site URL that moodle uses by default, if you want to use another one you can override it in config.php with $CFG-&amp;gt;behat_wwwroot attribute; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage or config-dist.php)&lt;br /&gt;
# (Optional) Start the Selenium server (in case you want to run tests that involves Javascript)&lt;br /&gt;
#* Open another command line interface and &#039;&#039;&#039;java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar&#039;&#039;&#039;&lt;br /&gt;
# Run Behat&lt;br /&gt;
#* &#039;&#039;&#039;vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039; (For more options &#039;&#039;&#039;vendor/bin/behat --help&#039;&#039;&#039; or http://docs.behat.org/guides/6.cli.html)&lt;br /&gt;
#* In case you don&#039;t want to run Javascript tests use the Behat tags option to skip them, &#039;&#039;&#039;vendor/bin/behat --tags ~@javascript --config /path/to/your/CFG_behat_dataroot/behat/behat.yml&#039;&#039;&#039;&lt;br /&gt;
#* If you followed all the steps and you receive an unknown weird error probably your system&#039;s Firefox version is not compatible with the Selenium version you are running, try downloading the latest Selenium release from it&#039;s website as explained above&lt;br /&gt;
# (Optional) If you are adding new tests or steps definitions update the tests list:&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039;&lt;br /&gt;
# (Optional) Disable test environment (if you want to prevent access to test environment)&lt;br /&gt;
#* &#039;&#039;&#039;php admin/tool/behat/cli/util.php --disable&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that if you have the HTTP_PROXY environment variable set, which you may have had to do to run composer, then you also need to set NO_PROXY=localhost.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests filters ===&lt;br /&gt;
With the &#039;&#039;&#039;--tags&#039;&#039;&#039; or the &#039;&#039;&#039;-name&#039;&#039;&#039; Behat options you can filter which tests are going to run or which ones are going to be skipped. There are a few tags that you might be interested in:&lt;br /&gt;
* &#039;&#039;&#039;@javascript&#039;&#039;&#039;: All the tests that runs in a browser using Javascript; they require Selenium to be running, otherwise an exception will be thrown.&lt;br /&gt;
* &#039;&#039;&#039;@_only_local&#039;&#039;&#039;: All the tests that involves file uploading or any OS feature that is not 100% part of the browser. They should only be executed when Selenium is running in the same machine where the tests are running.&lt;br /&gt;
* &#039;&#039;&#039;@_cross_browser&#039;&#039;&#039;: All the tests that should run against multiple combinations of browsers + OS in a regular basis. The features that are sensitive to different combinations of OS and browsers should be tagges as @_cross_browser.&lt;br /&gt;
* &#039;&#039;&#039;@componentname&#039;&#039;&#039;: Moodle features uses the [https://docs.moodle.org/dev/Frankenstyle Frankenstyle] component name to tag the features according to the Moodle subsystem they belong to.&lt;br /&gt;
&lt;br /&gt;
=== Output formats ===&lt;br /&gt;
&lt;br /&gt;
If you want to see the failures immediately (rather than waiting ~3 hours for all the tests to finish) then either use the -v option to output a bit more information, or change the output format using --format.&lt;br /&gt;
&lt;br /&gt;
== Advanced usage ==&lt;br /&gt;
There are a few settings for advanced use of Behat and execution in continuous integration systems, by default all this options are disabled, use this settings only if you know what you are doing.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Different test server URL&#039;&#039;&#039;. If for example your are interested in allowing accesses from your local network because your Jenkins server is there you can set $CFG-&amp;gt;behat_wwwroot to &#039;&#039;&#039;http://my.computer.local.ip:8000&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Behat configuration&#039;&#039;&#039;, Moodle writes a behat.yml config file with info about the available tests and steps definitions along with other Behat parameters, you can override the Behat parameters we set and add your new parameters, your parameters will be merged with the Moodle ones giving priority to your values in case of conflict. This is useful for an advanced use of Behat, with multiple profiles, output formats, integration with continuous servers... &lt;br /&gt;
* &#039;&#039;&#039;Running with a browser other than Firefox&#039;&#039;&#039;, by adding the following code to your config.php you can change the selected browser that is run when behat is invoked. In this case Chrome is selected, but internet explorer, firefox, iphone, android, chrome, htmlunit should be valid options. You will need to run &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; for changes to take effect.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code language=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = array(&lt;br /&gt;
    &#039;default&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;Behat\MinkExtension\Extension&#039; =&amp;gt; array(&lt;br /&gt;
                &#039;selenium2&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;browser&#039; =&amp;gt; &#039;chrome&#039;&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Note that for Chrome, you will need the Selenium Chrome Driver (https://code.google.com/p/selenium/wiki/ChromeDriver), and it will need to be installed in the command search path.&lt;br /&gt;
* &#039;&#039;&#039;Switch completely to test environment&#039;&#039;&#039; option was removed in 2.7, it is recommended to always set $CFG-&amp;gt;behat_wwwroot even in older versions instead.&lt;br /&gt;
* Note that when using cloud-based systems that can make use of non-standard capabilities like Saucelabs, you might want to provide configuration attributes containing the &#039;&#039;&#039;&#039;-&#039;&#039;&#039;&#039; character, which is automatically converted to &#039;&#039;&#039;&#039;_&#039;&#039;&#039;&#039; by the Symfony configuration manager that Behat is making use of (@see Symfony\Component\Config\Definition\Processor::normalizeKeys()) a way to avoid this restriction is to, adding to the vars you set like &#039;&#039;&#039;&#039;max-duration&#039;&#039;&#039;&#039; add the same var replacing dashes for underscores, this way the configuration manager will maintain the attribute containing dashes.&lt;br /&gt;
* &#039;&#039;&#039;Extra allowed settings&#039;&#039;&#039;, moodle allows users to define many settings in config.php (see config-dist.php) when running the behat test site those settings are skipped to avoid interaction with the production environment, in case you are interested in allowing some of those extra settings to run the tests using a configuration similar to the one you are using in your production environment you can whitelist them adding them to $CFG-&amp;gt;behat_extraallowedsettings (see config-dist.php for examples).&lt;br /&gt;
You can find more info and examples of how to use this settings in the config-dist.php file included in the Moodle codebase.&lt;br /&gt;
&lt;br /&gt;
== Writing features ==&lt;br /&gt;
&lt;br /&gt;
All Moodle components and plugins (including 3rd party plugins) can specify their tests in .feature files using all the available steps.&lt;br /&gt;
&lt;br /&gt;
Once you decided which functionality you want to specify as a feature you should:&lt;br /&gt;
# Select the most appropriate Moodle component to include your test and create a COMPONENTNAME/tests/behat/FEATURENAME.feature file&lt;br /&gt;
# Add a tag with the component name in Frankenstyle format (https://docs.moodle.org/dev/Frankenstyle) on the first line along with the plugin type or @core if it&#039;s a core subsystem&lt;br /&gt;
# Begin writing the user story of the feature, including in the &#039;As a ...&#039; statement the main beneficiary of the feature:&lt;br /&gt;
#: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@plugintype @plugintype_pluginname&lt;br /&gt;
Feature: FEATURENAME&lt;br /&gt;
  In order to ...    // Why this feature is useful&lt;br /&gt;
  As ...    // It can be &#039;an admin&#039;, &#039;a teacher&#039;, &#039;a student&#039;, &#039;a guest&#039;, &#039;a user&#039;, &#039;a tests writer&#039; and &#039;a developer&#039;&lt;br /&gt;
  I need to ...      // The feature we want&amp;lt;/code&amp;gt;&lt;br /&gt;
# From the beneficiary point of view, think of different scenarios to ensure the feature works as expected&lt;br /&gt;
# For each scenario you thought:&lt;br /&gt;
## Think of the initial context you need, for example &#039;&#039;1 course with 2 students on it and an assignment&#039;&#039;, and which steps do you need to follow (interacting with the browser) to verify the scenario works as expected&lt;br /&gt;
## What you are testing requires Javascript? Think only on the feature you are testing (for example if you want to test that you can view your profile you don&#039;t need Javascript to click on a link and assert against plain HTML, but if you want to test something related with the course&#039;s gradebook you might want to test it with Javascript)&lt;br /&gt;
## Check the steps list (more info in https://docs.moodle.org/dev/Acceptance_testing#Available_steps) and set the initial context data (see https://docs.moodle.org/dev/Acceptance_testing#Fixtures for more info) and the steps to follow to verify all works as it should work. &lt;br /&gt;
## The prefixes &#039;&#039;Given&#039;&#039;, &#039;&#039;When&#039;&#039; and &#039;&#039;Then&#039;&#039; separates the scenario in 3 parts, the initial context setup (&#039;&#039;Given&#039;&#039;), the action that provokes a change in the system (&#039;&#039;When&#039;&#039;) and the validation of that change outcomes (&#039;&#039;Then&#039;&#039;) So with a quick view at the scenario you can see what it is testing as the prefixes will be something like Given -&amp;gt; And -&amp;gt; And -&amp;gt; When -&amp;gt; And -&amp;gt; And -&amp;gt; Then -&amp;gt; And -&amp;gt; And -&amp;gt; And. Once we begin with the first &#039;&#039;Then&#039;&#039; we can consider that we are checking the outcomes so all the steps from there should be prefixed with &#039;&#039;Then&#039;&#039;&lt;br /&gt;
## Copy the list of steps to the .feature file with the Scenario header:&lt;br /&gt;
##: &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;Scenario: Short description of the scenario&lt;br /&gt;
  Given step 1&lt;br /&gt;
  And step 2&lt;br /&gt;
  And step 3&lt;br /&gt;
  When step 4&lt;br /&gt;
  And step 5&lt;br /&gt;
  Then step 6&amp;lt;/code&amp;gt;&lt;br /&gt;
## If the steps you are using requires Javascript add the @javascript tag above the &amp;quot;Scenario:&amp;quot; headline&lt;br /&gt;
##:    &amp;lt;code lang=&amp;quot;yaml&amp;quot;&amp;gt;@javascript&lt;br /&gt;
Scenario: Short description of the scenario&lt;br /&gt;
  ...&lt;br /&gt;
  ...&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run the tests, when creating your new features/scenarios you can specify a &#039;@wip&#039; (work in progress) tag in both the line above the Scenario description and the tests runner (vendor/bin/behat) to execute only the new scenario instead of running the whole set of tests.&lt;br /&gt;
# Add extra tags to the scenario or the feature if required&lt;br /&gt;
#* If there are scenarios that includes files uploads they should be tagged as @_only_local&lt;br /&gt;
#* If there are scenarios that are likely to fail in some browser-OS combinations they can be tagged as @_cross_browser, they will be tested in different OS / browser combinations by Moodle HQ continuous integration servers&lt;br /&gt;
&lt;br /&gt;
=== Available steps ===&lt;br /&gt;
&lt;br /&gt;
Moodle provides a interface to list and filter the steps you can use when writing features. You can access it through the Administration block, following &#039;&#039;&#039;Site Administration&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Development&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;Acceptance testing&#039;&#039;&#039;. It allows filtering by keyword, by the Moodle component or by the type of step:&lt;br /&gt;
* Processes to set up the environment&lt;br /&gt;
* Actions that provokes an event&lt;br /&gt;
* Checkings to ensure the outcomes are the expected ones&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
* You can use a &#039;&#039;&#039;Background&#039;&#039;&#039; section before the &#039;&#039;&#039;Scenario&#039;&#039;&#039; sections, this steps will be executed before the steps of each scenario (http://docs.behat.org/guides/1.gherkin.html#backgrounds)&lt;br /&gt;
* You can use &#039;&#039;&#039;Scenario outlines&#039;&#039;&#039; if your scenarios are nearly the same and depends on a few vars; check out the link for an explicative example (http://docs.behat.org/guides/1.gherkin.html#scenario-outlines)&lt;br /&gt;
* Is better to test the outcomes against the given data than against language strings, which are depending on the selected language.&lt;br /&gt;
* In case you need to interact with popup windows you need to switch to the window you want to interact with after opening it using the &#039;&#039;&#039;I switch to &amp;quot;popupwindowname&amp;quot; window&#039;&#039;&#039;, close it when you finish interacting with it and return to the main window using &#039;&#039;&#039;I switch to main window&#039;&#039;&#039;&lt;br /&gt;
* The format of the .feature files is YAML which finds out the data hierarchy from the indentation of it&#039;s elements, so be sure that the elements are correctly nested and the indentation is correct using spaces when necessary&lt;br /&gt;
&lt;br /&gt;
=== Providing values to steps ===&lt;br /&gt;
Most of the steps requires values, there are five methods to provide values to steps, the method depends on the step specification, you can know when a steps requires a value because you will see a drop down menu with a closed list of options that the step accepts as argument or an upper case string between double quotes, something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; or it ends with a &#039;&#039;&#039;:&#039;&#039;&#039; . The five methods are:&lt;br /&gt;
* &#039;&#039;&#039;A string/text&#039;&#039;&#039;; is the most common case, the texts are wrapped between double quotes (&amp;quot; character) you have to replace the info about the expected value for your value; for example something like &#039;&#039;&#039;I press &amp;quot;BUTTON_STRING&amp;quot;&#039;&#039;&#039; should become &#039;&#039;&#039;I press &amp;quot;Save and return to course&amp;quot;&#039;&#039;&#039;. If you want to add a string which contains a &amp;quot; character, you can escape it with \&amp;quot;, for example &#039;&#039;&#039;I fill the &amp;quot;Name&amp;quot; field with &amp;quot;Alan alias \&amp;quot;the legend\&amp;quot;&amp;quot;&#039;&#039;&#039;. You can identify this steps because they ends with &#039;&#039;&#039;_STRING&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A number&#039;&#039;&#039;; some steps requires numbers as values, to be more specific an undetermined number of digits from 0 to 9 (Natural numbers + 0) you can identify them because the expected value info string ends with &#039;&#039;&#039;_NUMBER&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;A table&#039;&#039;&#039;; is a relation between values, the most common use of it is to fill forms. The steps which requires tables are easily identifiable because they finish with &#039;&#039;&#039;:&#039;&#039;&#039; The steps description gives info about what the table columns must contain, for example &#039;&#039;&#039;Fills a moodle form with field/value data&#039;&#039;&#039;. Here you don&#039;t need to escape the double quotes if you want to include them as part of the value.&lt;br /&gt;
* &#039;&#039;&#039;A selector&#039;&#039;&#039;; there are steps that can be used with different kinds of elements, for example &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;link&amp;quot;&#039;&#039;&#039; or &#039;&#039;&#039;I click on &amp;quot;User Name&amp;quot; &amp;quot;button&amp;quot;&#039;&#039;&#039; this is a closed list of elements, they always works together with another argument, where you specify the locator (eg. the link text in a link) In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** field - for searching a field by its id, name, value or label&lt;br /&gt;
** link - for searching a link by its href, id, title, img alt or value&lt;br /&gt;
** button - for searching a button by its name, id, value, img alt or title&lt;br /&gt;
** link_or_button - for searching for both, links and buttons&lt;br /&gt;
** select - for searching a select field by its id, name or label&lt;br /&gt;
** checkbox - for searching a checkbox by its id, name, or label&lt;br /&gt;
** radio - for searching a radio button by its id, name, or label&lt;br /&gt;
** file - for searching a file input by its id, name, or label&lt;br /&gt;
** optgroup - for searching optgroup by its label&lt;br /&gt;
** option - for searching an option by its content&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
* &#039;&#039;&#039;A text selector&#039;&#039;&#039;; similar to a selector but those are the elements that returns an area of the DOM, they are useful in steps following the format &#039;&#039;&#039;... in the &amp;quot;Community finder&amp;quot; &amp;quot;block&amp;quot;&#039;&#039;&#039; where you are clicking or looking for some text inside a specific area. In the &#039;Acceptance testing&#039; interface you can see a drop-down menu to select one of these options:&lt;br /&gt;
** dialogue - for searching a dialogue with the specified header text&lt;br /&gt;
** block - for searching a Moodle block by it&#039;s Enligh name or it&#039;s frankenstyle name&lt;br /&gt;
** region - for searching a Moodle page region with that id, in fact it works with all the page&#039;s ids&lt;br /&gt;
** table_row - for searching a table row which contains the specified text&lt;br /&gt;
** table - for searching a table by its id or caption&lt;br /&gt;
** fieldset - for searching a fieldset by it&#039;s id or legend&lt;br /&gt;
** css_element - for searching an element by its CSS selector&lt;br /&gt;
** xpath_element - for searching an element by its XPath&lt;br /&gt;
&lt;br /&gt;
==== Uploading files ====&lt;br /&gt;
Note than some tests requires files to be uploaded, in this case&lt;br /&gt;
* The &#039;&#039;&#039;I upload &amp;quot;FILEPATH_STRING&amp;quot; file to &amp;quot;FILEPICKER_FIELD_STRING&amp;quot; filepicker&#039;&#039;&#039; step can be used when located in the form page&lt;br /&gt;
* The file to upload should be included along with the Moodle codebase in COMPONENTNAME/tests/fixtures/*&lt;br /&gt;
* The file to upload is specified by it&#039;s path, which should be relative to the codebase root (&#039;&#039;&#039;lib/tests/fixtures/users.csv&#039;&#039;&#039; for example) &lt;br /&gt;
* &#039;&#039;&#039;/&#039;&#039;&#039; should be used as directory separator and the file names can not include this &#039;&#039;&#039;/&#039;&#039;&#039; character as all of them would be converted to the OS-dependant directory separator to maintain the compatibility with Windows systems.&lt;br /&gt;
* The scenarios that includes files uploading should be tagged using the &#039;&#039;&#039;@_only_local&#039;&#039;&#039; tag&lt;br /&gt;
&lt;br /&gt;
=== Fixtures ===&lt;br /&gt;
&lt;br /&gt;
As seen in [[https://docs.moodle.org/dev/Acceptance_testing#Examples examples]] Moodle provides a way to quickly set up the contextual data (courses, users, enrolments...) that you need to properly test scenarios, this can be done using one of the site templates (TODO) or creating entities in the background section (common for all the steps) or in the &amp;quot;Given&amp;quot; part of your scenario. Note that this steps can only be used to set up the contextual data required to test the feature but they don&#039;t test what they are doing; for example, the &amp;quot;Given the following &amp;quot;users&amp;quot; exists&amp;quot; is not testing that Moodle is able to create a user, but to test that a user can add a blog entry you might want to use this step. For further info, acceptance tests are supposed to be black-boxed tests (the tester don&#039;t know about the internals of the application) and this steps are using internal Moodle data generators instead of running all the steps required to create a user or to create a course, which speeds up the test execution. There are other features to test that all this elements can be properly created.&lt;br /&gt;
&lt;br /&gt;
==== Available elements ====&lt;br /&gt;
Most of the available elements can only be created in relation to other elements, to hide the complexity of the Moodle internals (references by contexts, ids...) the references can be done using more human-friendly mappings. &lt;br /&gt;
&lt;br /&gt;
The examples below shows how to add elements referencing other elements, there are required fields to reference the elements, other attributes will be filled with random data if they are not specified.&lt;br /&gt;
&lt;br /&gt;
* Course categories&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
** References between parent/children by their idnumber, using the &amp;quot;category&amp;quot; field&lt;br /&gt;
  Given the following &amp;quot;categories&amp;quot; exists:&lt;br /&gt;
    | name       | category | idnumber |&lt;br /&gt;
    | Category 1 | 0        | CAT1     |&lt;br /&gt;
    | Category 2 | CAT1     | CAT2     |&lt;br /&gt;
&lt;br /&gt;
* Courses&lt;br /&gt;
** The required field is shortname&lt;br /&gt;
** Uses the category idnumber as category reference&lt;br /&gt;
  Given the following &amp;quot;courses&amp;quot; exists:&lt;br /&gt;
    | fullname | shortname | category | format | &lt;br /&gt;
    | Course 1 | COURSE1   | CAT1     | topics |&lt;br /&gt;
    | Course 2 | COURSE2   | CAT2     |        |&lt;br /&gt;
&lt;br /&gt;
* Activities *(note that this step does not work with all kind of activities, only the ones that have data generators)*&lt;br /&gt;
** The required fields are activity, course and idnumber&lt;br /&gt;
** Uses activity to specify the activity type&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Other activity-dependant fields can be specified by it&#039;s field name&lt;br /&gt;
  Given the following &amp;quot;activities&amp;quot; exists:&lt;br /&gt;
    | activity | course | idnumber | name                 | intro                       |&lt;br /&gt;
    | assign   | C1     | assign1  | Test assignment name | Test assignment description |&lt;br /&gt;
    | data     | C1     | data1    | Test database name   | Test database description   |&lt;br /&gt;
&lt;br /&gt;
* Groups&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groups&amp;quot; exists:&lt;br /&gt;
    | name    | description | course  | idnumber |&lt;br /&gt;
    | Group 1 | Anything    | COURSE1 | GROUP1   |&lt;br /&gt;
&lt;br /&gt;
* Groupings&lt;br /&gt;
** The required fields are course and idnumber&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
  Given the following &amp;quot;groupings&amp;quot; exists:&lt;br /&gt;
    | name       | course  | idnumber  |&lt;br /&gt;
    | Grouping 1 | COURSE1 | GROUPING1 |&lt;br /&gt;
    | Grouping 2 | COURSE1 | GROUPING2 |&lt;br /&gt;
&lt;br /&gt;
* Users&lt;br /&gt;
** The required field is username (if password is not set username value will be used as password too)&lt;br /&gt;
  Given the following &amp;quot;users&amp;quot; exists:&lt;br /&gt;
    | username | email       | firstname | lastname |&lt;br /&gt;
    | testuser | asd@asd.com | Test      | User     |&lt;br /&gt;
&lt;br /&gt;
* Course enrolments&lt;br /&gt;
** The required fields are user, course and role&lt;br /&gt;
** Uses the course shortname as course reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses the enrolment name as enrol reference&lt;br /&gt;
  Given the following &amp;quot;course enrolments&amp;quot; exists:&lt;br /&gt;
    | user     | course  | role           | enrol  |&lt;br /&gt;
    | testuser | COURSE1 | editingteacher | manual |&lt;br /&gt;
&lt;br /&gt;
* Role assigns&lt;br /&gt;
** The required fields are user, role, contextlevel and reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;role assigns&amp;quot; exists:&lt;br /&gt;
    | user  | role           | contextlevel | reference |&lt;br /&gt;
    | user1 | manager        | System       |           |&lt;br /&gt;
    | user2 | editingteacher | Category     | CATEGORY1 |&lt;br /&gt;
    | user3 | editingteacher | Course       | COURSE1   |&lt;br /&gt;
&lt;br /&gt;
* System role assigns (deprecated in favour of role assigns, see item right above this one)&lt;br /&gt;
** The required fields are user and role&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
** Uses the role shortname as role reference&lt;br /&gt;
  Given the following &amp;quot;system role assigns&amp;quot; exists:&lt;br /&gt;
    | user     | role    |&lt;br /&gt;
    | testuser | manager |&lt;br /&gt;
&lt;br /&gt;
* Group members&lt;br /&gt;
** The required fields are user and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the user username as user reference&lt;br /&gt;
  Given the following &amp;quot;group members&amp;quot; exists:&lt;br /&gt;
    | user     | group  |&lt;br /&gt;
    | testuser | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Grouping groups&lt;br /&gt;
** The required fields are grouping and group&lt;br /&gt;
** Uses the group idnumber as group reference&lt;br /&gt;
** Uses the grouping idnumber as grouping reference&lt;br /&gt;
  Given the following &amp;quot;grouping groups&amp;quot; exists:&lt;br /&gt;
    | grouping  | group  |&lt;br /&gt;
    | GROUPING1 | GROUP1 |&lt;br /&gt;
&lt;br /&gt;
* Cohorts&lt;br /&gt;
** The required field is idnumber&lt;br /&gt;
  Given the following &amp;quot;cohorts&amp;quot; exists:&lt;br /&gt;
    | name     | idnumber |&lt;br /&gt;
    | Cohort 1 | COHORT1  |&lt;br /&gt;
&lt;br /&gt;
* Permission overrides&lt;br /&gt;
** The required fields are capability, permissions, role, and the contextlevel + it&#039;s reference&lt;br /&gt;
** Uses contextlevel + reference to specify the context. See [[#Referencing_contexts]] for more info.&lt;br /&gt;
  Given the following &amp;quot;permission overrides&amp;quot; exists:&lt;br /&gt;
    | capability            | permission | role           | contextlevel | reference |&lt;br /&gt;
    | mod/forum:editanypost | Allow      | student        | Course       | C1        |&lt;br /&gt;
    | mod/forum:replynews   | Prevent    | editingteacher | Course       | C1        |&lt;br /&gt;
    | mod/paquiro:sings     | Prohibit   | student        | System       |           |&lt;br /&gt;
&lt;br /&gt;
==== Referencing contexts ====&lt;br /&gt;
&lt;br /&gt;
Moodle has different context levels, internally they have an identifier, but to reference them from steps we can use a more human way, using the level of the context (as specified below) and the reference, which will depend on the contextlevel we are using:&lt;br /&gt;
* contextlevel: &#039;&#039;&#039;System&#039;&#039;&#039;, &#039;&#039;&#039;User&#039;&#039;&#039;, &#039;&#039;&#039;Category&#039;&#039;&#039;, &#039;&#039;&#039;Course&#039;&#039;&#039; and &#039;&#039;&#039;Activity Module&#039;&#039;&#039;&lt;br /&gt;
* reference:&lt;br /&gt;
** System: Nothing, just leave the the cell empty&lt;br /&gt;
** User: The user &#039;&#039;&#039;username&#039;&#039;&#039;&lt;br /&gt;
** Category: The category &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
** Course: The course &#039;&#039;&#039;shortname&#039;&#039;&#039;&lt;br /&gt;
** Activity module: The activity &#039;&#039;&#039;idnumber&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The data generators which makes use of these format are pointing to here.&lt;br /&gt;
&lt;br /&gt;
=== Features check list ===&lt;br /&gt;
* It&#039;s a new feature or a new scenario of an existing feature&lt;br /&gt;
* Is using the &#039;&#039;&#039;Background&#039;&#039;&#039; section or &#039;&#039;&#039;Scenario Outlines&#039;&#039;&#039; instead of duplicating steps (only when applicable)&lt;br /&gt;
* Are using the appropriate Moodle component tag and includes @_only_local or @_cross_browser when required&lt;br /&gt;
* The user story of the feature includes a valid stakeholder and makes sense according to https://docs.moodle.org/dev/Acceptance_testing#Writing_features&lt;br /&gt;
* Covers both JS and non-JS environments&lt;br /&gt;
&lt;br /&gt;
== Adding steps definitions ==&lt;br /&gt;
&lt;br /&gt;
Each Moodle component and plugin (including 3rd party plugins) can add new steps definitions. If you are writing tests and you notice that you are repeating the same group of steps you might want to create a new step definition that allows you to substitute the group of steps for one single step, something like &#039;&#039;I add a forum post with &amp;quot;blablabla&amp;quot; as description&#039;&#039; for example; also you can create whole new steps using the APIs provided by Behat and Mink if what you need to do is not covered by any of the available steps.&lt;br /&gt;
&lt;br /&gt;
As commented in https://docs.moodle.org/dev/Acceptance_testing#Fixtures, this are black box tests, so we are not supposed to know about Moodle internals; translated to developer language it means don&#039;t use Moodle internals API calls, for example you should not try to cheat using a set_config() call, you should follow Moodle&#039;s user interface to reach the setting page and change it&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
You can use this example below or any of the existing steps definitions as a template.&lt;br /&gt;
&lt;br /&gt;
* auth/tests/behat/behat_auth.php&lt;br /&gt;
  class behat_auth extends behat_base {&lt;br /&gt;
      /**&lt;br /&gt;
       * Logs in the user. There should exist a user with the same value as username and password&lt;br /&gt;
       *&lt;br /&gt;
       * This second comment line will be not shown in the steps definitions list as it is only&lt;br /&gt;
       * reading the first line in the comment block.&lt;br /&gt;
       *&lt;br /&gt;
       * @Given /^I log in as &amp;quot;(?P&amp;lt;username_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot;$/&lt;br /&gt;
       */&lt;br /&gt;
      public function i_log_in_as($username) {&lt;br /&gt;
          return array(new Given(&#039;I am on homepage&#039;),&lt;br /&gt;
              new Given(&#039;I follow &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;username&#039;) . &#039;&amp;quot; with &amp;quot;&#039; . $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I fill in &amp;quot;&#039; . get_string(&#039;password&#039;) . &#039;&amp;quot; with &amp;quot;&#039;. $this-&amp;gt;escape($username) . &#039;&amp;quot;&#039;),&lt;br /&gt;
              new Given(&#039;I press &amp;quot;&#039; . get_string(&#039;login&#039;) . &#039;&amp;quot;&#039;)&lt;br /&gt;
          );&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
=== Tips ===&lt;br /&gt;
&lt;br /&gt;
If you are creating a completely new step definition there are also a few things to consider:&lt;br /&gt;
* Steps definitions should be compatible with both Javascript and non-Javascript tests, you can use $this-&amp;gt;running_javascript() to deal with both&lt;br /&gt;
* The definition code will be executed by Behat, not by Moodle, you have to keep this in mind for example when throwing exceptions, Behat exceptions will give more info to the user about where is the problem&lt;br /&gt;
** You can find these exceptions in &#039;&#039;&#039;vendor/behat/mink/src/Behat/Mink/Exception/*&#039;&#039;&#039;&lt;br /&gt;
* Selenium is fast, sometimes it tries to interact with DOM elements or tries to execute actions that requires JS that are not loaded or ready to used; this is why, sometimes and randomly, you can see an &amp;quot;element not found&amp;quot; failure&lt;br /&gt;
** The quickest way to solve this problem is using behat_base::find*() methods (where the * corresponds to &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;, &#039;&#039;&#039;_all&#039;&#039;&#039;, or to a named selector preceded by &#039;&#039;&#039;_&#039;&#039;&#039;, http://mink.behat.org/#named-selectors) which only requires the locator as argument. This methods will wait for the requested element to be ready or return an exception if the element is not found after the timeout value expires, you can also force the timeout value, which defaults to 6 seconds. An example of a named selector use is &#039;&#039;&#039;$button = $this-&amp;gt;find_button(&amp;quot;Save changes&amp;quot;);&#039;&#039;&#039; if you are not sure about the element being available you always can wrap the find*() call in a try &amp;amp; catch.&lt;br /&gt;
** For advanced usages, the spin method is defined in &#039;&#039;&#039;lib/behat/behat_base::spin&#039;&#039;&#039;, consider that all the contents of the closures passed to spin() can be executed more than once, so don&#039;t use irreversible actions that can invalidate the tests results (for example use find() methods but don&#039;t use click() methods)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you create new steps definitions or tests you must run &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; to update the Behat config file before running &#039;&#039;&#039;vendor/bin/behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Check list ===&lt;br /&gt;
&lt;br /&gt;
New steps should be/have:&lt;br /&gt;
* Implemented as public methods of a PHP class whose name must begin with &#039;behat_&#039; prefix and with &#039;.php extension&lt;br /&gt;
* Using the class name as filename (adding the &#039;.php&#039; extension) and extending MOODLEDIRROOT/lib/behat/behat_base.php (or MOODLEDIRROOT/lib/behat/behat_files.php if it&#039;s a repository or is files-related)&lt;br /&gt;
* With a descriptive class name, for example the component name (it will be used when filtering steps definitions)&lt;br /&gt;
* Stored in COMPONENTNAME/tests/behat/ directory or lib/tests/behat/ if is not part of any other component&lt;br /&gt;
* Describe it&#039;s purpose in a single line inside the method doc comment, the size of the comment is not a problem&lt;br /&gt;
* Describe the regular expression with the most appropriate tag inside the method doc comment:&lt;br /&gt;
** &#039;&#039;&#039;@Given&#039;&#039;&#039; - A step to set up the initial context (for example &#039;&#039;the following &amp;quot;courses&amp;quot; exists&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@When&#039;&#039;&#039; - An action that provokes an event (for example &#039;&#039;I press the button &amp;quot;buttonname&amp;quot;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;@Then&#039;&#039;&#039; - Checkings to ensure the outcomes are the expected (for example &#039;&#039;I should see &amp;quot;whatever&amp;quot;&#039;&#039;)&lt;br /&gt;
* Depending on the inputs your definition expects you must use a different regular expression:&lt;br /&gt;
** &#039;&#039;&#039;If you expect a number:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_number&amp;gt;\d+)&amp;quot; (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a string or a text:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;info_about_what_you_expect_string&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; Don&#039;t use &#039;&#039;&#039;text_selector_string&#039;&#039;&#039; and &#039;&#039;&#039;selector_string&#039;&#039;&#039; as info strings, they are reserved to selector types (note that the regular expression is quoted between &#039;&#039;&#039;&amp;quot;&#039;&#039;&#039;)&lt;br /&gt;
** &#039;&#039;&#039;If you expect a table with key/value pairs (for example to fill a form):&#039;&#039;&#039; Finish your regular expression with &#039;&#039;&#039;:&#039;&#039;&#039; and provide info in the description about the contents of the table&lt;br /&gt;
** &#039;&#039;&#039;If you expect a selector type:&#039;&#039;&#039; &amp;quot;(?P&amp;lt;selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; or &amp;quot;(?P&amp;lt;text_selector_string&amp;gt;[^&amp;quot;]*)&amp;quot; depending on whether you want to use any selector or you want a text-based selector (more info about selectors in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps)&lt;br /&gt;
* To make test writer&#039;s life better is good to include explicative info in the subexpressions of the regular expression about what the test writer is supposed to put in there (for example &#039;&#039;I expand &amp;quot;(?P&amp;lt;nodetext&amp;gt;(?:[^&amp;quot;]|\\&amp;quot;)*)&amp;quot; node&#039;&#039;)&lt;br /&gt;
* Is recommended to use the static part of the regular expression as the name of the method, using underscores instead of spaces (see current steps definitions)&lt;br /&gt;
&lt;br /&gt;
== Links == &lt;br /&gt;
* Guidelines for contributors: [[Acceptance_testing/Contributing_automated_tests|Contributing automated tests]]&lt;br /&gt;
* Technical info: [[Behat integration]]&lt;br /&gt;
* Behat CLI command options: http://docs.behat.org/guides/6.cli.html&lt;br /&gt;
* How to use selectors to interact with the site elements: http://mink.behat.org/#traverse-the-page-selectors&lt;br /&gt;
* See Also [https://tracker.moodle.org/browse/MDL-37046 MDL37046] for clear instruction&lt;br /&gt;
[[Category:Behat]][[Category:Quality Assurance]]&lt;br /&gt;
&lt;br /&gt;
[[es:Prueba de aceptación]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Deprecation&amp;diff=43427</id>
		<title>Deprecation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Deprecation&amp;diff=43427"/>
		<updated>2013-12-17T03:35:01Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Step 1. Immediate action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is deprecation? ==&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Deprecation Deprecation], in its programming sense, is the process of taking older code and marking it as no longer being useful within the codebase, usually because it has been superseded by newer code. The deprecated code is not immediately removed from the codebase because doing so may cause regression errors.&lt;br /&gt;
&lt;br /&gt;
== Why is deprecation needed? ==&lt;br /&gt;
&lt;br /&gt;
In an open source project, the end use of the codebase varies. People may have customisations and plugins that depend on a function that has been targeted for deprecation. Rather than simply removing a function, we must gracefully deprecate the function over a period covered by a number of released versions.&lt;br /&gt;
&lt;br /&gt;
== Moodle Core deprecation process ==&lt;br /&gt;
&lt;br /&gt;
Once it is decided that a function should be deprecated, a two-step process should be followed.&lt;br /&gt;
&lt;br /&gt;
Note that both steps should always happen as earlier as possible in the 6-months period  between major releases, so all developers will have time to adjust their code and ensure it will work in the next release. Obviously, no changes will be allowed after code freeze (the APIs must remain 100% unmodified after it).&lt;br /&gt;
&lt;br /&gt;
=== Step 1. Immediate action ===&lt;br /&gt;
&lt;br /&gt;
Deprecation affects only the current master version, in other words, the deprecation only becomes affective after the next [[Releases|major release]].&lt;br /&gt;
&lt;br /&gt;
* If the function is not a member of a class (in other words, it is an independent function), it should be moved, with its PHPDoc and all comments, to &#039;&#039;lib/deprecationlib.php&#039;&#039;, which is included everywhere. If the function is a class member, it will need to be deprecated in its current location.&lt;br /&gt;
** Deprecated behat step definitions should be moved to lib/tests/behat/behat_deprecated.php, including a call to behat_deprecated::deprecated_message() proposing an alternative to the deprecated method.&lt;br /&gt;
* A debugging message should be added to the function so that, when [[:en:Debugging|developer debugging mode]] is on, attention is drawn to the deprecation. The message should state that the function being called has been deprecated. If the function has been replaced, the user should be directed to the alternative.&lt;br /&gt;
&lt;br /&gt;
 debugging(&#039;foobar() is deprecated, please use foobar::blah() instead.&#039;, DEBUG_DEVELOPER);&lt;br /&gt;
&lt;br /&gt;
* If the deprecated function has been replaced with a new function, ideally the new function should be called from the deprecated function, so that the new functionality is used. This will make maintenance easier moving forward.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@deprecated&amp;lt;/tt&amp;gt; tag should be added to the PHPDoc for the function description so that IDEs describing the function will note that it is deprecated, documenting which version it was deprecated in and the MDL issue associated with it. See the guidelines in [[Coding_style#.40deprecated]].&lt;br /&gt;
* There will need to be an issue associated with the initial part of the deprecation. A second issue needs to be created to finish the job. The first issue will be linked to second issue. The second issue needs to be a sub-task of an appropriate [http://tracker.moodle.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=summary+%7E+%22meta+AND+deprecation%22+order+by+created&amp;amp;runQuery=true&amp;amp;clear=true deprecation META]. For example, if the current version is 2.3.2, the function will be marked as deprecated in 2.4 and should normally be removed for 2.6, so the second issue should be a subtask of a deprecation META for the 2.6 version (MDL-34434). This second issue should include instructions on how to remove the function so that when it comes time to do so, the task is trivial for any developer.&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@todo&amp;lt;/tt&amp;gt; tag can be added linking to the issues created for further action. (optional)&lt;br /&gt;
* A &amp;lt;tt&amp;gt;@see&amp;lt;/tt&amp;gt; tag can be added to point to the new apis that can be used. (optional)&lt;br /&gt;
&lt;br /&gt;
Longer deprecation periods can be considered for functions that are widely used.&lt;br /&gt;
&lt;br /&gt;
=== Step 2. Final deprecation ===&lt;br /&gt;
&lt;br /&gt;
* If a function has been marked as deprecated for 2.x (eg. 2.4) and set for removal at 2.x+2 (eg. 2.6), soon after the release of 2.x+1.1 (eg. 2.5.1), the 2.x+2 deprecation META will be processed. This means that the deprecated function will be removed before 2.x+2, but only in the master version. This allows any potential regressions caused by the removal of the function to be exposed as soon as possible.&lt;br /&gt;
* All content of the function is removed and in the skeleton that remains,  an error statement should be included that reports that the function has been removed. You can direct developers to new function(s) in this message.&lt;br /&gt;
&lt;br /&gt;
 throw new coding_exception(&#039;check_potential_filename() can not be used any more, please use new file API&#039;);&lt;br /&gt;
&lt;br /&gt;
* The PHPDoc for the function should have &amp;lt;tt&amp;gt;@param&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;@return&amp;lt;/tt&amp;gt; tags removed to reduce the temptation for developers to consider using the function and make it obvious in IDEs that the function has been deprecated. The &amp;lt;tt&amp;gt;@deprecated&amp;lt;/tt&amp;gt; tag should remain. When feasible the description should be removed as well, &#039;&#039;&#039;but do not remove the information about what you should use instead of the deprecated function&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== See also... ==&lt;br /&gt;
&lt;br /&gt;
* [[Process]]&lt;br /&gt;
* [[Release process (Combined)|Release process]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Processes]]&lt;br /&gt;
[[Category:Core development]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43383</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43383"/>
		<updated>2013-12-09T04:20:40Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Behat extension */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind requests) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that all those examples are not necessarily real nor part of the suite, they are meant to help understand the concepts, see [[Acceptance_testing]] for real examples&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send requests to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending requests like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration creates a new moodle site installation in parallel to the production one to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives, which should be only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide within the Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We set $CFG-&amp;gt;behat_wwwroot in config.php and we are accessing the moodle instance through it&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are behat libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical steps descriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
* Add a new formatter method based on progress (the moodle default one) to display info about the moodle site being tested&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43382</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43382"/>
		<updated>2013-12-09T03:32:19Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Available steps to create tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind requests) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that all those examples are not necessarily real nor part of the suite, they are meant to help understand the concepts, see [[Acceptance_testing]] for real examples&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send requests to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending requests like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration creates a new moodle site installation in parallel to the production one to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives, which should be only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide within the Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We set $CFG-&amp;gt;behat_wwwroot in config.php and we are accessing the moodle instance through it&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are behat libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical steps descriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43381</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43381"/>
		<updated>2013-12-09T03:29:18Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Alternative environment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind requests) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that all those examples are not necessarily real nor part of the suite, they are meant to help understand the concepts, see [[Acceptance_testing]] for real examples&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send requests to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending requests like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration creates a new moodle site installation in parallel to the production one to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives, which should be only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide within the Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;behat_wwwroot, $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We set $CFG-&amp;gt;behat_wwwroot in config.php and we are accessing the moodle instance through it&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical stepsdescriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43380</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43380"/>
		<updated>2013-12-09T03:25:03Z</updated>

		<summary type="html">&lt;p&gt;Davmon: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind requests) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that all those examples are not necessarily real nor part of the suite, they are meant to help understand the concepts, see [[Acceptance_testing]] for real examples&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send requests to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending requests like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration uses the PHP 5.4 built-in web server to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide with Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We are accessing Moodle through the PHP 5.4 built-in web server, php_sapi_name() == &#039;cli-server&#039;&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical stepsdescriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43379</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43379"/>
		<updated>2013-12-09T03:23:45Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* How Behat works */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind petitions) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note that all those examples are not necessarily real nor part of the suite, they are meant to help understand the concepts, see [[Acceptance_testing]] for real examples&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send petitions to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending petitions like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration uses the PHP 5.4 built-in web server to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide with Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We are accessing Moodle through the PHP 5.4 built-in web server, php_sapi_name() == &#039;cli-server&#039;&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical stepsdescriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43378</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=43378"/>
		<updated>2013-12-09T03:20:24Z</updated>

		<summary type="html">&lt;p&gt;Davmon: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description, how to install it, run the suite and add more features, see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind petitions) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send petitions to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending petitions like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration uses the PHP 5.4 built-in web server to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives only accessible from localhost or internal networks. Info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings. More info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the behat CLI utilities we provide with Moodle codebase (admin/tool/behat/cli/*) are using $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of $CFG-&amp;gt;prefix and $CFG-&amp;gt;dataroot, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We are accessing Moodle through the PHP 5.4 built-in web server, php_sapi_name() == &#039;cli-server&#039;&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains its functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
[[File:Acceptance_testing_UI_2.5.png]]&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical stepsdescriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
* Look for exceptions, debugging() calls, PHP error messages and other backtraces in Moodle&#039;s output&lt;br /&gt;
* Extend the Selenium2 behat driver to allow extra Selenium capabilities&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:Behat]]&lt;br /&gt;
&lt;br /&gt;
[[es:Behat]]&lt;/div&gt;</summary>
		<author><name>Davmon</name></author>
	</entry>
</feed>