Difference between revisions of "Extension talk:Selenium.php"

From Organic Design wiki
(move road-map to top)
(Change source-code blocks to standard format)
 
(37 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{ext-talk-msg|Selenium}}
 
{{ext-talk-msg|Selenium}}
The idea of this extension is to bundle selenium up along with the MediaWiki extension and provide a simple means of incorporating tests along with extensions which can be maintained as both wiki articles, and a special page used to manually run the tests. Also we'd like the ability to run tests on a regular schedule and have an email or talk-page based failure notification system. This would allow us to know immediately when changes to code affect extension version functionality when running in various MediaWiki versions.
+
[http://selenium-core.openqa.org Selenium Core] is a test tool for web applications. Selenium Core tests run '''directly in a browser''', just as real users do. And they run in Internet Explorer, Mozilla and Firefox on Windows, Linux, and Macintosh. No other test tool covers such a wide array of platforms. The idea of this extension is to bundle the Selenium Core functionality up as a MediaWiki extension to provide a simple means of incorporating tests along with extensions so that all their aspects of functionality can be tested for any given wiki installation, and failure reports be delivered automatically whenever functionality breaks.
 +
 
 +
Selenium tests are defined in an HTML table format which can be initially created in the [http://selenium-ide.openqa.org Selenium IDE] which runs in your browser. The process of creating and running tests in the Selenium IDE is very similar to recording and playing macros in Open Office or other popular office suite applications. A recorded test can be further refined in a text editor if necessary.
 +
 
 +
In the MediaWiki environment, test-suites don't need to be a specific format themselves, they are just articles which contain more than one test. For tests or parts of tests which are re-used across a number of suites, templates can be transcluded the to collate tests into a test-suite article. See the [[Example Selenium test suite]] for details.
 +
 
 +
The [[Special:Selenium|Selenium special page]] is then used to select test suites from a list which can be launched in the Selenium IDE to be run. Articles containing tests are automatically categorised into [[:Category:Selenium]] which is how the special page generates the selection list. Tests can also be set to run on a schedule along with actions to be taken should any of them fail, this is described in more details below.
  
 
Taking testing to a further level of organisation would allow us to package up wiki-based organisational systems which exactly specify their functionality and exhibit corresponding tests for every item specified. This would allow us to move into a higher level of service automation and would form the basis of a more robust SLA-based service architecture.
 
Taking testing to a further level of organisation would allow us to package up wiki-based organisational systems which exactly specify their functionality and exhibit corresponding tests for every item specified. This would allow us to move into a higher level of service automation and would form the basis of a more robust SLA-based service architecture.
  
== Road Map ==
+
== Installation ==
The overall plan for the Selenium extension is to work with [[Extension:Packages.php]] to create packages of tests and the articles required by the tests. Each package can test a particular set of functionality such as testing each feature that a particular extension claims to add to the environment, testing that [[:Category:Examples|examples]] in documentation aren't broken, or a general test of MediaWiki functionality etc.
+
The extension consists of a directory called ''Selenium'' containing a few four php scripts. Copy the directory into your extensions directory and include the main script from LocalSettings;
 +
<php>
 +
include("$IP/extensions/Selenium/Selenium.php");
 +
</php>
 +
The ''selenium core'' environment is an independent project which needs to be downloaded and placed into the ''extensions/Selenium'' directory. The Selenium core can be downloaded from [http://selenium-core.openqa.org/download.jsp here] as a zip file, it should be unpacked and it's name changed to ''selenium-core''. Alternatively the ''extensions/Selenium/selenium-core'' directory can be maintained directly from their subversion repository as follows:
 +
<pre>
 +
cd path-to-wiki/extensions/Selenium
 +
svn co https://svn.openqa.org/svn/selenium-core/trunk/src/main/resources selenium-core
 +
</pre>
  
This structured system of tests can then be integrated into our organisational system so that it can be easily implemented on other client servers and kept up to date. The tests can then be run on schedule on all of our test wikis so that automatic reports of failures on various environments and versions can be delivered in email or recent changes.
+
=== Selenium server installation (Debian Linux) ===
 +
The [http://selenium-rc.openqa.org Selenium Remote Control (SRC)] is used to allow scheduling of automated test execution. The SRC uses a java service called the Selenium Server to launch and control browser instances to run the Selenium tests in and report results back. The SRC can be downloaded from [http://selenium-rc.openqa.org/download.html here], it comes as a zip file containing directories for the Selenium Server and for each of the programming languages the remote control API is available for. I doesn't matter where the Selenium Server is unpacked to, but I prefer to take only the Server folder, rename it to ''selenium-server'' put it in the Selenium extension directory along with ''selenium-core''.
  
This testing environment will then become an important addition to our offered services which come with our general infrastructure that we install and maintain for clients and associated organisations. The current state of development of this infrastructure is in [[Wiki Organisation]].
+
It's in this ''selenium-server'' directory that the main java server program resides, it's called ''selenium-server.jar''. To be able to run it, you''ll need to install the Java framework if you don't already have it, which you can do on Debian or Ubuntu with the following package install:
 +
apt-get install sun-java5-jdk
  
== In-wiki test format ==
+
The next technical difficulty to overcome is that the Selenium Server actually runs real browser instances which open a window in the desktop, but the problem is that we need this to run on our remote web server which has no screen or desktop environment installed. So to get around this we must first install a minimal set of X-server components and a browser. On Debian servers this can be done with the following package installations. We've chosen firefox as our browser, but you can use any browser which uses a standard browser-DOM such as Opera, Konquerer or you could even use Internet Explorer through Wine.
{{Note| Ideally we would like to cater for transclusion of individual tests aswell. Optionally a namespace called ''Test:'' could be created specifically for selenium tests. The extension itself will categorize any <nowiki><selenium></nowiki> tag.}}
+
apt-get install xvfb xserver-xorg xfs xfonts-base firefox
 +
To test that the browser can run, we'll first create a virtual screen, launch the browser in it and then take a snapshot to see what it looks like. Best to do the following from a root terminal.
 +
nohup Xvfb :1 -screen 0 1024x768x24 2>&1 > /var/log/xvfb.log &
 +
DISPLAY=:1 firefox
 +
DISPLAY=:1 import -window root screenshot.png
 +
If all is working correctly, you'll see a normal browser window in the generated file ''screenshot.png''. If not, then you'll need to begin tracking down the problem starting with the information logged to ''/var/log/xvfb.log''.
  
If each test was a separate article, then they can be categorized etc. Utilizing existing Selenium IDE output HTML table format would be convenient. Each test article would be a suite of tests where each individual test is in a separate heading section, and then the actual functions composing the test is just a table within its section. This simplifies things by allowing all the tests for a given extension to be in just one article. It is quickest to maintain HTML tables as these can be imported quickly from the Selenium IDE as is. The only redundant tags are the <nowiki><html>...</html></nowiki> wrappers.  
+
== The Selenium IDE ==
 +
[[Image:Selenium-ide.gif|300px|right|thumb|Selenium IDE]]
 +
Selenium has both a server and a client side, the client side is [http://www.openqa.org/selenium-ide Selenium IDE] which is a Firefox browser plugin. Selenium IDE is an integrated development environment for Selenium tests. It is implemented as a Firefox extension, and allows you to record, edit, and debug tests. Selenium IDE includes the entire Selenium Core, allowing you to easily and quickly record and play back tests in the actual client browser environment that they will run.
  
It appears that the table tags <code><thead></thead><tbody></tbody></code> are not currently defined by the wiki parser, see [[W:Help:HTML_in_wikitext#Permitted_HTML]].
+
Selenium IDE is not only recording tool: it is a complete IDE. You can choose to use its recording capability, or you may edit your scripts by hand. With auto-complete support and the ability to move commands around quickly, Selenium IDE is the ideal environment for creating Selenium tests no matter what style of tests you prefer.
:Either use a &lt;selenium&gt; or just add tag-hooks for thead and tbody which return null - probly easiest --[[User:Nad|Nad]] 09:19, 7 December 2007 (NZDT)
 
I guess for simplicity the test environment should utilize the current way selenium works taking you to a URL which shows the selenium frames and the tests it is about to perform where you select the article to test from the Special page.
 
[[Image:Selenium.png|400px|right|thumb|Selenium TestRunner environment ''([PATH to selenium core]/TestRunner.html)'']]
 
  
The extension should come with a test that examines the selenium extension, checks it is installed, what version it is and usage.
+
It is also recommended to install the firefox extension [http://slesinsky.org/brian/code/xpath_checker.html XPath Checker], which provides a right click option ''View XPath'' over any part of a web page which provides the [[W:XPath|XPath]] expression.
  
 +
=== Creating tests ===
 +
The easiest way to create tests is to record them in firefox after enabling the Selenium IDE from the ''tools'' pull down menu. As you populate form fields with text, hitting tab will guarantee that the value is recorded by the Selenium IDE.  If a recorded field is incorrect, just edit the html table source removing the table row error and continue the recording process. After recording a test, the source html can be modified and refined by hand. In general long form URLs should be used to minimise ambiguity for portability of tests as some wiki's use Friendly URLs.
 +
<div class=visualClear>
  
 +
== Running tests on a schedule ==
 +
One of the main requirements that we have for the Selenium testing environment is to have it report to us whenever any functionality breaks from the development we do on our extensions. For example we like to schedule a suite of tests which cover all the functionality of the [[MW:Extension:SimpleSecurity|SimpleSecurity extension]], and test all that functionality on all the different MediaWiki code-bases we have installed in our [[OD/Wikia|wikia]].
  
=== Specialpage===
+
The extension uses a single global variable to contain the information about what test should be periodically run. The <tt>$wgSeleniumSchedule</tt> global contains a list of times (items with numeric keys) each in the format of ''hh:mm'' that determine at what times each day the tests should be run. The same global also contains ''key:value'' pairs. These determine what test suites are currently scheduled to run. Each ''key:value'' pair has a test-suite name for a key, and an array of domains that the test should be run on. This allows wikis that do not have the Selenium extension installed to be tested. However, the Selenium core environment must still exist in the extensions directory of the domain being tested. here's an example of filling in the <tt>$wgSeleniumSchedule</tt> global.
The url http:///www.organicdesign.co.nz/Specialpage:Selenium should allow users to select an article that they want to test from a pull down list, when the test is run to selenium the suite html will be created on the fly  by selecting the url - ''http://www.organicdesign.co.nz/Special:Selenium/Test article''.
+
<php>
As the article is made up of individual tests, the special page would also create the test html dynamically, e.g.  
+
$egSeleniumSchdeule = array(
<bash>
+
"10:30", "14:00", "23:55",
# Test article
+
"Example Selenium test suite" => array($wgServer, 'http://od.localhost')
http://www.organicdesign.co.nz/Special:Selenium/Test_article
+
);
http://www.organicdesign.co.nz/Special:Selenium/Test1
+
</php>
http://www.organicdesign.co.nz/Special:Selenium/Test2
+
All the information about test run and failures are appended to <tt>$wgSeleniumLog</tt> which is set by default to [[MediaWiki:Selenium log]]. It's been done as an article edit so that the failure shows up in the recent changes, and so that any interested parties can watch the article and thereby be notified of failures over email if they choose.
http://www.organicdesign.co.nz/Special:Selenium/Test_article#third_selenium_tag_header
 
http://www.organicdesign.co.nz/Special:Selenium/Test4
 
...
 
# Extension location
 
$IP/extensions/Selenium/Selenium.php
 
# Selenium core location
 
$IP/extensions/Selenium/selenium-core-0
 
$IP/extensions/Selenium/selenium -> $IP/extensions/Selenium/selenium-core-0
 
  
</bash>
+
=== Selenium Remote Control (SRC) ===
 +
Running the tests automatically on a schedule is not quite as simple as initially expected. The Selenium IDE is a complex JavaScript application and so must run within a full browser DOM. It cannot be run from a simple perl  module user agent like ''lib-www''. But this is the job of the [http://selenium-rc.openqa.org Selenium Remote Control] enrionment which is designed to instantiate a local browser, run the tests in it and capture the results. It has interfaces to the most popular programming languages so that the functionality of the Selenium IDE can be placed under automated control.
  
The expected html of a selenium test  is currently a test Suite file which links to many tests. An example structure is
+
The Selenium Remote Control is a daemon written in Java that launches browser instances and runs the Selenium IDE in them. One of the options allows it to launch a browser and then run the specified test suite for the given domain.
;Test suite wrapper file
+
  java -jar selenium-server.jar "*custom /usr/bin/firefox" domain suite.html results.txt
<pre>
+
There are a number of difficulties with this which require workarounds:
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+
*The Selenium core is expected to reside at a default path of ''/selenium-server/core''
<title>Test Suite</title>
+
*The tests are expected to exist in ''/selenium-server/tests''
</head><body><table cellpadding="1" cellspacing="1" border="1"><tbody>
+
*The results are POSTed back to '/selenium-server/postResults''
<tr><td><b>Flouzo Test Suite</b></td></tr>
+
*The script doesn't close after running the test and '''-timeout nnnn'''' option must be added
 +
*The results.txt file is not updated (probably because it doesn't close properly)
 +
*The firefox browser asks about starting a new session or restoring which the SRC can't answer inassisted
 +
I've been able to get the system working by creating a symlink to ensure that the path ''/selenium-server'' exists and points to the Selenium core in ''/var/www/extensions/Selenium/selenium-core''. And I created a rewrite rule to map the non-existent ''postResults'' script onto [[postResults.php]] which appends the relavent passes and fails to the ''results.txt'' file.
  
<tr><td><a href="/selenium/Wikitests/Logout.html">Logout.html</a></td></tr>
+
A further difficulty is that a minimal installation of a browser must be set up on the server which does not require a screen or the massive XWindow layer to work ([http://blarg.slackworks.com/posts/integrating-selenium this example] and [http://wiki.openqa.org/display/SRC/Selenium-RC+and+Continuous+Integration this one] may help with that).
  
</tbody></table></body></html>
+
== Test suite articles ==
</pre>
+
The tests produced by the Selenium IDE are text encoded into a specific HTML format. Each test is in the form of an HTML table, but unfortunately the table's generated HTML syntax contains some tags which are not allowed in wikitext. Here's an example of the ''logout'' test:
; A selenium test - ''/selenium/Wikitests/Logout.htm''
+
<xml>
<pre>
 
 
<html>
 
<html>
<head>
+
    <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>New Test</title>
+
        <title>Logout</title>
</head>
+
    </head>
<body>
+
    <body>
<table cellpadding="1" cellspacing="1" border="1">
+
        <table cellpadding="1" cellspacing="1" border="1">
<thead>
+
            <thead>
<tr><td rowspan="1" colspan="3">New Test</td></tr>
+
                <tr><td rowspan="1" colspan="3">Logout</td></tr>
</thead><tbody>
+
            </thead>
<tr>
+
            <tbody>
<td>open</td>
+
                <tr>
<td>/mediawiki-1.11.0/index.php?title=Special:Userlogout</td>
+
                    <td>open</td>
 
+
                    <td>/wiki/index.php?title=Main_page</td>
<td></td>
+
                    <td></td>
</tr>
+
                </tr>
</tbody></table>
+
                <tr>
</body>
+
                    <td>clickAndWait</td>
 +
                    <td>link=Log out</td>
 +
                    <td></td>
 +
                </tr>
 +
                <tr>
 +
                    <td>verifyHtmlSource</td>
 +
                    <td>glob:*You are now logged out.*</td>
 +
                    <td></td>
 +
                </tr>
 +
            </tbody>
 +
        </table>
 +
    </body>
 
</html>
 
</html>
</pre>
+
</xml>
 +
As you can see, the test comtain a number of illegal tags, and the whole test is surrounded by an ''html'' tag which is reserved by MediaWiki, so we need to surround Selenium tests in ''selenium'' tags so that we can remove these unwanted tags before parsing the content normally. We still want to parse the content because we need transclusion and parser functions to work as usual, and also we'd like the table to render properly and we don't want to send the content back to the client as raw HTML because of XSS concerns.
  
 +
So the test above would be changed slightly to the following - the whole test is wrapped in the ''selenium'' tag and the path to the Main Page article is done using the ''localurl'' parser function.
 +
<xml>
 +
<selenium>
 +
    <html>
 +
        <head>
 +
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 +
            <title>Logout</title>
 +
        </head>
 +
        <body>
 +
            <table cellpadding="1" cellspacing="1" border="1">
 +
                <thead>
 +
                    <tr><td rowspan="1" colspan="3">Logout</td></tr>
 +
                </thead>
 +
                <tbody>
 +
                    <tr>
 +
                        <td>open</td>
 +
                        <td>{(localurl:Main Page}}</td>
 +
                        <td></td>
 +
                    </tr>
 +
                    <tr>
 +
                        <td>clickAndWait</td>
 +
                        <td>link=Log out</td>
 +
                        <td></td>
 +
                    </tr>
 +
                    <tr>
 +
                        <td>verifyHtmlSource</td>
 +
                        <td>glob:*You are now logged out.*</td>
 +
                        <td></td>
 +
                    </tr>
 +
                </tbody>
 +
            </table>
 +
        </body>
 +
    </html>
 +
</selenium>
 +
</xml>
  
 
+
== Table style ==
=== Test article naming ===
+
The ''body'' tag replaces itself with a ''div'' of class "selenium" allowing the tests to have nicer styling applied to them from CSS, for example, we added the following rules to our own [[MediaWiki:Common.css]].
The name of the article should be in the "test", "selenium" or maybe "spec" namespace and have the same title as the extension it is designed to test. This way, the Selenium extension can offer an action button to the tests if there is one corresponding to the current page. Whatever the name, there should be a unique namespace, then these articles could be transcluded into a master article allowing template variable embedding, however we want to suppress certain wikitext though.
+
<css>
 
+
.selenium table {
=== Specification ===
+
    border: 2px solid #dde;
Each section is a test for some specific functionality which should be described clearly in plain english below the heading before the bullet list/HTML table of test functions. This way each extension's test article becomes a complete ''specification'' of the extended functionality which is both human readable and machine testable. For this reason the "spec" namespace may be more appropriate than "test".
+
    background: white;
 
+
    font-family: Verdana, Arial, sans-serif;
== Test Execution ==
+
    font-size: 12px;
The special page allows all the known tests to be listed, and specific tests to be executed by launching the ''Test Runner''. The test runner requires the tests to be in a simple HTML table format, and requires them to be available from a URL relative to the Selenium code. The special page must therefore be able to accept for its parameter the name of the tests to run and be able to return them in the appropriate format for Selenium.
+
    font-weight: bold;
 +
    text-align: center;
 +
}
 +
.selenium td {
 +
    border: none;
 +
    padding: 4px;
 +
    margin: 0;
 +
}
 +
.selenium tr {
 +
    background: #dde;
 +
}
 +
.selenium tr + tr {
 +
    font-weight: normal;
 +
    background: #eef;
 +
    text-align: left;
 +
}
 +
</css>
  
 
== Test Automation ==
 
== Test Automation ==
Line 95: Line 178:
  
 
By creating a quick script called results.php in a temporary directory in <code>$IP/extensions/Selenium/</code> with contents;
 
By creating a quick script called results.php in a temporary directory in <code>$IP/extensions/Selenium/</code> with contents;
{{code|<php>
+
<source lang="php">
 
<?php
 
<?php
  
Line 103: Line 186:
  
 
?>
 
?>
</php>
+
</source>
}}
 
  
 
and redirecting ''resultsUrl=../../tmp/results.php''.  
 
and redirecting ''resultsUrl=../../tmp/results.php''.  
  
an example of the posted parameters sent are as follows;
+
An example of the posted parameters sent are as follows;
 
{{message|icon=|text=
 
{{message|icon=|text=
 
selenium_version => 0.8.3<br />selenium_revision => 1879<br />result => passed<br />totalTime => 5<br />numTestPasses => 1<br />numTestFailures => 0<br />numCommandPasses => 0<br />numCommandFailures => 0<br />numCommandErrors => 0<br />testTable_1 => <div>
 
selenium_version => 0.8.3<br />selenium_revision => 1879<br />result => passed<br />totalTime => 5<br />numTestPasses => 1<br />numTestFailures => 0<br />numCommandPasses => 0<br />numCommandFailures => 0<br />numCommandErrors => 0<br />testTable_1 => <div>
Line 158: Line 240:
  
 
I think its probly best to keep all its files in its own dir (ie extensions/selenium) same as other extensions like searchlog which generate other files it should also be able to be executed from shell and run selected tests eg from cron etc.
 
I think its probly best to keep all its files in its own dir (ie extensions/selenium) same as other extensions like searchlog which generate other files it should also be able to be executed from shell and run selected tests eg from cron etc.
 
== How does this complement [[SVN|SubVersion (SVN)]]? ==
 
I guess SVN testing can only check server side PHP for errors in core (and extension) MediaWiki functionality, whereas Selenium is testing the output environment from the end user clients perspective.
 
  
 
== See also ==
 
== See also ==
*[[MW:Development_policy| MediaWiki development policy]]
+
*[[MW:Development_policy|MediaWiki development policy]]
 
*[[Selenium]]
 
*[[Selenium]]
*[[Extension:CategoryHook.php]] -''Categorization of <nowiki><selenium></nowiki> tags''
 
*[http://www.organicdesign.co.nz/wiki/index.php?title=Extension:Packages.php&diff=prev&oldid=80189 extractSections() in Parser.php]
 
== [[MediaWiki:Common.css]] ==
 
 
The following CSS rules can be added to enhance table rendering;
 
<pre>
 
/** CSS placed here will be applied to all skins */
 
div.selenium table {
 
border:1px solid #CCCCCC;
 
border-collapse:collapse;
 
font-family:Verdana,Arial,sans-serif;
 
font-size:12px;
 
}
 
</pre>
 
 
== [[MW:Manual:Tag_extensions#Security_Concerns|Cross site scripting]] ==
 
 
;Pseudo code
 
{{code|<php>
 
enableTags = function($text, $tags) {
 
/*
 
  * Function to run htmlspecialchars on input html, then replacing selected tags  * starting &lt; with < to reenable tag function
 
  */
 
 
# Convert all '<' (less than) to '&lt;'
 
$text = htmlspecialchars($text);
 
 
# for loop enabling tags in array again
 
  for( $tags as $tag ) { # slightly incorrect here
 
    $text = preg_replace("/&lt;/?$tag/", "</?$tag", $text);
 
  }
 
return($text);
 
}
 
</php>
 
}}
 

Latest revision as of 18:11, 22 May 2015

Info.svg This talk page pertains specifically to the development of this extension. For more general discussion about bugs and usage etc, please refer to the mediawiki.org talk page at MW:Extension talk:Selenium

Selenium Core is a test tool for web applications. Selenium Core tests run directly in a browser, just as real users do. And they run in Internet Explorer, Mozilla and Firefox on Windows, Linux, and Macintosh. No other test tool covers such a wide array of platforms. The idea of this extension is to bundle the Selenium Core functionality up as a MediaWiki extension to provide a simple means of incorporating tests along with extensions so that all their aspects of functionality can be tested for any given wiki installation, and failure reports be delivered automatically whenever functionality breaks.

Selenium tests are defined in an HTML table format which can be initially created in the Selenium IDE which runs in your browser. The process of creating and running tests in the Selenium IDE is very similar to recording and playing macros in Open Office or other popular office suite applications. A recorded test can be further refined in a text editor if necessary.

In the MediaWiki environment, test-suites don't need to be a specific format themselves, they are just articles which contain more than one test. For tests or parts of tests which are re-used across a number of suites, templates can be transcluded the to collate tests into a test-suite article. See the Example Selenium test suite for details.

The Selenium special page is then used to select test suites from a list which can be launched in the Selenium IDE to be run. Articles containing tests are automatically categorised into Category:Selenium which is how the special page generates the selection list. Tests can also be set to run on a schedule along with actions to be taken should any of them fail, this is described in more details below.

Taking testing to a further level of organisation would allow us to package up wiki-based organisational systems which exactly specify their functionality and exhibit corresponding tests for every item specified. This would allow us to move into a higher level of service automation and would form the basis of a more robust SLA-based service architecture.

Installation

The extension consists of a directory called Selenium containing a few four php scripts. Copy the directory into your extensions directory and include the main script from LocalSettings; <php> include("$IP/extensions/Selenium/Selenium.php"); </php> The selenium core environment is an independent project which needs to be downloaded and placed into the extensions/Selenium directory. The Selenium core can be downloaded from here as a zip file, it should be unpacked and it's name changed to selenium-core. Alternatively the extensions/Selenium/selenium-core directory can be maintained directly from their subversion repository as follows:

cd path-to-wiki/extensions/Selenium
svn co https://svn.openqa.org/svn/selenium-core/trunk/src/main/resources selenium-core

Selenium server installation (Debian Linux)

The Selenium Remote Control (SRC) is used to allow scheduling of automated test execution. The SRC uses a java service called the Selenium Server to launch and control browser instances to run the Selenium tests in and report results back. The SRC can be downloaded from here, it comes as a zip file containing directories for the Selenium Server and for each of the programming languages the remote control API is available for. I doesn't matter where the Selenium Server is unpacked to, but I prefer to take only the Server folder, rename it to selenium-server put it in the Selenium extension directory along with selenium-core.

It's in this selenium-server directory that the main java server program resides, it's called selenium-server.jar. To be able to run it, youll need to install the Java framework if you don't already have it, which you can do on Debian or Ubuntu with the following package install:

apt-get install sun-java5-jdk

The next technical difficulty to overcome is that the Selenium Server actually runs real browser instances which open a window in the desktop, but the problem is that we need this to run on our remote web server which has no screen or desktop environment installed. So to get around this we must first install a minimal set of X-server components and a browser. On Debian servers this can be done with the following package installations. We've chosen firefox as our browser, but you can use any browser which uses a standard browser-DOM such as Opera, Konquerer or you could even use Internet Explorer through Wine.

apt-get install xvfb xserver-xorg xfs xfonts-base firefox

To test that the browser can run, we'll first create a virtual screen, launch the browser in it and then take a snapshot to see what it looks like. Best to do the following from a root terminal.

nohup Xvfb :1 -screen 0 1024x768x24 2>&1 > /var/log/xvfb.log &
DISPLAY=:1 firefox
DISPLAY=:1 import -window root screenshot.png

If all is working correctly, you'll see a normal browser window in the generated file screenshot.png. If not, then you'll need to begin tracking down the problem starting with the information logged to /var/log/xvfb.log.

The Selenium IDE

Selenium IDE

Selenium has both a server and a client side, the client side is Selenium IDE which is a Firefox browser plugin. Selenium IDE is an integrated development environment for Selenium tests. It is implemented as a Firefox extension, and allows you to record, edit, and debug tests. Selenium IDE includes the entire Selenium Core, allowing you to easily and quickly record and play back tests in the actual client browser environment that they will run.

Selenium IDE is not only recording tool: it is a complete IDE. You can choose to use its recording capability, or you may edit your scripts by hand. With auto-complete support and the ability to move commands around quickly, Selenium IDE is the ideal environment for creating Selenium tests no matter what style of tests you prefer.

It is also recommended to install the firefox extension XPath Checker, which provides a right click option View XPath over any part of a web page which provides the XPath expression.

Creating tests

The easiest way to create tests is to record them in firefox after enabling the Selenium IDE from the tools pull down menu. As you populate form fields with text, hitting tab will guarantee that the value is recorded by the Selenium IDE. If a recorded field is incorrect, just edit the html table source removing the table row error and continue the recording process. After recording a test, the source html can be modified and refined by hand. In general long form URLs should be used to minimise ambiguity for portability of tests as some wiki's use Friendly URLs.

Running tests on a schedule

One of the main requirements that we have for the Selenium testing environment is to have it report to us whenever any functionality breaks from the development we do on our extensions. For example we like to schedule a suite of tests which cover all the functionality of the SimpleSecurity extension, and test all that functionality on all the different MediaWiki code-bases we have installed in our wikia.

The extension uses a single global variable to contain the information about what test should be periodically run. The $wgSeleniumSchedule global contains a list of times (items with numeric keys) each in the format of hh:mm that determine at what times each day the tests should be run. The same global also contains key:value pairs. These determine what test suites are currently scheduled to run. Each key:value pair has a test-suite name for a key, and an array of domains that the test should be run on. This allows wikis that do not have the Selenium extension installed to be tested. However, the Selenium core environment must still exist in the extensions directory of the domain being tested. here's an example of filling in the $wgSeleniumSchedule global. <php> $egSeleniumSchdeule = array( "10:30", "14:00", "23:55", "Example Selenium test suite" => array($wgServer, 'http://od.localhost') ); </php> All the information about test run and failures are appended to $wgSeleniumLog which is set by default to MediaWiki:Selenium log. It's been done as an article edit so that the failure shows up in the recent changes, and so that any interested parties can watch the article and thereby be notified of failures over email if they choose.

Selenium Remote Control (SRC)

Running the tests automatically on a schedule is not quite as simple as initially expected. The Selenium IDE is a complex JavaScript application and so must run within a full browser DOM. It cannot be run from a simple perl module user agent like lib-www. But this is the job of the Selenium Remote Control enrionment which is designed to instantiate a local browser, run the tests in it and capture the results. It has interfaces to the most popular programming languages so that the functionality of the Selenium IDE can be placed under automated control.

The Selenium Remote Control is a daemon written in Java that launches browser instances and runs the Selenium IDE in them. One of the options allows it to launch a browser and then run the specified test suite for the given domain.

java -jar selenium-server.jar "*custom /usr/bin/firefox" domain suite.html results.txt

There are a number of difficulties with this which require workarounds:

  • The Selenium core is expected to reside at a default path of /selenium-server/core
  • The tests are expected to exist in /selenium-server/tests
  • The results are POSTed back to '/selenium-server/postResults
  • The script doesn't close after running the test and -timeout nnnn' option must be added
  • The results.txt file is not updated (probably because it doesn't close properly)
  • The firefox browser asks about starting a new session or restoring which the SRC can't answer inassisted

I've been able to get the system working by creating a symlink to ensure that the path /selenium-server exists and points to the Selenium core in /var/www/extensions/Selenium/selenium-core. And I created a rewrite rule to map the non-existent postResults script onto postResults.php which appends the relavent passes and fails to the results.txt file.

A further difficulty is that a minimal installation of a browser must be set up on the server which does not require a screen or the massive XWindow layer to work (this example and this one may help with that).

Test suite articles

The tests produced by the Selenium IDE are text encoded into a specific HTML format. Each test is in the form of an HTML table, but unfortunately the table's generated HTML syntax contains some tags which are not allowed in wikitext. Here's an example of the logout test: <xml> Logout

Logout
open /wiki/index.php?title=Main_page
clickAndWait link=Log out
verifyHtmlSource glob:*You are now logged out.*
</xml> As you can see, the test comtain a number of illegal tags, and the whole test is surrounded by an html tag which is reserved by MediaWiki, so we need to surround Selenium tests in selenium tags so that we can remove these unwanted tags before parsing the content normally. We still want to parse the content because we need transclusion and parser functions to work as usual, and also we'd like the table to render properly and we don't want to send the content back to the client as raw HTML because of XSS concerns.

So the test above would be changed slightly to the following - the whole test is wrapped in the selenium tag and the path to the Main Page article is done using the localurl parser function. <xml> <selenium>

   
        
            
            Logout
        
        
            
Logout
open {(localurl:Main Page}}
clickAndWait link=Log out
verifyHtmlSource glob:*You are now logged out.*

</selenium> </xml>

Table style

The body tag replaces itself with a div of class "selenium" allowing the tests to have nicer styling applied to them from CSS, for example, we added the following rules to our own MediaWiki:Common.css. <css> .selenium table {

   border: 2px solid #dde;
   background: white;
   font-family: Verdana, Arial, sans-serif;
   font-size: 12px;
   font-weight: bold;
   text-align: center;

} .selenium td {

   border: none;
   padding: 4px;
   margin: 0;

} .selenium tr {

   background: #dde;

} .selenium tr + tr {

   font-weight: normal;
   background: #eef;
   text-align: left;

} </css>

Test Automation

We need to include as part of the extension (maybe in an additional PERL script) the ability to run the tests automatically from crontab and report to us via talk page or a test log article any problems which crop up due to code or environment changes.

Automation of the selenium-core suite can be done by adding the query string parameter &auto=true (see details). An additional url can be provided &resultsUrl = [relative path] which creates an html output file. See Continuous integration section for details. By default the querystring parameter resultsUrl posts results to /postResults, which is in the path $IP/extensions/Selenium/selenium-core/core.

By creating a quick script called results.php in a temporary directory in $IP/extensions/Selenium/ with contents;

<?php

foreach($_POST as $key=>$value) {
print "$key => $value <br />";
}

?>

and redirecting resultsUrl=../../tmp/results.php.

An example of the posted parameters sent are as follows;

selenium_version => 0.8.3
selenium_revision => 1879
result => passed
totalTime => 5
numTestPasses => 1
numTestFailures => 0
numCommandPasses => 0
numCommandFailures => 0
numCommandErrors => 0
testTable_1 =>
<thead>

</thead><tbody>

</tbody>
New Test
open /wiki/index.php/Main_Page
clickAndWait link=Special pages
clickAndWait link=Categories
clickAndWait link=Selenium



numTestTotal => 1
suite => <tbody> </tbody>
Foo
<a href="/wiki/index.php?title=Special:Selenium&suite=Foo&test=Test">Test</a>

log => info: Starting test /wiki/index.php

info: Executing:

It appears that the important posted parameters are;

  • result => passed
  • totalTime => 5
  • numTestPasses => 1
  • numTestFailures => 0
  • numCommandPasses => 0
  • numCommandFailures => 0
  • numCommandErrors => 0

I think its probly best to keep all its files in its own dir (ie extensions/selenium) same as other extensions like searchlog which generate other files it should also be able to be executed from shell and run selected tests eg from cron etc.

See also