the code wants the best, but there is no time for refactoring;
making edits in one place breaks logic in another;
to cover * Unit tests, it is easier to rewrite the project;
business logic is blurred by code and even by templates.
To score and justify that such a code should not live?
I often encountered such situations and it did not suit me. While searching for a suitable testing method / tool, I came across Selenium. And apply it for more than 3 years.
DevPoint conference dedicated to web development took place on April 9 in Kiev. The organizer of this event was Uniweb . As part of it, I decided to share an impression about Selenium. ')
Selenium consists of many subprojects, but wanted to highlight only three:
Selenium Core - JavaScript framework for writing and executing tests. Used in Selenium IDE and Remote Control *.
Selenium IDE - plugin for Firefox, which allows you to record and play tests. It can also generate test code for use in Selenium Remote Control.
Selenium Remote Control is a client-server system that allows you to control web browsers locally or on other computers using virtually any programming language.
As part of this report about Selenium Core there was no time to focus attention, although this project is most interesting for writing tests with nontrivial logic.
Selenium IDE
Advantages of Selenium IDE:
Intuitive interface;
the ability to record user actions;
Anyone who understands how a project should work will cope with writing tests;
automatic generation of * Unit code for various programming languages.
A spoon of tar:
Only for FireFox;
after recording the action, you still need to “finish handles”;
There is no built-in tool for getting XPath elements.
We use Selenium IDE in practice
For example, I took a lively old project, which is still the task to cover up with tests. This is a regular online store, which is used for in-house bulk purchases in one company, we don’t give names ... The first test that we write will simply log in to the system:
Recommendations for those who start using Selenium:
Do not forget the waitForPageToLoad command;
use assert * and verify * commands as often as possible;
after waitForPopUp do not forget the selectPopUp command;
after closing popUp - selectWindow;
clearly understand the difference between click and clickAndWait;
When testing ajax parts, use the waitFor * commands.
The system is very important functionality associated with the exchange rate, as it must be set manually for each day. Let's write a test covering this logic:
And the last two tests that cover the logic of creating and editing an order:
And to check our tests, the intention was to spoil the preservation of the order:
Advantages of testing in IDE:
Sequential execution of tests in the suite;
convenient modification of tests.
Minuses:
Only for FireFox;
data initialization has to be done manually;
inability to test cron scripts.
Selenium Remote Control
Selenium Remote Control is an http daemon that accepts commands via GET and executes them. API for communication with Selenium RC is almost for all programming languages. This report is only about the API for PHP, which is provided with PHPUnit
As mentioned earlier in the Selenium IDE there is a nice option for generating code for * Unit:
Thus, you can simply copy the code and execute it in your PHPUnit suite.
Also in PHPUnit - Selenium it is possible to run tests written in Selenium IDE:
class SeleneseTests extends PHPUnit_Extensions_SeleniumTestCase { public static $ seleneseDirectory = '/ devpoint / ide' ;
protected function setUp ( ) { $ this -> setBrowser ( "* firefox" ) ; $ this -> setBrowserUrl ( " test.devpoint.com.ua/" ) ; } }
Without a file can not do ...
PHPUnit_Extensions_SeleniumTestCase cannot interpret suite files with the Selenium IDE;
to run the test, PHPUnit always launches a new browser;
PHPUnit 3.4.x does not properly handle the logic of the wait commands.
The execution of tests in the Selenium IDE and in PHPUnit differ in their approach. Selenium IDE assumes that tests performed in a suite may be dependent on each other, while in PHPUnit each test is independent of the previous *. And for each test PHPUnit sends commands to re-initialize the browser and, accordingly, our tests are performed with an error, since they depend on the first test. To solve this problem, the logic was written to execute the suite file created in Selenium IDE.
To solve the problem with the execution of the wait * commands, you need to consider how they are executed in PHPUnit:
for ( $ second = 0 ;; $ second ++ ) { if ( $ second > = 60 ) $ this -> fail ( "timeout" ) ; try { if ( "Orders" == $ this -> getText ( "// html / body / table / tbody / tr / td [2] / form / table / tbody / tr / td" ) ) break ; } catch ( Exception $ e ) { } sleep ( 1 ) ; }
In fact, we loop the execution of the command for a certain interval and wait until our condition becomes true. Implementing PHPUnit - Selenium sending the Selenium RC command expects only two answers from it, that everything is good or that everything is bad. If the ERROR answer came, then it immediately closes the browser, writes that an error occurred and, accordingly, our cycle will send commands to an already closed Selenium RC session.
I put the code with the solution of these problems on github and I will not dwell on it.
Another of the nice things about Selenium RC is that he can take screenshots when an error is detected:
The downside is that the screenshots do not highlight the location of the error, but the text in PHPUnit is usually easy to understand what is wrong.
We pull the strings not FireFox
According to the developers, Selenium RC supports the following browsers:
chrome
iexplore
firefox3
googlechrome
konqueror
firefox2
safari
opera
In fact, to achieve correct execution in these browsers is not always possible the first time, but this is not in the framework of this report. The only thing I’ll note in Firefox, IE and Chrome under Windows is almost never a problem in Safari under MacOS.
To run our tests in different browsers, it is enough to describe an array in the static $ browsers variable with the settings for accessing Selenium RC: