Acceptance testing can be performed by a non-technical person. That person can be your tester, manager or even client.
If you are developing a web-application (and you probably are) the tester needs nothing more than a web browser
to check that your site works correctly. You can reproduce an acceptance tester’s actions in scenarios
and run them automatically. Codeception keeps tests clean and simple
as if they were recorded from the words of an actual acceptance tester.
It makes no difference what (if any) CMS or framework is used on the site. You can even test sites created with different
languages, like Java, .NET, etc. It’s always a good idea to add tests to your website.
At least you will be sure that site features work after the latest changes were made.
Let’s say the first test you would want to run, would be signing in.
In order to write such a test, we still require basic knowledge of PHP and HTML:
This scenario can be performed either by PhpBrowser or by a “real” browser through Selenium WebDriver.
||Guzzle + Symfony BrowserKit
||Chrome or Firefox
seeElement checks if…
|…text is present in the HTML source
||…text is actually visible to the user
|Read HTTP response headers
||PHP with cURL extension
||Selenium Standalone Server, Chrome or Firefox
We will start writing our first acceptance tests with PhpBrowser.
This is the fastest way to run acceptance tests since it doesn’t require running an actual browser.
We use a PHP web scraper, which acts like a browser: It sends a request, then receives and parses the response.
Codeception uses Guzzle and Symfony BrowserKit to interact with HTML web pages.
Common PhpBrowser drawbacks:
- You can only click on links with valid URLs or form submit buttons
- You can’t fill in fields that are not inside a form
We need to specify the
url parameter in the acceptance suite config:
We should start by creating a test with the next command:
It will be placed into
$I object is used to write all interactions.
The methods of the
$I object are taken from the PhpBrowser Module. We will briefly describe them here:
We will assume that all actions starting with
have describe the initial environment.
amOnPage action sets the starting point of a test to the
PhpBrowser you can click the links and fill in the forms. That will probably be the majority of your actions.
Emulates a click on valid anchors. The URL referenced in the
href attribute will be opened.
As a parameter, you can specify the link name or a valid CSS or XPath selector.
Codeception tries to locate an element by its text, name, CSS or XPath.
You can specify the locator type manually by passing an array as a parameter. We call this a strict locator.
Available strict locator types are:
There is a special class
which may help you to generate complex XPath locators.
For instance, it can easily allow you to click an element on the last row of a table:
Clicking links is probably not what takes the most time during the testing of a website.
The most routine waste of time goes into the testing of forms. Codeception provides several ways of testing forms.
Let’s submit this sample form inside the Codeception test:
From a user’s perspective, a form consists of fields which should be filled in, and then a submit button clicked:
To match fields by their labels, you should write a
for attribute in the
From the developer’s perspective, submitting a form is just sending a valid POST request to the server.
Sometimes it’s easier to fill in all of the fields at once and send the form without clicking a ‘Submit’ button.
A similar scenario can be rewritten with only one command:
submitForm is not emulating a user’s actions, but it’s quite useful
in situations when the form is not formatted properly, for example, to discover that labels aren’t set
submitForm doesn’t send values for buttons. The last parameter allows specifying
what button values should be sent, or button values can be explicitly specified in the second parameter:
Hiding Sensitive Data
If you need to fill in sensitive data (like passwords) and hide it in logs,
you can pass instance
\Codeception\Step\Argument\PasswordArgument with the data which needs to be hidden.
thisissecret will be filled into a form but it won’t be shown in output and logs.
PhpBrowser you can test the page contents.
In most cases, you just need to check that the required text or element is on the page.
The most useful method for this is
You can check that a specific HTML element exists (or doesn’t) on a page:
We also have other useful commands to perform checks. Please note that they all start with the
Usually, as soon as any assertion fails, further assertions of this test will be skipped.
Sometimes you don’t want this - maybe you have a long-running test and you want it to run to the end.
In this case, you can use conditional assertions.
see method has a corresponding
canSee method, and
dontSee has a
Each failed assertion will be shown in the test results, but it won’t stop the test.
Within a long scenario, you should describe what actions you are going to perform and what results should be achieved.
Comment methods like
expectTo help you in making tests more descriptive:
These commands retrieve data that can be used in the test. Imagine your site generates a password for every user
and you want to check that the user can log into the site using this password:
Grabbers allow you to get a single value from the current page with commands:
Cookies, URLs, Title, etc
Actions for cookies:
Actions for checking the page title:
Actions for URLs:
A nice feature of Codeception is that most scenarios are similar, no matter of how they are executed.
PhpBrowser was emulating browser requests but how to execute such test in a real browser like Chrome or Firefox?
Selenium WebDriver can drive them so in our acceptance tests we can automate scenarios we used to test manually.
In such tests, we should concentrate more on testing the UI than on testing functionality.
“WebDriver” is the name of a protocol (specified by W3C)
to drive browsers automatically. This specification is implemented for all modern desktop and mobile browsers.
Codeception uses facebook/php-webdriver library from Facebook as PHP implementation of WebDriver protocol.
To control the browsers you need to use a program or a service to start/stop browser sessions.
In the next section, we will overview the most popular solutions.
Selenium Server is a de-facto standard for automated web and mobile testing.
It is a server that can launch and drive different browsers locally or remotely.
WebDriver protocol was initially created by Selenium before becoming a W3C standard.
This makes Selenium server the most stable complete implementation of WebDriver for today.
Selenium Server is also recommended by Codeception team.
To control browsers Selenium Server uses official tools maintained by browser vendors, like ChromeDriver for Chrome or GeckoDriver for Firefox.
This makes Selenium quite heavy to install, as it requires Java, browsers, Chrome or GeckoDriver and GUI (display server) to run browsers in.
PhantomJS is a customized WebKit-based headless browser
built for programmatic usage only. It doesn’t display a browser window and doesn’t require GUI (display server) to be installed.
This makes PhantomJS highly popular for Continuous Integration systems.
PhantomJS needs only one binary with no extra dependencies which make it the simplest WebDriver tool to install.
However, it should be noted that PhantomJS is not a real browser, so the behavior and output in real browsers may differ from PhantomJS.
And the most important: PhantomJS is not maintained anymore. So use it at your own risk.
ChromeDriver was created by Google to control Chrome and Chromium browsers programmatically.
It can be paired with Selenium Server or used as a standalone tool to drive Chrome browser.
It is simpler to set up than Selenium Server, however, it has limited support for WebDriver protocol.
To execute a test in a browser we need to change the suite configuration to use WebDriver instead of
See WebDriver Module for details.
Please note that actions executed in a browser will behave differently. For instance,
seeElement won’t just check that the element exists on a page,
but it will also check that element is actually visible to the user:
While WebDriver duplicates the functionality of PhpBrowser, it has its limitations: It can’t check headers since browsers don’t provide APIs for that.
WebDriver also adds browser-specific functionality:
They can be used to specify what event you expect to occur on a page, before continuing the test.
In this case, we are waiting for the ‘agree’ button to appear and then click it. If it didn’t appear after 30 seconds,
the test will fail. There are other
wait methods you may use, like waitForText,
waitForElementVisible and others.
If you don’t know what exact element you need to wait for, you can simply pause execution with using
since 2.3.4 version
It is possible to wait for elements pragmatically.
If a test uses element which is not on a page yet, Codeception will wait for few extra seconds before failing.
This feature is based on Implicit Wait of Selenium.
Codeception enables implicit wait only when searching for a specific element and disables in all other cases. Thus, the performance of a test is not affected.
SmartWait can be enabled by setting
wait option in WebDriver config. It expects the number of seconds to wait. Example:
With this config we have the following test:
It is important to understand that SmartWait works only with a specific locators:
#locator - CSS ID locator, works
//locator - general XPath locator, works
['css' => 'button''] - strict locator, works
But it won’t be executed for all other locator types.
See the example:
Wait and Act
waitForElement with actions inside that element you can use the performOn method.
Let’s see how you can perform some actions inside an HTML popup:
Alternatively, this can be executed using a callback, in this case the
WebDriver instance is passed as argument
For more options see
Multi Session Testing
Codeception allows you to execute actions in concurrent sessions. The most obvious case for this
is testing realtime messaging between users on a site. In order to do it, you will need to launch two browser windows
at the same time for the same test. Codeception has a very smart concept for doing this. It is called Friends:
In this case, we performed, or ‘did’, some actions in the second window with the
does method on a friend object.
Sometimes you may want to close a webpage before the end of the test. For such cases, you may use
You can also specify roles for a friend:
Some environments are hard to be reproduced manually, testing Internet Explorer 6-8 on Windows XP may be a hard thing,
especially if you don’t have Windows XP installed. This is where Cloud Testing services come to help you.
Services such as SauceLabs, BrowserStack
and others can create virtual machines on demand
and set up Selenium Server and the desired browser. Tests are executed on a remote machine in a cloud,
to access local files cloud testing services provide a special application called Tunnel.
Tunnel operates on a secured protocol and allows browsers executed in a cloud to connect to a local web server.
Cloud Testing services work with the standard WebDriver protocol. This makes setting up cloud testing really easy.
You just need to set the WebDriver configuration to:
- specify the host to connect to (depends on the cloud provider)
- authentication details (to use your account)
We recommend using params
to provide authorization credentials.
It should be mentioned that Cloud Testing services are not free. You should investigate their pricing models
and choose one that fits your needs. They also may work painfully slowly if ping times between the local server
and the cloud is too high. This may lead to random failures in acceptance tests.
In the modern era of Single Page Applications, the browser replaces the server in creating the user interface.
Unlike traditional web applications, web pages are not reloaded on user actions.
However, testing Single Page Applications can be a hard task.
There could be no information of the application state: e.g. has it completed rendering or not?
What is possible to do in this case is to use more
For applications built with the AngularJS v1.x framework,
we implemented AngularJS module which is based on Protractor
(an official tool for testing Angular apps). Under the hood, it pauses step execution
before the previous actions are completed and use the AngularJS API to check the application state.
The AngularJS module extends WebDriver so that all the configuration options from it are available.
Codeception modules can print valuable information while running.
Just execute tests with the
--debug option to see running details. For any custom output use the
On each failure, the snapshot of the last shown page will be stored in the
PhpBrowser will store the HTML code and WebDriver will save a screenshot of the page.
Additional debugging features by Codeception:
Custom Browser Sessions
By default, WebDriver module is configured to automatically start browser before the test and stop afterward.
However, this can be switched off with
start: false module configuration.
To start a browser you will need to write corresponding methods in Acceptance Helper.
WebDriver module provides advanced methods for the browser session, however, they can only be used from Helpers.
Those methods can be used to create custom commands like
$I->startBrowser() or used in before/after hooks.
Writing acceptance tests with Codeception and PhpBrowser is a good start.
You can easily test your Joomla, Drupal, WordPress sites, as well as those made with frameworks.
Writing acceptance tests is like describing a tester’s actions in PHP. They are quite readable and very easy to write.
If you need to access the database, you can use the Db Module.