<?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=Sbourget</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=Sbourget"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Sbourget"/>
	<updated>2026-04-17T08:35:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58696</id>
		<title>Running acceptance test</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Running_acceptance_test&amp;diff=58696"/>
		<updated>2021-04-26T19:15:16Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: Updated chromedriver link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Short version ==&lt;br /&gt;
&lt;br /&gt;
...or how I got it to work on Ubuntu and some of the problems encountered. &lt;br /&gt;
&lt;br /&gt;
You need a bunch of browsers and terminal windows open to do this.&lt;br /&gt;
&lt;br /&gt;
==== 1. Background ====  &lt;br /&gt;
&lt;br /&gt;
# I am using the desktop version of Ubuntu 17.04 so there are no issues about running this software in headless mode. Running in headless mode was not tested.&lt;br /&gt;
# Moodle is version 3.3 and is a fully installed and working version using the &#039;standard&#039; Ubuntu LAMP stack.&lt;br /&gt;
&lt;br /&gt;
==== 2. Set up Selenium ====&lt;br /&gt;
First, you should have a look at [[Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium#Working_combinations_of_OS.2BBrowser.2Bselenium|working combinations of OS+Browser+selenium]].&lt;br /&gt;
&lt;br /&gt;
# Download the Selenium Standalone Server from [http://www.seleniumhq.org/download/ http://www.seleniumhq.org/download/]. It&#039;s a single JAR file, put it anywhere handy.&lt;br /&gt;
# Download the Chrome driver from [https://sites.google.com/chromium.org/driver/ https://sites.google.com/chromium.org/driver/]. Ensure you have the right version of the Chrome driver - see [[#Trouble_shooting| Trouble shooting]]. (Firefox is currently problematic. See [[Actual_Selenium_with_old_Firefox_47.0.1]] if you need to try to make it work.)&lt;br /&gt;
# Unzip the driver (it&#039;s a single file) and copy to /usr/local/bin (should work anywhere on the path)&lt;br /&gt;
# If not installed already, &#039;&amp;lt;tt&amp;gt;sudo apt install default-jre&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Start Selenium - &#039;&amp;lt;tt&amp;gt;java -jar /path/to/your/selenium/server/selenium-server-standalone-N.NN.N.jar -port 4444&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# check it works, access &#039;localhost:4444/wd/hub/&#039; in your browser and check you can create a new Chrome session.&lt;br /&gt;
&lt;br /&gt;
If running headless or the above doesn&#039;t work (&amp;quot;Selenium server is not running&amp;quot; when running the behat tests). Try the following&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;Xvfb -ac :99 -screen 0 1280x1024x16 &amp;amp;&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# Then immediately, &#039;&amp;lt;tt&amp;gt;export DISPLAY=:99&amp;lt;/tt&amp;gt;&#039;&lt;br /&gt;
# The run the Selenium command as above&lt;br /&gt;
&lt;br /&gt;
==== 3. Set up Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Create a new &#039;dataroot&#039; area for files especially for behat adjusting permissions accordingly. &lt;br /&gt;
# If not there already, add Section 11 from config-dist.php to your config.php file and review the settings. &lt;br /&gt;
# $CFG-&amp;gt;behat_wwwroot needs to point to your Moodle site yet be different from the &#039;normal&#039; wwwroot (e.g. if you used localhost for wwwroot use 127.0.0.1 for the behat_wwwroot). Whatever you choose, make sure it works. &lt;br /&gt;
# $CFG-&amp;gt;behat_dataroot should point to the directory you created above&lt;br /&gt;
# $CFG-&amp;gt;behat_prefix should be fine. &lt;br /&gt;
# Set up $CFG-&amp;gt;behat_profiles to select Chrome as the browser...&lt;br /&gt;
&lt;br /&gt;
     $CFG-&amp;gt;behat_profiles = [&lt;br /&gt;
         &#039;default&#039; =&amp;gt; [&lt;br /&gt;
             &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
             &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
                 &#039;Behat\MinkExtension&#039; =&amp;gt; [&lt;br /&gt;
                     &#039;selenium2&#039; =&amp;gt; [&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;
&lt;br /&gt;
==== 4. Configure Behat for Moodle ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;php admin/tool/behat/cli/init.php&amp;lt;/tt&amp;gt;&#039; (from the root of your Moodle install). This installs all the required software and creates the test version of Moodle. &lt;br /&gt;
&lt;br /&gt;
==== 5. Run Behat tests ====&lt;br /&gt;
&lt;br /&gt;
# Run &#039;&amp;lt;tt&amp;gt;vendor/bin/behat&amp;lt;/tt&amp;gt;&#039;. If you don&#039;t want to run all the tests add &#039;&amp;lt;tt&amp;gt;--tags=&amp;quot;@something&amp;quot;&amp;lt;/tt&amp;gt;&#039; where the @something refers to the tags at the top of most feature files. Use comma-separated list like &#039;&amp;lt;tt&amp;gt;@some_thing,@some_thing_else&amp;lt;/tt&amp;gt;&#039; to run tests from multiple areas. See upstream documentation on Gherkin filters for advanced syntax and more complex examples.&lt;br /&gt;
# After some initial setup dots should start to go by. It&#039;s a while before Selenium is first accessed. On the Linux desktop a new Chrome window appears and the testing process &#039;remote control&#039; starts (hopefully!)&lt;br /&gt;
# At the end of each line it shows you the number of steps that have completed so far.&lt;br /&gt;
#* If you are doing a full run, then as of November 2020 there are about 63,000 steps, which took around 25 hours to complete on one test machine (when not using the parallel running feature). Moodle HQ manage complete runs in ~5 hours on a well-optmised set-up, with 3 parallel workers.&lt;br /&gt;
&lt;br /&gt;
== Prerequisite ==&lt;br /&gt;
Before initializing acceptance test environment for running behat, you should ensure:&lt;br /&gt;
# [[Acceptance_testing#Requirements Meet min. system requirements for running tests]]&lt;br /&gt;
# [[Acceptance_testing#Installation Have set min. config variable in config.php for behat]]&lt;br /&gt;
# [[Acceptance_testing#Installation Downloaded composer dependencies]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
Acceptance tests (also known as behat), use [http://www.seleniumhq.org/download/ Selenium server] and can be run as:&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; In single run, only one behat run is executed. So all features are executed in this single run.&lt;br /&gt;
# &#039;&#039;&#039;Parallel runs:&#039;&#039;&#039; (Since Moodle 3.0) Parallel runs allow dev&#039;s to execute multiple behat runs together. This was introduced to get acceptance tests results faster. To achieve this:&lt;br /&gt;
#* Features are divided between multiple behat runs&lt;br /&gt;
#* Symlinks behatrun{x} (x being the run process number), are created pointing to moodle directory, so site for run 1 is accessible via https://localhost/moodle/behatrun1&lt;br /&gt;
#* Process number is included as suffix to $CFG-&amp;gt;behat_prefix.&lt;br /&gt;
#* Process number is suffixed to $CFG-&amp;gt;behat_dataroot.&lt;br /&gt;
&lt;br /&gt;
== Step 1: Initialise acceptance test environment ==&lt;br /&gt;
Before running acceptance tests, environment needs to be initialised for acceptance testing.&lt;br /&gt;
&lt;br /&gt;
=== Single run ===&lt;br /&gt;
For initialising acceptance tests for single run, above command is sufficient.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For initialising acceptance tests for parallel runs, you can use one of the following options&lt;br /&gt;
# &#039;&#039;&#039;-j=&amp;lt;number&amp;gt; or --parallel=&amp;lt;number&amp;gt;&#039;&#039;&#039; (required) Number of parallel behat run to initialise&lt;br /&gt;
# &#039;&#039;&#039;-m=&amp;lt;number&amp;gt; or --maxruns=&amp;lt;number&amp;gt;&#039;&#039;&#039;  (optional) Max parallel site which should be initialised at one time. If your system is slow, then you can initialise sites in chucks.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run from. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;--torun=&amp;lt;number&amp;gt;&#039;&#039;&#039; (optional) Initialise site to run specified run till. Used for running acceptance tests on different vms&lt;br /&gt;
# &#039;&#039;&#039;-o or --optimize-runs&#039;&#039;&#039; (optional) This option will split features with specified tags in all parallel runs, so they are executed first when parallel run gets executed.&lt;br /&gt;
# &#039;&#039;&#039;-a=&amp;lt;name&amp;gt; or --add-core-features-to-theme=&amp;lt;name&amp;gt;&#039;&#039;&#039; (optional) Since Moodle 3.2. Use this option to add all core features to specified themes (comma separated list of themes)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
// Below command will initialise moodle to run 2 parallel tests.&lt;br /&gt;
php admin/tool/behat/cli/init.php --parallel=2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step 2: Running acceptance test environment ==&lt;br /&gt;
=== Single run ===&lt;br /&gt;
Run either of the following commands. 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;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You almost always want to limit the number of tests that are run. To run all the tests in one plugin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml --tags mod_myplugin&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run all the tests in one .feature file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To run a single scenario:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --config /path/to/your/CFG_behat_dataroot/behatrun/behat/behat.yml /path/to/moodle/mod/myplugin/tests/behat/testsomething.feature:40&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, &#039;40&#039; is the line-number of the feature file where the Scenario starts.&lt;br /&gt;
&lt;br /&gt;
=== Parallel runs ===&lt;br /&gt;
For running parallel runs, use following command&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/run.php&lt;br /&gt;
&lt;br /&gt;
Following optional options are available for custom run:&lt;br /&gt;
# &#039;&#039;&#039;--feature&#039;&#039;&#039; Only execute specified feature file (Absolute path of feature file).&lt;br /&gt;
# &#039;&#039;&#039;--suite&#039;&#039;&#039; Features for specified theme will be executed.&lt;br /&gt;
# &#039;&#039;&#039;--replace&#039;&#039;&#039; Replace args string with run process number, useful for output and reruns.&lt;br /&gt;
# &#039;&#039;&#039;--fromrun&#039;&#039;&#039; Execute run starting from (Used for parallel runs on different vms)&lt;br /&gt;
# &#039;&#039;&#039;--torun&#039;&#039;&#039; Execute run till (Used for parallel runs on different vms)&lt;br /&gt;
# Behat options can be passed for filtering features/scenarios:&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;--tags=&amp;quot;~@javascript&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific scenario, use the Behat name option to run it, &#039;&#039;&#039;--name=&amp;quot;Filter user accounts by role and cohort&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
#* In case you want to run specific feature file, use the Behat feature option to run it, &#039;&#039;&#039;--feature=&amp;quot;/PATH/TO/MOODLE/admin/tests/behat/filter_users.feature&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example: Initialise and run Behat tests for a custom plugin under a custom theme:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/behat/cli/init.php --parallel=3 --add-core-features-to-theme=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
 php admin/tool/behat/cli/run.php --tags=&amp;quot;@tool_myplugin&amp;quot; --suite=&amp;quot;mytheme&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Common options for running tests ===&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; iframe&#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;
Since Moodle 3.1 option for output is:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=pretty --out=/path/to/pretty.txt --format=moodle_progress --out=std&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Before Moodle 3.1 option for output was:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
--format=&#039;moodle_progress,pretty&#039; --out=&#039;,/path/to/pretty.txt&#039;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Following output formats are supported:&lt;br /&gt;
# &#039;&#039;&#039;progress&#039;&#039;&#039;: Prints one character per step.&lt;br /&gt;
# &#039;&#039;&#039;pretty&#039;&#039;&#039;: Prints the feature as is.&lt;br /&gt;
# &#039;&#039;&#039;junit&#039;&#039;&#039;: Outputs the failures in JUnit compatible files.&lt;br /&gt;
# &#039;&#039;&#039;moodle_progress&#039;&#039;&#039;: Prints Moodle branch information and dots for each step.&lt;br /&gt;
# &#039;&#039;&#039;moodle_list&#039;&#039;&#039;: List all scenarios.&lt;br /&gt;
# &#039;&#039;&#039;moodle_stepcount&#039;&#039;&#039;: List all features with total steps in each feature file. Used for parallel run.&lt;br /&gt;
# &#039;&#039;&#039;moodle_screenshot&#039;&#039;&#039;: (since Moodle 3.1) Take screenshot and core dump of each step. With following options you can dump either or both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;image&amp;quot;}&#039;**: will dump image only&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;}&#039;**: will dump html only.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html,image&amp;quot;}&#039;**: will dump both.&lt;br /&gt;
## --format-settings &#039;{&amp;quot;formats&amp;quot;: &amp;quot;html&amp;quot;, &amp;quot;dir_permissions&amp;quot;: &amp;quot;0777&amp;quot;}&#039;**&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. Format &#039;pretty&#039; (&#039;&#039;&#039;-f pretty&#039;&#039;&#039;) is sufficient for most cases, as it outputs each step outcomes in the command line making easier to see the progress.&lt;br /&gt;
&lt;br /&gt;
== Advance usage ==&lt;br /&gt;
=== Rerun failed scenarios ===&lt;br /&gt;
With slow systems or parallel run you might see some random failures, to rerun only failed scenarios (to eliminate random failures), use --rerun option&lt;br /&gt;
# &#039;&#039;&#039;Single run:&#039;&#039;&#039; --run=&amp;quot;absolute_path_to_empty_file&amp;quot; (Behat will record failed scenarios in this file, and when run again only failed scenarios will be run)&lt;br /&gt;
# &#039;&#039;&#039;Parallel run:&#039;&#039;&#039; --rerun=&amp;quot;absolute_path_to_empty_file_{runprocess}.txt --replace=&amp;quot;{runprocess}&amp;quot; ({runprocess} will be replaced with the process number for recording fails in the specific run process).&lt;br /&gt;
&#039;&#039;&#039;Since Moodle 3.1 --rerun option don&#039;t accept any value, as it is handled internally by behat&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Running behat with specified theme (Since Moodle 3.2) ===&lt;br /&gt;
You can run behat with any theme installed. To execute behat with specified theme use &#039;&#039;&#039;--suite=[classic | customtheme ]&#039;&#039;&#039; option, while running behat. By default the features in theme behat folder will be executed for the suite. But if you want to run all core features with the specific theme then initialise acceptance test with --add-core-features-to-theme={THEME_NAME}, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/init.php --add-core-features-to-theme=clean&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first time init runs can be time consuming as it creates a paralell set of tables to core, i.e. bh_user,bh_assign etc. After init the tests can be run with the alternative theme as follows.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
vendor/bin/behat --suite=classic --tags=&amp;quot;@enrol_foobar&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If there is no --suite= parameter it will fall back to the default boost theme.  No = or quotes needed around the theme name.&lt;br /&gt;
&lt;br /&gt;
Make sure that &amp;lt;tt&amp;gt;$CFG-&amp;gt;theme&amp;lt;/tt&amp;gt; is &#039;&#039;&#039;not set&#039;&#039;&#039; in your config.php.&lt;br /&gt;
&lt;br /&gt;
==== Override behat core context for theme suite ====&lt;br /&gt;
To override behat step definitions so as to run behat with specified theme, you should create a contexts within &#039;&#039;&#039;/theme/{MYTHEME}/tests/behat/&#039;&#039;&#039; with prefix behat_theme_{MYTHEME}_ and suffixed with the context being overridden. For example, if you want to override behat_mod_forum context, then you should create a class /theme/{MYTHEME}/tests/behat/mod_forum/behat_theme_{MYTHEME}_behat_mod_forum.php&lt;br /&gt;
&lt;br /&gt;
==== Blacklist behat context or features to run in theme suite ====&lt;br /&gt;
To blacklist contexts/ features to be executed by theme suite you should create a /theme/{MYTHEME}/tests/behat/blacklist.json file with following format. Following will not use step_definitions from  behat_grade and behat_navigation while running theme suite. Also, scenarios in auth/tests/behat/login.feature and grade/tests/behat/grade_hidden_items.feature won&#039;t be executed with theme suite.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;contexts&amp;quot;: [&lt;br /&gt;
    &amp;quot;behat_grade&amp;quot;,&lt;br /&gt;
    &amp;quot;behat_navigation&amp;quot;,&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;features&amp;quot;: [&lt;br /&gt;
    &amp;quot;auth/tests/behat/login.feature&amp;quot;,&lt;br /&gt;
    &amp;quot;grade/tests/behat/grade_hidden_items.feature&amp;quot;,&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Override core behat selectors ====&lt;br /&gt;
To override behat selectors in specific theme, you should create a class behat_theme_{MYTHEME}_behat_selectors in /theme/{MYTHEME}/tests/behat/behat_theme_{MYTHEME}_behat_selectors.php extending behat_selectors.&lt;br /&gt;
&lt;br /&gt;
=== Use php built in web server ===&lt;br /&gt;
You can use php built-in-web server for executing behat runs. To do so:&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;
# Update $CFG-&amp;gt;behat_wwwroot = localhost:8000; in config.php&lt;br /&gt;
&lt;br /&gt;
=== Define custom options for parallel runs ===&lt;br /&gt;
You can set following custom config options for parallel runs via $CFG-&amp;gt;behat_parallel_run. It&#039;s an array of options where 1st array is for 1st run and so on.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
       array (&lt;br /&gt;
           &#039;dbtype&#039; =&amp;gt; &#039;mysqli&#039;,&lt;br /&gt;
           &#039;dblibrary&#039; =&amp;gt; &#039;native&#039;,&lt;br /&gt;
           &#039;dbhost&#039; =&amp;gt; &#039;localhost&#039;,&lt;br /&gt;
           &#039;dbname&#039; =&amp;gt; &#039;moodletest&#039;,&lt;br /&gt;
           &#039;dbuser&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;dbpass&#039; =&amp;gt; &#039;moodle&#039;,&lt;br /&gt;
           &#039;behat_prefix&#039; =&amp;gt; &#039;mdl_&#039;,&lt;br /&gt;
           &#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;,&lt;br /&gt;
           &#039;behat_wwwroot&#039; =&amp;gt; &#039;http://127.0.0.1/moodle&#039;,&lt;br /&gt;
           &#039;behat_dataroot&#039; =&amp;gt; &#039;/home/example/bht_moodledata&#039;&lt;br /&gt;
       )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To set different selenium servers for parallel runs, you can use following. NOTE: Running parallel (headless) runs on different selenium servers avoid random focus failures.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    $CFG-&amp;gt;behat_parallel_run = array (&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4444/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4445/wd/hub&#039;),&lt;br /&gt;
        array (&#039;wd_host&#039; =&amp;gt; &#039;http://127.0.0.1:4446/wd/hub&#039;),&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Write new tests and behat methods ===&lt;br /&gt;
&lt;br /&gt;
If you want to write tests for your own integration, you can do so by creating new tests with format .feature. Follow instructions in [[Writing_acceptance_tests|this page]] to write new tests. &lt;br /&gt;
&lt;br /&gt;
It is also possible to add new steps the moodle behat integration. In order to do so, you will have to create a new .php class with the prefix &#039;&#039;&#039;behat_&#039;&#039;&#039;. Copy the format from &#039;&#039;&#039;lib\behat\behat_base.php&#039;&#039;&#039;, but set your class to extend the behat_base class instead of the MinkExtension. You can define new behat steps by declaring functions with the appropriate heading. &lt;br /&gt;
&lt;br /&gt;
You will not be  able to use these steps and features right away. Check [[Running_acceptance_test#New_step_definitions_or_features_are_not_executed|this section]] for instructions on how to update the behat integration. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For further information on how to create new steps definitions, check [[Acceptance testing/Custom acceptance steps]].&lt;br /&gt;
&lt;br /&gt;
=== Running acceptance tests with different browser ===&lt;br /&gt;
&lt;br /&gt;
If you follow the steps above, Behat will run with Chrome.&lt;br /&gt;
&lt;br /&gt;
You can get it to run with other browsers. The basic idea is to expand the $CFG-&amp;gt;behat_profiles array in config.php to list more browsers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_profiles = array(&lt;br /&gt;
   &#039;chrome&#039; =&amp;gt; array(&lt;br /&gt;
       &#039;browser&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
       &#039;tags&#039; =&amp;gt; &#039;@javascript&#039;,&lt;br /&gt;
   )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Acceptance_testing/Browsers|More info about alternative browsers]]&lt;br /&gt;
&lt;br /&gt;
=== Start multiple selenium servers ===&lt;br /&gt;
From command line Start selenium servers at different ports (say 4444, 4445, 4446 for 3 parallel runs)&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4444 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4445 &amp;amp;&lt;br /&gt;
java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port 4446&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternative way of running three Selenium servers in parallel:&lt;br /&gt;
&lt;br /&gt;
 $ printf %d\\n {4444..4446} | xargs -n 1 -P 3 java -jar /path/to/your/selenium/server/selenium-server-standalone-2.NN.N.jar -port&lt;br /&gt;
&lt;br /&gt;
=== Run tests directly in Chrome, with no Selenium ===&lt;br /&gt;
&lt;br /&gt;
Historically, the tests would talk to a Selenium server, which would then tell the target browser what to do. More and more, the browsers themselves contain such a server and you can talk to them directly, which is faster and easier. Work was done to get this working with Chrome in MDL-58948, but it still needs some further setup to get it working, which is detailed in the bug ticket, and which I&#039;ll copy below:&lt;br /&gt;
&lt;br /&gt;
Replace your current behat config with the abve, the api_url is where you&#039;ll talk directly to your Chrome browser.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_config = [&lt;br /&gt;
    &#039;default&#039; =&amp;gt; [&lt;br /&gt;
        &#039;extensions&#039; =&amp;gt; [&lt;br /&gt;
            &#039;DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension&#039; =&amp;gt; [],&lt;br /&gt;
            &#039;Behat\MinkExtension&#039;                                          =&amp;gt; [&lt;br /&gt;
                &#039;browser_name&#039; =&amp;gt; &#039;chrome&#039;,&lt;br /&gt;
                &#039;base_url&#039;     =&amp;gt; $CFG-&amp;gt;behat_wwwroot,&lt;br /&gt;
                &#039;goutte&#039;       =&amp;gt; null,&lt;br /&gt;
                &#039;selenium2&#039;    =&amp;gt; null,&lt;br /&gt;
                &#039;sessions&#039;     =&amp;gt; [&lt;br /&gt;
                    &#039;javascript&#039; =&amp;gt; [&lt;br /&gt;
                        &#039;chrome&#039; =&amp;gt; [&lt;br /&gt;
                            &#039;api_url&#039; =&amp;gt; &#039;http://localhost:9222&#039;&lt;br /&gt;
                        ]&lt;br /&gt;
                    ]&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;
Use composer to install two more required libraries:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
composer require --dev dmore/behat-chrome-extension&lt;br /&gt;
composer require --dev dmore/chrome-mink-driver&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you try to run the tests it will tell you that Chrome isn&#039;t running, in a second tab run the following to start Chrome (or chromium-browser on Ubuntu)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;chrome --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is running headless so you won&#039;t see any windows pop up as the tests run, though it runs in the other mode too.&lt;br /&gt;
&lt;br /&gt;
Behat should now run as before, but faster.&lt;br /&gt;
&lt;br /&gt;
==== Run Chrome locally with Behat and Moodle on a remote server ====&lt;br /&gt;
If you have Moodle running on a remote (headless) server, but don&#039;t want to install a window manager, you can do the following:&lt;br /&gt;
&lt;br /&gt;
1. Go through all the steps from above&lt;br /&gt;
&lt;br /&gt;
2. Establish an SSH SOCKS5 proxy connection to your server:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C USER@SERVER&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Forward the port to connect to the DevTools-API of your browser:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C&amp;lt;/code&amp;gt;&lt;br /&gt;
4. Tell your local Chrome to use custom settings:&lt;br /&gt;
&amp;lt;code&amp;gt;/path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, all in one command:&lt;br /&gt;
&amp;lt;code&amp;gt;ssh -D VARIABLE-PORT-A -N -q -C -f USER@SERVER &amp;amp;&amp;amp; ssh -R VARIABLE-PORT-B:localhost:VARIABLE-PORT-B USER@SERVER -N -q -C -f &amp;amp;&amp;amp; /path/to/Google\ Chrome [--disable-gpu] --remote-debugging-address=0.0.0.0 --remote-debugging-port=VARIABLE-PORT-B --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation for the SSH settings:&lt;br /&gt;
* VARIABLE-PORT-B &amp;amp; VARIABLE-PORT-A : Choose these as you like. Bear in mind that you will need root rights if the port number is 1023 or lower&lt;br /&gt;
* -N: Tells SSH not to open an actual command prompt&lt;br /&gt;
* -C: Compress all data passed through the tunnel&lt;br /&gt;
* -q: Quiet mode. Causes most warning and diagnostic messages to be suppressed&lt;br /&gt;
*-R: Open a tunnel binding to localhost on the remote machine, going to localhost on the local machine&lt;br /&gt;
* -f: Fork the process into background&lt;br /&gt;
&lt;br /&gt;
Explanation for the Chrome settings:&lt;br /&gt;
* --proxy-bypass-list=&#039;&amp;lt;-loopback&amp;gt;&#039; : Tells Chrome to send requests to localhost through the tunnel&lt;br /&gt;
* --proxy-server=socks://127.0.0.1:VARIABLE-PORT-A : To use the SOCKS5 tunnel we just set up&lt;br /&gt;
* --remote-debugging-port=VARIABLE-PORT-B &amp;amp; --remote-debugging-address=0.0.0.0 : To use the SSH tunnel we just set up&lt;br /&gt;
&lt;br /&gt;
=== Using Docker to start selenium server ===&lt;br /&gt;
==== What is Docker ====&lt;br /&gt;
Docker is a app container,  it&#039;s a kind of virtual machine, but only for one app, service,  so you can download&lt;br /&gt;
a docker image and run a selenium server without worry in how to configure selenium in your machine, one for chrome, others for firefox, you either don&#039;t need to install the browsers in your machine&lt;br /&gt;
To install docker follow this link; https://docs.docker.com/engine/installation/&lt;br /&gt;
&lt;br /&gt;
==== Selenium docker images ====&lt;br /&gt;
There is many docker images available,  for many browser, the complete list is in https://hub.docker.com/u/selenium/&lt;br /&gt;
for moodle you can use standalone version.&lt;br /&gt;
You can download  specific selenium version too,  for example,  for firefox,  moodle recommend selenium 2.53.1, see: [https://docs.moodle.org/dev/Acceptance_testing/Browsers/Working_combinations_of_OS%2BBrowser%2Bselenium What version do I need?]&lt;br /&gt;
&lt;br /&gt;
so  the command will be:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
docker run -d -p4444:4444 selenium/standalone-firefox:2.53.1-beryllium&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
to see all available version click in tags.   For firefox you can find at: https://hub.docker.com/r/selenium/standalone-firefox/tags/&lt;br /&gt;
&lt;br /&gt;
==== Change config.php file ====&lt;br /&gt;
In config.php file you must change the $CFG-&amp;gt;behat_wwwroot=   to your network card (NIC) ip address,  you can&#039;t use &lt;br /&gt;
localhost , 127.0.0.1, ...  or selenium docker server  will fail&lt;br /&gt;
&lt;br /&gt;
=== Increasing timeouts ===&lt;br /&gt;
&lt;br /&gt;
You may see errors such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Javascript code and/or AJAX requests are not ready after 10 seconds. &lt;br /&gt;
There is a Javascript error or the code is extremely slow.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sometimes this indicates a genuine problem with the code, but if you are using a slow computer, it could just mean that the browser was not yet ready. You may find that the test works if you run it again. If you get this error frequently, it might be useful to increase the timeout.&lt;br /&gt;
&lt;br /&gt;
It is possible to increase this timeout by adding a line in your config.php. (Requires Moodle versions 3.5 (from 3.5.6), 3.6 (from 3.6.4), or 3.7+.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;behat_increasetimeout = 2;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will increase all the timeouts by a factor of 2; if that isn&#039;t sufficient, you could use 3. &lt;br /&gt;
&lt;br /&gt;
Increasing timeouts will make tests run a bit slower (because there are points where Behat waits up to a timeout to make sure something doesn&#039;t happen) so don&#039;t do this unless you need to.&lt;br /&gt;
&lt;br /&gt;
== NOTE ==&lt;br /&gt;
# 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;
&lt;br /&gt;
=== Disable acceptance test environment ===&lt;br /&gt;
if you want to prevent access to test environment&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --disable&lt;br /&gt;
&amp;lt;/code&amp;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;
== Trouble shooting ==&lt;br /&gt;
&lt;br /&gt;
=== New step definitions or features are not executed === &lt;br /&gt;
If you are adding new tests or steps definitions update the tests list&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
php admin/tool/behat/cli/util.php --enable&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; For parallel runs, all options for initialising parallel runs are valid &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Tests are failing ===&lt;br /&gt;
&lt;br /&gt;
If you followed all the steps and you receive an unknown weird error probably your browser version is not compatible with the Selenium version you are running.  Please refer Working combinations to ensure you have correct [[Acceptance_testing/Browsers#Working_combinations_of_OS.2BBrowser.2Bselenium]] of them to run acceptance test.&lt;br /&gt;
&lt;br /&gt;
=== The tests are failing, and the error message is completely useless ===&lt;br /&gt;
&lt;br /&gt;
For example, it just says &amp;quot;Error writing to database&amp;quot; with no stack trace.&lt;br /&gt;
&lt;br /&gt;
Add -vv command-line option to get very verbose output.&lt;br /&gt;
&lt;br /&gt;
=== Errors during setup (before test are launched) ===&lt;br /&gt;
Typical errors are:&lt;br /&gt;
* Behat requirement not satisfied: http://127.0.0.1/m/stable_master is not available, ensure you specified correct url and that the server is set up and started.&lt;br /&gt;
* Behat is configured but not enabled on this test site.&lt;br /&gt;
&lt;br /&gt;
In order to fix those errors please check that: the behat_dataroot has correct write permissions and that the $CFG-&amp;gt;behat* variables are placed before the lib/setup.php include:&lt;br /&gt;
 require_once(__DIR__ . &#039;/lib/setup.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Selenium server is not running ===&lt;br /&gt;
==== Chrome specific ====&lt;br /&gt;
&lt;br /&gt;
If you are using chrome, you need to ensure that the driver matches the version of the installed chrome browser – which may change on OS updates/upgrades.  Moodle or Selenium will not give the appropriate message – see [https://tracker.moodle.org/browse/MDL-67659/ MDL-67659].  One solution is the one suggested in the issue and use Andrew Nicols’ [https://github.com/andrewnicols/chromedriver-wrapper/  Chromedriver Wrapper] which will ensure you have the appropriate driver before running the tests.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
* Vagrant profile with Moodle and Behat preconfigured: https://github.com/mackensen/moodle-hat&lt;br /&gt;
* Docker containers for Moodle Developers and Behat: https://github.com/moodlehq/moodle-docker&lt;br /&gt;
* Docker environment with Behat preconfigured : https://github.com/tobiga/docker_moodle_environment&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Acceptance testing for the mobile app]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Quality Assurance]][[Category:Behat]]&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Authentication_plugins&amp;diff=52324</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Authentication_plugins&amp;diff=52324"/>
		<updated>2017-05-09T18:08:45Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
This page first gives an &#039;&#039;&#039;overview&#039;&#039;&#039; of the &#039;&#039;authentication process&#039;&#039; and then explains how &#039;&#039;authentication modules&#039;&#039; can be &#039;&#039;&#039;created&#039;&#039;&#039; using hooks to take over from the native authentication in Moodle.&lt;br /&gt;
=== Overview of Moodle authentication process ===&lt;br /&gt;
[[File:1.9.11_login_element.png|203px||thumb|right|The login UI element in Moodle 1.9]]The authentication use case in Moodle starts when a user clicks on the Login link in the UI or if they try to access a protected page. There are two broad classes of authentication plugins, the regular type where moodle handles the password and ones where the password is handled by a 3rd party page eg SAML, OpenID etc.&lt;br /&gt;
&lt;br /&gt;
For the regular plugins the following happens (skipping some minor details and rarer scenarios):&lt;br /&gt;
&lt;br /&gt;
# The default login page (&amp;lt;tt&amp;gt;/login/index.php&amp;lt;/tt&amp;gt;) is displayed. OR, if a system administrator has set the Alternate Login URL on the &amp;quot;Manage authentication&amp;quot; page, that URL will be displayed.&lt;br /&gt;
# A user enters their credentials and submits the form.&lt;br /&gt;
# The handler code in &amp;lt;tt&amp;gt;/login/index.php&amp;lt;/tt&amp;gt; runs:&lt;br /&gt;
## Gets a list of enabled authentication plugins.&lt;br /&gt;
## Runs &amp;lt;tt&amp;gt;loginpage_hook()&amp;lt;/tt&amp;gt; for each plugin, in case any of them needs to intercept the login request.&lt;br /&gt;
## Checks to make sure that the username meets Moodle&#039;s criteria (alphanumeric, with periods and hyphens allowed).&lt;br /&gt;
## Calls &amp;lt;tt&amp;gt;authenticate_user_login()&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;/lib/moodlelib.php&amp;lt;/tt&amp;gt;, which returns a &amp;lt;code&amp;gt;$user&amp;lt;/code&amp;gt; object. (Details of this code follow this main outline.)&lt;br /&gt;
## Determines whether authentication was successful (by checking whether &amp;lt;code&amp;gt;$user&amp;lt;/code&amp;gt; is a valid object) and, if not, sends them back to the login page with an error message. Otherwise, it figures out where to send the user based on their original page request, whether their password is expired, etc., and redirects them there.&lt;br /&gt;
&lt;br /&gt;
For the 3rd party auth plugins the process could look like this (eg CAS, SAML, OpenID etc):&lt;br /&gt;
# Access a protected page but isn&#039;t logged in, so moodle calls &amp;lt;tt&amp;gt;pre_loginpage_hook()&amp;lt;/tt&amp;gt; on each enabled plugin, which may redirect to the 3rd party login page&lt;br /&gt;
# Or if they go directly to the login page moodle calls &amp;lt;tt&amp;gt;loginpage_hook()&amp;lt;/tt&amp;gt; on each enabled plugin, which may redirect to the 3rd party login page&lt;br /&gt;
# The user enters their credentials and authenticates on the 3rd party page&lt;br /&gt;
# The remote authentication service redirects back to moodle with an assertion, such as a single use token or encrypted response in a query param&lt;br /&gt;
# The auth plugin now validates the token or decrypts the assertion, does any other checking as required and then logs the user in using &amp;lt;tt&amp;gt;complete_user_login($user)&amp;lt;/tt&amp;gt;. If this happens inside &amp;lt;tt&amp;gt;pre_loginpage_hook()&amp;lt;/tt&amp;gt; then the user continues on their way, or if inside &amp;lt;tt&amp;gt;loginpage_hook()&amp;lt;/tt&amp;gt; or another custom page then the plugin should redirect to the wantsurl.&lt;br /&gt;
&lt;br /&gt;
Note that in this scenario above &amp;lt;tt&amp;gt;user_login($username, $password)&amp;lt;/tt&amp;gt; is never called and should probably return false.&lt;br /&gt;
&lt;br /&gt;
==History==&lt;br /&gt;
Authentication plugins exist from 1.9&lt;br /&gt;
==Example==&lt;br /&gt;
[http://moodle.org/plugins/view.php?plugin=auth_googleoauth2 Google / Facebook / Messenger Oauth2 Authentication plugin]&lt;br /&gt;
&lt;br /&gt;
==Template==&lt;br /&gt;
Please see Moodle &#039;&#039;&#039;none&#039;&#039;&#039; authentication plugin (auth/none), it&#039;s the perfect plugin template to start with.&lt;br /&gt;
&lt;br /&gt;
==Naming convention==&lt;br /&gt;
==File structure==&lt;br /&gt;
# Choose a name for your plugin.  We&#039;ll use &#039;sentry&#039; as an example below; change it to whatever name you have chosen.&lt;br /&gt;
# Under your Moodle installation root, create the directory &amp;lt;tt&amp;gt;/auth/sentry&amp;lt;/tt&amp;gt;.  It should be sibling to existing auth plugin directories: &#039;db&#039;, &#039;nologin&#039;, &#039;none&#039;, etc.&lt;br /&gt;
# Create the file &amp;lt;tt&amp;gt;/auth/sentry/auth.php&amp;lt;/tt&amp;gt;.  Within the file, create a class &amp;lt;tt&amp;gt;auth_plugin_sentry&amp;lt;/tt&amp;gt; that extends &amp;lt;tt&amp;gt;auth_plugin_base&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;/lib/authlib.php&amp;lt;/tt&amp;gt;.  (You will need to &amp;lt;code&amp;gt;require_once&amp;lt;/code&amp;gt; the authlib file.)&lt;br /&gt;
# Implement the &amp;lt;tt&amp;gt;user_login()&amp;lt;/tt&amp;gt; function in your &amp;lt;tt&amp;gt;auth.php&amp;lt;/tt&amp;gt; file, and create or override additional functions based on your plugin&#039;s requirements.&lt;br /&gt;
# Log in to your Moodle installation as a site administrator and find, in the site administrator block, the page &amp;quot;Users -&amp;gt; Authentication -&amp;gt; Manage authentication&amp;quot;.  You will see your plugin in the list, appearing as &amp;lt;nowiki&amp;gt;[[auth_sentrytitle]]&amp;lt;/nowiki&amp;gt;.  You can enable it and move it up and down in the order.  &#039;&#039;&#039;At this point, with the plugin enabled, your plugin is registered and will be used by Moodle in its authentication process.&#039;&#039;&#039;&lt;br /&gt;
# If you don&#039;t like seeing &amp;lt;nowiki&amp;gt;[[auth_sentrytitle]]&amp;lt;/nowiki&amp;gt; as the name of your plugin in the Moodle UI, you&#039;ll need to create language files for your plugin.  Do this by creating the directory &amp;lt;tt&amp;gt;/auth/sentry/lang&amp;lt;/tt&amp;gt;, and under it, a directory for each language that your installation needs to support.  (Example: &amp;lt;tt&amp;gt;/auth/sentry/lang/en&amp;lt;/tt&amp;gt;.)  Within each of these language directories, create a file called &amp;lt;tt&amp;gt;auth_sentry.php&amp;lt;/tt&amp;gt;.  That file should set the desired value for &amp;lt;code&amp;gt;$string[&#039;auth_sentrytitle&#039;] for that language (use $string[&#039;pluginname&#039;] for Moodle2)&amp;lt;/code&amp;gt;.  You can also set the plugin description by setting &amp;lt;code&amp;gt;$string[&#039;auth_sentrydescription&#039;]&amp;lt;/code&amp;gt;, and you can also assign other translatable strings that your plugin uses, in these files.  &#039;&#039;&#039;Note:&#039;&#039;&#039; A folder named like &#039;&#039;&#039;en&#039;&#039;&#039; may not work for everyone. Please refer to the lang folder under your moodle installation directory to get an idea about the language/locale codes used in your moodle installation. For example, the lang folder in own users system contained folders named &#039;&#039;&#039;en&#039;&#039;&#039; and &#039;&#039;&#039;zh-cn&#039;&#039;&#039;. He emulated the same in the lang folder of the auth plugin and the plugin picked up the title and description strings immediately. ([[Places_to_search_for_lang_strings|More info on how Moodle handles language]]).&lt;br /&gt;
# If you want to configure your plugin through the Moodle UI, implement &amp;lt;tt&amp;gt;config_form()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;process_config()&amp;lt;/tt&amp;gt; in the plugin class.  You might find it convenient to use the &#039;db&#039; plugin as a model for this.  The plugin&#039;s config settings can then be managed through the Manage authentication page by clicking on the Settings link for that plugin, and the values will be stored in the &amp;lt;tt&amp;gt;mdl_config_plugins&amp;lt;/tt&amp;gt; table in the database.&lt;br /&gt;
&lt;br /&gt;
==Interfacing to API&#039;s==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;authenticate_user_login()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
That&#039;s the main outline, but a lot of interesting stuff happens in &amp;lt;tt&amp;gt;authenticate_user_login()&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
# It gets a list of enabled authentication plugins.&lt;br /&gt;
# It looks up the username in the mdl_user table to see if they are allowed to log in, and which authentication plugin handles their login requests. (This will be the plugin that handled their first-ever login request.)&lt;br /&gt;
# It creates a user object, which will contain the data from &amp;lt;tt&amp;gt;mdl_user&amp;lt;/tt&amp;gt; if the username is known; if not, it will be an empty object.&lt;br /&gt;
# It does the following with the authentication plugin (note that for a username unknown to Moodle, it will do these steps for each authenticated plugin until one succeeds or it has tried them all):&lt;br /&gt;
## Calls the &amp;lt;tt&amp;gt;user_login()&amp;lt;/tt&amp;gt; function provided by that plugin, which returns a boolean value based on whether the credentials authenticate or not. If the result is false (not authenticated), skips the rest of the steps below and continues to the next plugin.&lt;br /&gt;
## If the plugin authenticates against an external system (not Moodle&#039;s user database), its &amp;lt;tt&amp;gt;update_user_record()&amp;lt;/tt&amp;gt; function is called to get the user&#039;s name, contact info, etc.&lt;br /&gt;
## Creates the Moodle user record if it doesn&#039;t already exist.&lt;br /&gt;
## Calls the plugin&#039;s &amp;lt;tt&amp;gt;sync_roles()&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
## Notifies each enabled authentication plugin that the user successfully authenticated, by calling each one&#039;s &amp;lt;tt&amp;gt;user_authenticated_hook()&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
# It returns the user object if everything was successful, or false if no plugin was able to successfully authenticate the credentials.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_login($username, $password)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
This must be rewritten by plugin to return boolean value, returns true if the username and password work and false if they are wrong or don&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_change_password()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if this authentication plugin can change users&#039; password.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : false&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;change_password_url()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns the URL for changing the users&#039; passwords, or empty if the default URL can be used.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_edit_profile()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if this authentication plugin can edit the users&#039; profile.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : true&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;edit_profile_url()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns the URL for editing users&#039; profile, or empty if the defaults URL can be used.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;is_internal()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if this authentication plugin is &amp;quot;internal&amp;quot;.  Internal plugins use password hashes from Moodle user table for authentication.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : true&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;prevent_local_passwords()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Indicates if password hashes should be stored in local moodle database.  This function automatically returns the opposite boolean of what is_internal() returns.  Returning true means MD5 password hashes will be stored in the user table.  Returning false means flag &#039;not_cached&#039; will be stored there instead.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : !$this-&amp;gt;is_internal()&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;is_synchronised_with_external()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Indicates if moodle should automatically update internal user records with data from external sources using the information from get_userinfo() method.  This function automatically returns the opposite boolean of what is_internal() returns.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : !$this-&amp;gt;is_internal()&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_update_password($user, $newpassword)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Update the user&#039;s password.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_update($olduser, $newuser)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Called when the user record is updated. It will modify the user information in external database.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_delete($olduser)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
User delete requested. Internal user record had been deleted.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_reset_password()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if plugin allows resetting of internal password.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : false&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_signup()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if plugin allows resetting of internal password.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : false&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_signup($user, $notify=true)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Sign up a new user ready for confirmation, password is passed in plaintext.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_confirm()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns true if plugin allows confirming of new users.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Return type&#039;&#039;&#039; : boolean&lt;br /&gt;
; &#039;&#039;&#039;Default return value&#039;&#039;&#039; : false&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_confirm($username, $confirmsecret)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Confirm the new user as registered.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_exists($username)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Checks if user exists in external db.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;password_expire($username)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Returns number of days to user password expires.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;sync_roles()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Sync roles for this user - usually creator&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;get_userinfo($username)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Read user information from external database and returns it as array.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;config_form($config, $err, $user_fields)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Prints a form for configuring this authentication plugin. It&#039;s called from admin/auth.php, and outputs a full page with a form for configuring this plugin.  &lt;br /&gt;
This function has been deprecated in Moodle 3.3.  You should use the [[Admin_settings]] API instead.  For more information see [https://tracker.moodle.org/browse/MDL-12689]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;validate_form($form, $err)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Validate form data.&lt;br /&gt;
This function has been deprecated in Moodle 3.3.  You should use the [[Admin_settings]] API instead.  For more information see [https://tracker.moodle.org/browse/MDL-12689]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;process_config($config)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Processes and stores configuration data for this authentication plugin.&lt;br /&gt;
This function has been deprecated in Moodle 3.3.  You should use the [[Admin_settings]] API instead.  For more information see [https://tracker.moodle.org/browse/MDL-12689]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;loginpage_hook()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Hook for overriding behaviour of login page.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;pre_loginpage_hook()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Hook for overriding behaviour of prior to redirecting to the login page, eg redirecting to an external login url for SAML or OpenID authentication. If you implement this you should also implement loginpage_hook as the user may go directly to the login page.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;user_authenticated_hook($user, $username, $password)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Post authentication hook. This method is called from authenticate_user_login() for all enabled auth plugins.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;prelogout_hook()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Pre logout hook.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;postlogout_hook()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
This method replace the prelogout_hook method to avoid authentication plugins redirects before the user logout event being triggered. &lt;br /&gt;
At the moment the only authentication plugin using this method is CAS (SSO).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;logoutpage_hook()&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Hook for overriding behaviour of logout page.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;can_be_manually_set()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
This function was introduced in the base class and returns false by default. If overriden by an authentication plugin to return true, the authentication plugin will be able to be manually set for users. For example, when bulk uploading users you will be able to select it as the authentication method they use.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt; loginpage_idp_list() &amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Override this method and return a list of Identification Providers (IDPs) that your authentication plugin supports. An array of associative arrays containing url, icon and name for the IDP. These will be displayed on the login page and in the login block.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;pre_user_login_hook(&amp;amp;$user)&amp;lt;/tt&amp;gt;===&lt;br /&gt;
This method is called from authenticate_user_login() right after the user object is generated. This gives the auth plugin an option to make modification to the user object before the verification process starts.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Authentication API]]&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/discuss.php?d=102070 Overview of entire authentication code flow] forum discussion&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/view.php?id=42 User authentication forum]&lt;br /&gt;
* Moodle Docs [[:en:Manage authentication|Manage authentication]]&lt;br /&gt;
* [[:en:Authentication FAQ|Authentication FAQ]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;br /&gt;
[[Category:Plugins]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[fr:Méthodes_d&#039;authentification]]&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49897</id>
		<title>Lesson Improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49897"/>
		<updated>2016-04-28T11:36:36Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Proposed Lesson 3.X Improvements&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is a very powerful but complex module.  The goal of this proposal is to simplify the module without sacrificing flexibility or functionality.  A current analysis of the open issues for the lesson module show that the can be grouped into 3 categories:&lt;br /&gt;
&lt;br /&gt;
*Feature requests to add support for features currently provided by core APIs but are not currently implemented in lesson &lt;br /&gt;
*Bug fixes for current lesson functionality provided by non-standard APIs&lt;br /&gt;
*New features and improvements&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What this proposal is trying to fix:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is considered an advanced module due to the numerous settings that control its behaviors.  One major goal of revamping the lesson module should be to make it simpler to use for teachers. This should be done without removing functionality, but making it easier / more intuitive to set up.  This can be accomplished a few different ways.&lt;br /&gt;
*By removing redundant settings from the module&lt;br /&gt;
*By moving some functionality to independent moodle plugins&lt;br /&gt;
*By converting different parts of the lesson module to use standard moodle APIs &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Proposed changes:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;Phase I: (Simplify the lesson codebase / reduce the number of options when creating a new lesson)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to simplify the user interface, several unnecessary settings can be removed from the lesson module:&lt;br /&gt;
*“Maximum number of answers”  - This setting is only used to limit the number of answers on multiple choice and matching authoring pages.  Most other modules in moodle allow the activity author to add as many answers as needed while creating the activity. (MDL-52874)&lt;br /&gt;
*“Password” - There are two settings required to enable a password in a lesson activity.  One setting to enable the password, another to actually set the password.  Other activities in Moodle that use a password only require a single field (MDL-53143) &lt;br /&gt;
&lt;br /&gt;
In order to simplify the lesson codebase and reduce a significant amount of duplicate code, several lesson features should be converted to separate moodle plugins.&lt;br /&gt;
&lt;br /&gt;
*“Media File / File pop-up” - The lesson module has a feature that allows a teacher to post a single file in a fake block displayed within that specific lesson activity.  It makes sense to create a generic block to allow teacher to post any number of files anywhere in moodle and then convert the “media file” feature in lesson to use this block. This should eliminate the confusion about the media popup in lesson. (MDL-29437, MDL-30333)&lt;br /&gt;
*Lesson Menu - The lesson module has a couple of configuration settings to determine when a navigation menu should be displayed to the student.  There is also a feature request to make this block moveable which would require an additional setting on the lesson configuration screen.  It makes sense to create a separate lesson navigation block and remove the left menu settings from the lesson module. Lessons would be converted to use this block instead. (MDL-31920, MDL-22752)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase II: (Implement a lesson overview page)&#039;&#039;&#039;&lt;br /&gt;
Once the lesson codebase has been cleaned up, A few changes can be made to improve the way a lesson is presented to the student.  The biggest proposed change is to add a lesson overview page at the start of each lesson activity.  (this is similar to how the quiz module works.)  This overview page would display the following information:&lt;br /&gt;
*Lesson Description (if set)&lt;br /&gt;
*Lesson available from date (if set)&lt;br /&gt;
*Lesson available until date (if set)&lt;br /&gt;
*Time limit (if set)&lt;br /&gt;
*Grading method for lesson (no grade,  maximum points)&lt;br /&gt;
*Whether retakes are allowed.&lt;br /&gt;
*How retakes are scored&lt;br /&gt;
(It would also display a start lesson / resume lesson button depending on the current state of the students attempt)&lt;br /&gt;
&lt;br /&gt;
The lesson overview page would only be displayed to users who have the lesson:view capability (MDL-14448) and the start lesson button would only be available to users with the lesson:attempt capability (MDL-20087).  These improvements should also resolve issues MDL-51735 and MDL-49480.&lt;br /&gt;
&lt;br /&gt;
Once these tasks have been completed it should be easy to improve the reporting for the lesson module. Specifically MDL-19948 allowing students to review their answers choices in lesson.  This could be provided as a link on the lesson overview page for users who have completed the lesson and have the lesson:viewmyattempt capability.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase III: (Implement partial question bank support)&#039;&#039;&#039;&lt;br /&gt;
Allowing the Lesson module to fully utilize the questions API (MDL-18954) will resolve a significant number of lesson bugs and feature requests (MDL-34927, MDL-47548, MDL-50256, MDL-43111, MDL-39874, MDL-39261, MDL-39655,  MDL-45798, etc)&lt;br /&gt;
&lt;br /&gt;
The moodle lesson activity currently has functionality to import questions stored in Moodle XML format.  There currently isn’t a mechanism however to export a lesson into Moodle XML format.  The improvement proposed here is to create a utility that will convert / export all existing lesson pages into standard moodle question types to make them available in the moodle question bank.  It should be possible to map the existing lesson page types to the following Moodle question types:&lt;br /&gt;
*Lesson Essay -&amp;gt; Essay&lt;br /&gt;
*Lesson Matching -&amp;gt; Matching&lt;br /&gt;
*Lesson T/F -&amp;gt; True / False&lt;br /&gt;
*Lesson Multichoice -&amp;gt; Multichoice&lt;br /&gt;
*Lesson Content page -&amp;gt; Description&lt;br /&gt;
*Lesson Numerical -&amp;gt; Numeric&lt;br /&gt;
*Lesson Short Answer -&amp;gt; Short answer (Note: the core short answer question type may need to be extended to support the regular expression option available in it’s lesson counterpart)&lt;br /&gt;
*Cluster / subcluster -&amp;gt; Random question (Not Exported)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase IV: (Full Question bank support)&#039;&#039;&#039;&lt;br /&gt;
Implement a new editing page for lesson allowing teachers to choose questions from the question bank and allow teachers to specify page / question sequencing.  All existing lessons would be converted to use the question bank in place of lesson&#039;s custom page types.&lt;br /&gt;
&lt;br /&gt;
Currently lessons are made up of pages that contain a single question or piece of content.  How the user answers these questions dictate which page the user will navigate to next.  Rather than displaying a single question per page, This proposal seeks to instead have a lesson constructed of pages and each page constructed of one or more questions.  The current approach for lesson sequencing would be changed as follows:&lt;br /&gt;
&lt;br /&gt;
*Each page would allow path selection based on a grade percentage or range  (0%, 50%, 100%, etc)&lt;br /&gt;
*Each page would allow  path selection based on one or more manual links (For non-auto graded pages like description or essay)&lt;br /&gt;
*Pages that contain a single question would allow path selection based on the user answer. (Note, this would only be available to specific question types specifically multiple choice, true/false, numeric, and short answer.  Each question type would have to announce support for this functionality.  This would allow existing lessons to continue working as-is.)&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49483</id>
		<title>Lesson Improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49483"/>
		<updated>2016-02-16T22:34:03Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Proposed Lesson 3.X Improvements&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is a very powerful but complex module.  The goal of this proposal is to simplify the module without sacrificing flexibility or functionality.  A current analysis of the open issues for the lesson module show that the can be grouped into 3 categories:&lt;br /&gt;
&lt;br /&gt;
*Feature requests to add support for features currently provided by core APIs but are not currently implemented in lesson &lt;br /&gt;
*Bug fixes for current lesson functionality provided by non-standard APIs&lt;br /&gt;
*New features and improvements&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What this proposal is trying to fix:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is considered an advanced module due to the numerous settings that control its behaviors.  One major goal of revamping the lesson module should be to make it simpler to use for teachers. This should be done without removing functionality, but making it easier / more intuitive to set up.  This can be accomplished a few different ways.&lt;br /&gt;
*By removing redundant settings from the module&lt;br /&gt;
*By moving some functionality to independent moodle plugins&lt;br /&gt;
*By converting different parts of the lesson module to use standard moodle APIs &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Proposed changes:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;Phase I: (Simplify the lesson codebase / reduce the number of options when creating a new lesson)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to simplify the user interface, several unnecessary settings can be removed from the lesson module:&lt;br /&gt;
*“Maximum number of answers”  - This setting is only used to limit the number of answers on multiple choice and matching authoring pages.  Most other modules in moodle allow the activity author to add as many answers as needed while creating the activity. (MDL-52874)&lt;br /&gt;
*“Password” - There are two settings required to enable a password in a lesson activity.  One setting to enable the password, another to actually set the password.  Other activities in Moodle that use a password only require a single field (MDL-53143) &lt;br /&gt;
&lt;br /&gt;
In order to simplify the lesson codebase and reduce a significant amount of duplicate code, several lesson features should be converted to separate moodle plugins.&lt;br /&gt;
&lt;br /&gt;
*“Media File / File pop-up” - The lesson module has a feature that allows a teacher to post a single file in a fake block displayed within that specific lesson activity.  It makes sense to create a generic block to allow teacher to post any number of files anywhere in moodle and then convert the “media file” feature in lesson to use this block. This should eliminate the confusion about the media popup in lesson. (MDL-29437, MDL-30333)&lt;br /&gt;
*Lesson Menu - The lesson module has a couple of configuration settings to determine when a navigation menu should be displayed to the student.  There is also a feature request to make this block moveable which would require an additional setting on the lesson configuration screen.  It makes sense to create a separate lesson navigation block and remove the left menu settings from the lesson module. Lessons would be converted to use this block instead. (MDL-31920, MDL-22752)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase II: (Implement a lesson overview page)&#039;&#039;&#039;&lt;br /&gt;
Once the lesson codebase has been cleaned up, A few changes can be made to improve the way a lesson is presented to the student.  The biggest proposed change is to add a lesson overview page at the start of each lesson activity.  (this is similar to how the quiz module works.)  This overview page would display the following information:&lt;br /&gt;
*Lesson Description (if set)&lt;br /&gt;
*Lesson available from date (if set)&lt;br /&gt;
*Lesson available until date (if set)&lt;br /&gt;
*Time limit (if set)&lt;br /&gt;
*Grading method for lesson (no grade,  maximum points)&lt;br /&gt;
*Whether retakes are allowed.&lt;br /&gt;
*How retakes are scored&lt;br /&gt;
(It would also display a start lesson / resume lesson button depending on the current state of the students attempt)&lt;br /&gt;
&lt;br /&gt;
The lesson overview page would only be displayed to users who have the lesson:view capability (MDL-14448) and the start lesson button would only be available to users with the lesson:attempt capability (MDL-20087).  These improvements should also resolve issues MDL-51735 and MDL-49480.&lt;br /&gt;
&lt;br /&gt;
Once these tasks have been completed it should be easy to improve the reporting for the lesson module. Specifically MDL-19948 allowing students to review their answers choices in lesson.  This could be provided as a link on the lesson overview page for users who have completed the lesson and have the lesson:viewmyattempt capability.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase III: (Implement partial question bank support)&#039;&#039;&#039;&lt;br /&gt;
Allowing the Lesson module to fully utilize the questions API (MDL-18954) will resolve a significant number of lesson bugs and feature requests (MDL-34927, MDL-47548, MDL-50256, MDL-43111, MDL-39874, MDL-39261, MDL-39655,  MDL-45798, etc)  While this proposal seeks to improve the situation, it will not address all of the current issues.  &lt;br /&gt;
&lt;br /&gt;
The moodle lesson activity currently has functionality to import questions stored in Moodle XML format.  There currently isn’t a mechanism however to export a lesson into Moodle XML format.  The improvement proposed here is to create a utility that will convert / export all existing lesson pages into standard moodle question types to make them available in the moodle question bank.  It should be possible to map the existing lesson page types to the following moodle question types:&lt;br /&gt;
*Lesson Essay -&amp;gt; Essay&lt;br /&gt;
*Lesson Matching -&amp;gt; Matching&lt;br /&gt;
*Lesson T/F -&amp;gt; True / False&lt;br /&gt;
*Lesson Multichoice -&amp;gt; Multichoice&lt;br /&gt;
*Lesson Content page -&amp;gt; Description&lt;br /&gt;
*Lesson Numerical -&amp;gt; Numeric&lt;br /&gt;
*Lesson Short Answer -&amp;gt; Short answer (Note: the core short answer question type may need to be extended to support the regular expression option available in it’s lesson counterpart)&lt;br /&gt;
*Cluster / subcluster -&amp;gt; Random question (Not Exported)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase IV: (Future Full Question bank support)&#039;&#039;&#039;&lt;br /&gt;
Implement a new editing page for lesson allowing teachers to choose questions from the question bank and allow teachers to specify question sequencing&lt;br /&gt;
*Allow path selection based on a grade percentage or range  (0%, 50%, 100%, etc)&lt;br /&gt;
*Allow path selection based on a manual link (For non-auto graded pages like description or essay)&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49482</id>
		<title>Lesson Improvements</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lesson_Improvements&amp;diff=49482"/>
		<updated>2016-02-16T22:33:26Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: Created page with &amp;quot;Moodle Lesson Module Improvement Plan  &amp;#039;&amp;#039;&amp;#039;Overview:&amp;#039;&amp;#039;&amp;#039; The lesson module is a very powerful but complex module.  The goal of this proposal is to simplify the module without sa...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle Lesson Module Improvement Plan&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is a very powerful but complex module.  The goal of this proposal is to simplify the module without sacrificing flexibility or functionality.  A current analysis of the open issues for the lesson module show that the can be grouped into 3 categories:&lt;br /&gt;
&lt;br /&gt;
*Feature requests to add support for features currently provided by core APIs but are not currently implemented in lesson &lt;br /&gt;
*Bug fixes for current lesson functionality provided by non-standard APIs&lt;br /&gt;
*New features and improvements&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;What this proposal is trying to fix:&#039;&#039;&#039;&lt;br /&gt;
The lesson module is considered an advanced module due to the numerous settings that control its behaviors.  One major goal of revamping the lesson module should be to make it simpler to use for teachers. This should be done without removing functionality, but making it easier / more intuitive to set up.  This can be accomplished a few different ways.&lt;br /&gt;
*By removing redundant settings from the module&lt;br /&gt;
*By moving some functionality to independent moodle plugins&lt;br /&gt;
*By converting different parts of the lesson module to use standard moodle APIs &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Proposed changes:&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;Phase I: (Simplify the lesson codebase / reduce the number of options when creating a new lesson)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to simplify the user interface, several unnecessary settings can be removed from the lesson module:&lt;br /&gt;
*“Maximum number of answers”  - This setting is only used to limit the number of answers on multiple choice and matching authoring pages.  Most other modules in moodle allow the activity author to add as many answers as needed while creating the activity. (MDL-52874)&lt;br /&gt;
*“Password” - There are two settings required to enable a password in a lesson activity.  One setting to enable the password, another to actually set the password.  Other activities in Moodle that use a password only require a single field (MDL-53143) &lt;br /&gt;
&lt;br /&gt;
In order to simplify the lesson codebase and reduce a significant amount of duplicate code, several lesson features should be converted to separate moodle plugins.&lt;br /&gt;
&lt;br /&gt;
*“Media File / File pop-up” - The lesson module has a feature that allows a teacher to post a single file in a fake block displayed within that specific lesson activity.  It makes sense to create a generic block to allow teacher to post any number of files anywhere in moodle and then convert the “media file” feature in lesson to use this block. This should eliminate the confusion about the media popup in lesson. (MDL-29437, MDL-30333)&lt;br /&gt;
*Lesson Menu - The lesson module has a couple of configuration settings to determine when a navigation menu should be displayed to the student.  There is also a feature request to make this block moveable which would require an additional setting on the lesson configuration screen.  It makes sense to create a separate lesson navigation block and remove the left menu settings from the lesson module. Lessons would be converted to use this block instead. (MDL-31920, MDL-22752)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase II: (Implement a lesson overview page)&#039;&#039;&#039;&lt;br /&gt;
Once the lesson codebase has been cleaned up, A few changes can be made to improve the way a lesson is presented to the student.  The biggest proposed change is to add a lesson overview page at the start of each lesson activity.  (this is similar to how the quiz module works.)  This overview page would display the following information:&lt;br /&gt;
*Lesson Description (if set)&lt;br /&gt;
*Lesson available from date (if set)&lt;br /&gt;
*Lesson available until date (if set)&lt;br /&gt;
*Time limit (if set)&lt;br /&gt;
*Grading method for lesson (no grade,  maximum points)&lt;br /&gt;
*Whether retakes are allowed.&lt;br /&gt;
*How retakes are scored&lt;br /&gt;
(It would also display a start lesson / resume lesson button depending on the current state of the students attempt)&lt;br /&gt;
&lt;br /&gt;
The lesson overview page would only be displayed to users who have the lesson:view capability (MDL-14448) and the start lesson button would only be available to users with the lesson:attempt capability (MDL-20087).  These improvements should also resolve issues MDL-51735 and MDL-49480.&lt;br /&gt;
&lt;br /&gt;
Once these tasks have been completed it should be easy to improve the reporting for the lesson module. Specifically MDL-19948 allowing students to review their answers choices in lesson.  This could be provided as a link on the lesson overview page for users who have completed the lesson and have the lesson:viewmyattempt capability.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase III: (Implement partial question bank support)&#039;&#039;&#039;&lt;br /&gt;
Allowing the Lesson module to fully utilize the questions API (MDL-18954) will resolve a significant number of lesson bugs and feature requests (MDL-34927, MDL-47548, MDL-50256, MDL-43111, MDL-39874, MDL-39261, MDL-39655,  MDL-45798, etc)  While this proposal seeks to improve the situation, it will not address all of the current issues.  &lt;br /&gt;
&lt;br /&gt;
The moodle lesson activity currently has functionality to import questions stored in Moodle XML format.  There currently isn’t a mechanism however to export a lesson into Moodle XML format.  The improvement proposed here is to create a utility that will convert / export all existing lesson pages into standard moodle question types to make them available in the moodle question bank.  It should be possible to map the existing lesson page types to the following moodle question types:&lt;br /&gt;
*Lesson Essay -&amp;gt; Essay&lt;br /&gt;
*Lesson Matching -&amp;gt; Matching&lt;br /&gt;
*Lesson T/F -&amp;gt; True / False&lt;br /&gt;
*Lesson Multichoice -&amp;gt; Multichoice&lt;br /&gt;
*Lesson Content page -&amp;gt; Description&lt;br /&gt;
*Lesson Numerical -&amp;gt; Numeric&lt;br /&gt;
*Lesson Short Answer -&amp;gt; Short answer (Note: the core short answer question type may need to be extended to support the regular expression option available in it’s lesson counterpart)&lt;br /&gt;
*Cluster / subcluster -&amp;gt; Random question (Not Exported)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Phase IV: (Future Full Question bank support)&#039;&#039;&#039;&lt;br /&gt;
Implement a new editing page for lesson allowing teachers to choose questions from the question bank and allow teachers to specify question sequencing&lt;br /&gt;
*Allow path selection based on a grade percentage or range  (0%, 50%, 100%, etc)&lt;br /&gt;
*Allow path selection based on a manual link (For non-auto graded pages like description or essay)&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=sandbox&amp;diff=49481</id>
		<title>sandbox</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=sandbox&amp;diff=49481"/>
		<updated>2016-02-16T22:26:13Z</updated>

		<summary type="html">&lt;p&gt;Sbourget: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For playing around in....&lt;br /&gt;
a&lt;/div&gt;</summary>
		<author><name>Sbourget</name></author>
	</entry>
</feed>