diff --git a/RoboFile.php b/RoboFile.php
index 0bdb3109e..944bdf8b1 100644
--- a/RoboFile.php
+++ b/RoboFile.php
@@ -129,6 +129,46 @@ public function buildDocs()
$this->changelog();
}
+ public function buildDocsGuides() {
+ $guides = Finder::create()
+ ->ignoreVCS(true)
+ ->depth('== 0')
+ ->name('*.md')
+ ->sortByName()
+ ->in('guides');
+
+ $guidesLinks = [];
+
+ foreach ($guides as $file) {
+ $name = substr($file->getBasename(), 0, -3);
+ $titleName = preg_replace("(\d+-)", '', $name);
+
+ $link = "/docs/$titleName";
+ $editLink = 'https://github.com/Codeception/codeception.github.com/edit/master/guides/' . $file->getBasename();
+ $title = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\\1 \\2', $titleName);
+ $title = preg_replace('/([a-z\d])([A-Z])/', '\\1 \\2', $title);
+
+ $contents = file_get_contents($file->getPathname());
+
+ foreach ([$file->getBasename(), $titleName . '.md'] as $filename) {
+ $this->taskWriteToFile('docs/' . $filename)
+ ->line('---')
+ ->line('layout: doc')
+ ->line("title: $title - Codeception Docs")
+ ->line('---')
+ ->line('')
+ ->line('')
+ ->text($contents)
+ ->line('')
+ ->line('
- {% include cloudways.html %}
-
-
diff --git a/_posts/2022-07-02-codeception-5.markdown b/_posts/2022-07-02-codeception-5.markdown
new file mode 100644
index 000000000..d1d4f6b16
--- /dev/null
+++ b/_posts/2022-07-02-codeception-5.markdown
@@ -0,0 +1,172 @@
+---
+layout: post
+title: "Codeception 5"
+date: 2022-07-02 01:03:50
+---
+
+Codeception 5.0 is out!
+
+This release is **PHP 8+** only, so we are back on track with modern PHP. We are **dropping support for PHPUnit < 9**, and are technically ready for PHPUnit 10. And we also support **Symfony 6** without dropping support of previous Symfony versions. As always, we did our best to keep backward compatibility so if you can update your dependencies, all tests should be working for you.
+
+So let's take a look at new features:
+
+## New Directory Structure
+
+Codeception 5 will match PSR-12 standard. So all tests and classes will have their own namespace `Tests`. The directory structure was updated accordingly:
+
+```
+tests/
+ _output
+ Acceptance
+ Functional
+ Support/
+ Data/
+ _generated/
+ Helper/
+ Unit/
+```
+
+All suite name will have their own namespace, as well as actor and helper classes:
+
+```php
+amOnPage('/');
+ }
+}
+```
+
+New directory structure will be generated by running `codecept bootstrap`. The directory structure is set with a new default config, so the previous directory structure is still valid.
+
+## Attributes
+
+Annotations were an essential part of Codeception testing framework. Even though they were not native language constructs, they proved to be quite good to separate a test from its metadata. We believe that test should not include code that doesn't belong to the test scenario.
+
+So we were glad that native Attributes have landed PHP world. In this release we encourage our users to start using them:
+
+```php
+#[Group('important')]
+#[Group('api')]
+#[Examples('GET', '/users')]
+#[Examples('GET', '/posts')]
+#[Env('staging-alpha')]
+#[Env('staging-beta')]
+#[Env('production')]
+#[Prepare('startServices')]
+public function testApiRequests(ApiTester $I, Example $e)
+{
+ $I->send($e[0], $e[1]);
+ $I->seeResponseCodeIsSuccessful();
+ $I->seeResponseIsJson();
+}
+```
+
+As you see, attributes decouple all preparation steps, keeping the test scenario minimal. We also keep supporting annotations, so an urgent upgrade is not needed. Attributes can't do something that traditional annotations can't, they are just a modern alternative.
+
+List of available attributes (all under `Codeception\Attribute`) namespace:
+
+* `Before` - specifies the method that should be executed before each test
+* `After` - specifies the method that should be executed after each test
+* `Group` - set the group for the test
+* `Skip` - skips the current test
+* `Incomplete` - marks test as incomplete
+* `Depends` - sets the test that must be executed before the current one
+* `Prepare` - sets a method to execute to initialize the environment (launch server, browser, etc)
+* `DataProvider` - specifies a method that provides data for data-driven tests
+* `Examples` - sets data for data-driven tests inside the annotation
+* `Env` - sets environment value for the current test
+* `Given`, `When`, `Then` - marks a method as BDD step
+
+## Debugging
+
+Do you remember, `Hoa\Console`? Unfortunately, this library was deprecated and we were looking for a modern alternative that could power `codecept console` and `$I->pause();` commands. We switched to [PsySH](https://psysh.org) a PHP REPL.
+
+An interactive console is used to pause a test in the given state. While in pause you can try different Codeception commands, and check variable values. Instead of fixing tests blindly, you can start an interactive session. This is quite a similar effect you can get with a real debugger like XDebug but focused on Codeception commands. Especially this is helpful to write acceptance tests as the test scenario can be planned while executing a test. So basic scenario can be written as:
+
+```php
+$I->amOnPage('/');
+$I->pause();
+```
+
+After opening a page you will be able to try commands in a browser. If a command succeeds you can use it in your tests.
+
+Also new functions were added:
+
+* `codecept_pause()` - starts interactive pause anywhere in debug mode
+* `codecept_debug()` - prints a variable into console using Symfony VarDumper
+
+## Sharding
+
+[Parallel Execution](/docs/ParallelExecution) guide has been rewritten and focused on a new feature: sharding. It is the simplest way to run slow tests (think of acceptance tests first) in parallel on multiple agents.
+
+In this case, you specify the batch of tests that should be executed independently and each job picks up its own not intersecting group of tests to run them.
+
+```
+# first job
+./venodor/bin/codecept run --shard 1/3
+
+# second job
+./venodor/bin/codecept run --shard 2/3
+
+# third job
+./venodor/bin/codecept run --shard 3/3
+```
+
+This feature reduces the need for complex configuration and usage of `robo` task runner to split tests.
+
+It is recommended to use sharding to parallelize tests between multiple jobs as the simplest approach. Unfortunately, PHP doesn't have native multi-threading for test parallelization, and even if it had, it doesn't solve the problem of running slow browser tests that interacts with a whole application. So only horizontal scaling by jobs can be suggested as a long-running approach. The more build agents you add to your Continuous Integration server, the fastest tests will run. That's it!
+
+## Grep and Filter
+
+New options `--grep` and `--filter` were introduced to select tests by part of their name. Actually, it is the same option and an alias. `--grep` is a common way to select tests to execute in NodeJS test runners, so we ported it to Codeception. But as usual, specific tests can also be executed by group or specifying a test signature.
+
+```
+php venodor/bin/codecept run --grep "user"
+```
+
+## Other Changes
+
+Please go through the list of changes introduced to see if they don't affect your codebase:
+
+* Requires PHP 8.0 or higher
+* Compatible with PHPUnit 9 and ready for PHPUnit 10
+* Compatible with Symfony 4.4 - 6.0
+* Stricter check for phpdotenv v5 (older versions are not supported)
+* Throw exception if actor setting is missing in suite configuration
+* Removed `generate:cept` command (Cept format is deprecated)
+* Removed settings `disallow_test_output` and `log_incomplete_skipped`.
+* Removed setting `paths.log` (it was replaced by `paths.output` in Codeception 2.3)
+* Removed suite setting `class_name` (replaced by `actor` in Codeception 2.3)
+* Removed global setting `actor` (replaced by `actor_prefix` in Codeception 2.3)
+* Removed `Configuration::logDir` method (replaced by `Configuration::outputDir` in 2.0)
+* Moved XmlBuilder class to module-soap
+* Decoupled test execution and reporting from PHPUnit
+* Custom reporters implementing TestListener are no longer supported and must be converted to Extensions
+* Added optional value to `fail-fast` option (#6275) by #Verest
+* Removed `JSON` and `TAP` loggers
+* Removed code coverage blacklist functionality
+* Removed deprecated class aliases
+ - Codeception\TestCase\Test
+ - Codeception\Platform\Group
+ - Codeception\Platform\Group
+ - Codeception\TestCase
+* Introduced strict types in the code base.
+
+[Complete Changelog](https://raw.githubusercontent.com/Codeception/Codeception/5.0/CHANGELOG-5.x.md)
+
+---
+
+We really happy that we are finally here with Codeception 5. This release was crafted during wartime, which happens in Ukraine. It is mentally and morally hard to work on tech products knowing that at any point this peaceful virtual life can end at any moment by a random missile. Codeception was created in 2011 by Michael Bodnarchuk in Kyiv, and today in 2022 he also stays there writing this post. If you want to support Codeception, all the Ukrainian PHP community, and all our brave nation who stands for democracy against barbaric Russian invasion, consider **[donating to Ukrainian charities](https://stand-with-ukraine.pp.ua)**. Not a single time. Every month until the war ends. Every time you travel or enjoy tasty food in a restaurant think of people who are forced to defend their land, or who fled their homes. Glory to Ukraine!
+
+This release wouldn't be possible without the hard work of [Gintautas Misselis](https://github.com/Naktibalda) who keeps constant work on modernizing internals and keeping Codeception up to date. Also we are really thankful to [Gustavo Nieves
+](https://github.com/TavoNiievez) who did a lot of work transitioning Codeception to new Symfony and more! Thanks to our maintainers! If you want to support our work we have [OpenCollective](https://opencollective.com/codeception)!
+
+
diff --git a/docs/01-Introduction.md b/docs/01-Introduction.md
index 964a725eb..52db1708b 100644
--- a/docs/01-Introduction.md
+++ b/docs/01-Introduction.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 01-Introduction - Codeception - Documentation
+title: Introduction - Codeception Docs
---
+
# Introduction
The idea behind testing is not new. You can't sleep well if you are not confident
@@ -49,9 +50,7 @@ With acceptance tests, you can be confident that users, following all the define
#### Sample acceptance test
-{% highlight php %}
-
-amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', [
@@ -59,8 +58,7 @@ $I->submitForm('#signup', [
'email' => 'miles@davis.com'
]);
$I->see('Thank you for Signing Up!');
-
-{% endhighlight %}
+```
### Functional Tests
@@ -73,17 +71,14 @@ For functional tests, your application needs to be structured in order to run in
#### Sample functional test
-{% highlight php %}
-
-amOnPage('/');
$I->click('Sign Up');
$I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']);
$I->see('Thank you for Signing Up!');
$I->seeEmailSent('miles@davis.com', 'Thank you for registration');
$I->seeInDatabase('users', ['email' => 'miles@davis.com']);
-
-{% endhighlight %}
+```
> This looks very similar to acceptance tests. The behavior is the same, however, the test is executed inside PHP without launching a browser.
@@ -103,9 +98,7 @@ The better you understand the testing scenario, the faster you can update it for
#### Sample integration test
-{% highlight php %}
-
- 'Davis'
]);
}
-
-{% endhighlight %}
+```
## Conclusion
@@ -129,9 +121,4 @@ It allows writing unit, functional, integration, and acceptance tests in a singl
All Codeception tests are written in a descriptive manner.
Just by looking at the test body, you can clearly understand what is being tested and how it is performed.
-
-
-
-* **Next Chapter: [GettingStarted >](/docs/02-GettingStarted)**
-
-
+
diff --git a/docs/02-GettingStarted.md b/docs/02-GettingStarted.md
index 943034451..6c81398a4 100644
--- a/docs/02-GettingStarted.md
+++ b/docs/02-GettingStarted.md
@@ -1,47 +1,45 @@
---
layout: doc
-title: 02-GettingStarted - Codeception - Documentation
+title: Getting Started - Codeception Docs
---
+
# Getting Started
Let's take a look at Codeception's architecture. We'll assume that you have already [installed](https://codeception.com/install) it
and bootstrapped your first test suites. Codeception has generated three of them: unit, functional, and acceptance.
They are well described in the [previous chapter](https://codeception.com/docs/01-Introduction). Inside your __/tests__ folder you will have three `.yml` config files and three directories
-with names corresponding to these suites: `unit`, `functional`, `acceptance`. Suites are independent groups of tests with a common purpose.
+with names corresponding to these suites: `Unit`, `Functional`, `Acceptance`. Suites are independent groups of tests with a common purpose.
## The Codeception Syntax
Codeception follows simple naming rules to make it easy to remember (as well as easy to understand) its method names.
* **Actions** start with a plain english verb, like "click" or "fill". Examples:
- {% highlight php %}
-
- click('Login');
- $I->fillField('#input-username', 'John Dough');
- $I->pressKey('#input-remarks', 'foo');
-
-{% endhighlight %}
+
+```php
+$I->click('Login');
+$I->fillField('#input-username', 'John Dough');
+$I->pressKey('#input-remarks', 'foo');
+```
+
* **Assertions** always start with "see" or "dontSee". Examples:
- {% highlight php %}
-
- see('Welcome');
- $I->seeInTitle('My Company');
- $I->seeElement('nav');
- $I->dontSeeElement('#error-message');
- $I->dontSeeInPageSource('
');
-
-{% endhighlight %}
+
+```php
+$I->see('Welcome');
+$I->seeInTitle('My Company');
+$I->seeElement('nav');
+$I->dontSeeElement('#error-message');
+$I->dontSeeInPageSource('');
+```
+
* **Grabbers** take information. The return value of those are meant to be saved as variables and used later. Example:
- {% highlight php %}
- grabAttributeFrom('#login-form', 'method');
- $I->assertEquals('post', $method);
-
-{% endhighlight %}
+```php
+$method = $I->grabAttributeFrom('#login-form', 'method');
+$I->assertEquals('post', $method);
+```
+
## Actors
@@ -54,60 +52,56 @@ Codeception tries to solve 90% of possible testing issues in its modules, so you
We think that you can spend more time on writing tests and less on writing support code to make those tests run.
By default, AcceptanceTester relies on PhpBrowser module, which is set in the `tests/acceptance.suite.yml` configuration file:
-{% highlight yaml %}
-
+```yaml
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost/myapp/
- \Helper\Acceptance
+```
-{% endhighlight %}
In this configuration file you can enable/disable and reconfigure modules for your needs.
When you change the configuration, the actor classes are rebuilt automatically. If the actor classes are not created or updated as you expect,
try to generate them manually with the `build` command:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept build
+```
-{% endhighlight %}
## Writing a Sample Test
Codeception has its own testing format called Cest (Codecept + Test).
To start writing a test we need to create a new Cest file. We can do that by running the following command:
-{% highlight bash %}
+```bash
+php vendor/bin/codecept generate:cest Acceptance Signin
+```
+
-php vendor/bin/codecept generate:cest acceptance Signin
+This will generate `SigninCest.php` file inside `tests/Acceptance` directory. Let's open it:
-{% endhighlight %}
+```php
+see('Hello, davert');
}
}
+```
-{% endhighlight %}
This scenario can probably be read by non-technical people. If you just remove all special chars like braces, arrows and `$`,
this test transforms into plain English text:
-{% highlight yaml %}
+```yaml
I amOnPage '/login'
I fillField 'Username','davert'
I fillField 'Password','qwerty'
I click 'Login'
I see 'Hello, davert'
+```
-{% endhighlight %}
Codeception generates this text representation from PHP code by executing:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept generate:scenarios
+```
-{% endhighlight %}
These generated scenarios will be stored in your `_data` directory in text files.
Before we execute this test, we should make sure that the website is running on a local web server.
Let's open the `tests/acceptance.suite.yml` file and replace the URL with the URL of your web application:
-{% highlight yaml %}
-
+```yaml
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: 'http://myappurl.local'
- \Helper\Acceptance
+```
-{% endhighlight %}
After configuring the URL we can run this test with the `run` command:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run
+```
-{% endhighlight %}
This is the output we should see:
-{% highlight bash %}
-
+```bash
Acceptance Tests (1) -------------------------------
✔ SigninCest: sign in successfully
----------------------------------------------------
@@ -187,21 +181,19 @@ Acceptance Tests (1) -------------------------------
Time: 1 second, Memory: 21.00Mb
OK (1 test, 1 assertions)
+```
-{% endhighlight %}
Let's get some detailed output:
-{% highlight bash %}
-
+```
php vendor/bin/codecept run acceptance --steps
+```
-{% endhighlight %}
We should see a step-by-step report on the performed actions:
-{% highlight bash %}
-
+```bash
Acceptance Tests (1) -------------------------------
SigninCest: Login to website
Signature: SigninCest.php:signInSuccessfully
@@ -218,8 +210,8 @@ Scenario --
Time: 0 seconds, Memory: 21.00Mb
OK (1 test, 1 assertions)
+```
-{% endhighlight %}
This simple test can be extended to a complete scenario of site usage, therefore,
by emulating the user's actions, you can test any of your websites.
@@ -229,9 +221,13 @@ If your tests share common setup actions put them into `_before` method.
For instance, to test CRUD we want 4 methods to be implemented and all next tests should start at `/task` page:
-{% highlight php %}
-
+```php
pause()`** somewhere in your test, then run the test in [debug mode](#Debugging).
-
-Interactive Pause requires [`hoa/console`](https://hoa-project.net/) which is not installed by default. To install it, run:
-
-{% highlight bash %}
-
-php composer.phar require --dev hoa/console
-
-{% endhighlight %}
-
-{% highlight php %}
-
-pause();
-
-{% endhighlight %}
-
-The execution of the test is stopped at this point, and a console is shown where you can try all available commands "live".
-This can be very useful when you write functional, acceptance, or api test.
-
-
-
-Inside Interactive Pause you can use the entire power of the PHP interpreter: variables, functions, etc.
-You can access the result of the last executed command in a variable called `$result`.
-
-In acceptance or functional test you can save page screenshot or html snapshot.
-
-{% highlight php %}
-
-makeHtmlSnapshot();
-
-// inside WebDriver
-// saves screenshot and prints a path to created file
-$I->makeScreenshot();
-
-{% endhighlight %}
-
-To try commands without running a single test you can launch interactive console:
-
-{% highlight bash %}
-
-$ php vendor/bin/codecept console suitename
-
-{% endhighlight %}
-
-Now you can execute all the commands of a corresponding Actor class and see the results immediately.
-
## BDD
Codeception allows execution of user stories in Gherkin format in a similar manner as is done in Cucumber or Behat.
@@ -337,60 +276,53 @@ The same goes for suite configs. For example, the `unit.suite.yml` will be merge
Tests can be started with the `run` command:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run
+```
-{% endhighlight %}
With the first argument you can run all tests from one suite:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run acceptance
+```
-{% endhighlight %}
To limit tests run to a single class, add a second argument. Provide a local path to the test class, from the suite directory:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run acceptance SigninCest.php
+```
-{% endhighlight %}
Alternatively you can provide the full path to test file:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run tests/acceptance/SigninCest.php
+```
-{% endhighlight %}
You can further filter which tests are run by appending a method name to the class, separated by a colon (for Cest or Test formats):
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run tests/acceptance/SigninCest.php:^anonymousLogin$
+```
-{% endhighlight %}
You can provide a directory path as well. This will execute all acceptance tests from the `backend` dir:
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run tests/acceptance/backend
+```
-{% endhighlight %}
Using regular expressions, you can even run many different test methods from the same directory or class.
For example, this will execute all acceptance tests from the `backend` dir beginning with the word "login":
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run tests/acceptance/backend:^login
+```
-{% endhighlight %}
To execute a group of tests that are not stored in the same directory, you can organize them in [groups](https://codeception.com/docs/07-AdvancedUsage#Groups).
@@ -398,26 +330,20 @@ To execute a group of tests that are not stored in the same directory, you can o
To generate JUnit XML output, you can provide the `--xml` option, and `--html` for HTML report.
-{% highlight bash %}
-
+```bash
php vendor/bin/codecept run --steps --xml --html
+```
-{% endhighlight %}
This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be stored in the `tests/_output/` directory.
-To see all the available options, run the following command:
-
-{% highlight bash %}
-
-php vendor/bin/codecept help run
-
-{% endhighlight %}
+Learn more about [available reports](/docs/Reporting).
## Debugging
To receive detailed output, tests can be executed with the `--debug` option.
-You may print any information inside a test using the `codecept_debug` function.
+
+Learn more about [debugging](/docs/Debugging).
### Generators
@@ -439,10 +365,4 @@ There are plenty of useful Codeception commands:
We have taken a look into the Codeception structure. Most of the things you need were already generated by the `bootstrap` command.
After you have reviewed the basic concepts and configurations, you can start writing your first scenario.
-
-
-
-* **Next Chapter: [AcceptanceTests >](/docs/03-AcceptanceTests)**
-* **Previous Chapter: [< Introduction](/docs/01-Introduction)**
-
-
+
diff --git a/docs/03-AcceptanceTests.md b/docs/03-AcceptanceTests.md
index 7e08c6138..c4dc6b6e1 100644
--- a/docs/03-AcceptanceTests.md
+++ b/docs/03-AcceptanceTests.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 03-AcceptanceTests - Codeception - Documentation
+title: Acceptance Tests - Codeception Docs
---
+
# Acceptance Testing
Acceptance testing can be performed by a non-technical person. That person can be your tester, manager or even client.
@@ -20,16 +21,13 @@ At least you will be sure that site features work after the latest changes were
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:
-{% highlight php %}
-
-amOnPage('/login');
$I->fillField('username', 'davert');
$I->fillField('password', 'qwerty');
$I->click('LOGIN');
$I->see('Welcome, Davert!');
-
-{% endhighlight %}
+```
**This scenario can be performed either by PhpBrowser or by a "real" browser through WebDriver**.
@@ -57,8 +55,7 @@ Common PhpBrowser drawbacks:
We need to specify the `url` parameter in the acceptance suite config:
-{% highlight yaml %}
-
+```yaml
# acceptance.suite.yml
actor: AcceptanceTester
modules:
@@ -66,39 +63,31 @@ modules:
- PhpBrowser:
url: http://www.example.com/
- \Helper\Acceptance
-
-{% endhighlight %}
+```
We should start by creating a test with the next command:
-{% highlight php %}
- vendor/bin/codecept g:cest acceptance Signin
-
-{% endhighlight %}
+```
+php vendor/bin/codecept g:cest acceptance Signin
+```
It will be placed into `tests/acceptance` directory.
-{% highlight php %}
-
-amOnPage('/login');
-
-{% endhighlight %}
+```
We will assume that all actions starting with `am` and `have` describe the initial environment.
The `amOnPage` action sets the starting point of a test to the `/login` page.
@@ -110,9 +99,7 @@ With the `PhpBrowser` you can click the links and fill in the forms. That will p
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.
-{% highlight php %}
-
-click('Log in');
// CSS selector applied
$I->click('#login a');
@@ -120,8 +107,7 @@ $I->click('#login a');
$I->click('//a[@id=login]');
// Using context as second argument
$I->click('Login', '.nav');
-
-{% endhighlight %}
+```
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**.
@@ -134,24 +120,19 @@ Available strict locator types are:
* link
* class
-{% highlight php %}
-
-click(['link' => 'Login']);
$I->click(['class' => 'btn']);
-
-{% endhighlight %}
+```
There is a special class [`Codeception\Util\Locator`](https://codeception.com/docs/reference/Locator)
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:
-{% highlight php %}
-
+```php
$I->click('Edit' , \Codeception\Util\Locator::elementAt('//table/tr', -1));
-
-{% endhighlight %}
+```
#### Forms
@@ -160,8 +141,7 @@ The most routine waste of time goes into the testing of forms. Codeception provi
Let's submit this sample form inside the Codeception test:
-{% highlight html %}
-
+```html
-
-{% endhighlight %}
+```
From a user's perspective, a form consists of fields which should be filled in, and then a submit button clicked:
-{% highlight php %}
-
-fillField('Name', 'Miles');
// we can use input name or id
$I->fillField('user[email]','miles@davis.com');
$I->selectOption('Gender','Male');
$I->click('Update');
-
-{% endhighlight %}
+```
To match fields by their labels, you should write a `for` attribute in the `label` tag.
@@ -197,16 +173,13 @@ From the developer's perspective, submitting a form is just sending a valid POST
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:
-{% highlight php %}
-
-submitForm('#update_form', array('user' => array(
'name' => 'Miles',
'email' => 'Davis',
'gender' => 'm'
)));
-
-{% endhighlight %}
+```
The `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
@@ -215,9 +188,7 @@ or that fields have unclean names or badly written IDs, or the form is sent by a
By default, `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:
-{% highlight php %}
-
-submitForm('#update_form', array('user' => array(
'name' => 'Miles',
'email' => 'Davis',
@@ -230,23 +201,19 @@ $I->submitForm('#update_form', array('user' => array(
'gender' => 'm',
'submitButton' => 'Update'
)));
-
-{% endhighlight %}
+```
##### 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.
-{% highlight php %}
-
-amOnPage('/form/password_argument');
$I->fillField('password', new PasswordArgument('thisissecret'));
-
-{% endhighlight %}
+```
`thisissecret` will be filled into a form but it won't be shown in output and logs.
@@ -257,9 +224,7 @@ In most cases, you just need to check that the required text or element is on th
The most useful method for this is `see()`:
-{% highlight php %}
-
-see('Thank you, Miles');
// We check that 'Thank you, Miles' is inside an element with 'notice' class.
@@ -268,30 +233,23 @@ $I->see('Thank you, Miles', '.notice');
$I->see('Thank you, Miles', "//table/tr[2]");
// We check this message is *not* on the page.
$I->dontSee('Form is filled incorrectly');
-
-{% endhighlight %}
+```
You can check that a specific HTML element exists (or doesn't) on a page:
-{% highlight php %}
-
-seeElement('.notice');
$I->dontSeeElement('.error');
-
-{% endhighlight %}
+```
We also have other useful commands to perform checks. Please note that they all start with the `see` prefix:
-{% highlight php %}
-
-seeInCurrentUrl('/user/miles');
$I->seeCheckboxIsChecked('#agree');
$I->seeInField('user[name]', 'Miles');
$I->seeLink('Login');
-
-{% endhighlight %}
+```
#### Conditional Assertions
@@ -300,14 +258,11 @@ Sometimes you don't want this - maybe you have a long-running test and you want
In this case, you can use conditional assertions.
Each `see` method has a corresponding `canSee` method, and `dontSee` has a `cantSee` method:
-{% highlight php %}
-
-canSeeInCurrentUrl('/user/miles');
$I->canSeeCheckboxIsChecked('#agree');
$I->cantSeeInField('user[name]', 'Miles');
-
-{% endhighlight %}
+```
Each failed assertion will be shown in the test results, but it won't stop the test.
@@ -315,14 +270,12 @@ Conditional assertions are disabled in bootstrap setup. To enable them you shoul
> If you started project as `codecept init acceptance` they should be already enabled in config
-{% highlight yaml %}
-
+```yaml
# in acceptance.suite.yml
# or in codeception.yml inside suites section
step_decorators:
- \Codeception\Step\ConditionalAssertion
-
-{% endhighlight %}
+```
Then rebuild actors with `codecept build` command.
@@ -331,25 +284,20 @@ Then rebuild actors with `codecept build` command.
Within a long scenario, you should describe what actions you are going to perform and what results should be achieved.
Comment methods like `amGoingTo`, `expect`, `expectTo` help you in making tests more descriptive:
-{% highlight php %}
-
-amGoingTo('submit user form with invalid values');
$I->fillField('user[email]', 'miles');
$I->click('Update');
$I->expect('the form is not submitted');
$I->see('Form is filled incorrectly');
-
-{% endhighlight %}
+```
#### Grabbers
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:
-{% highlight php %}
-
-fillField('email', 'miles@davis.com');
$I->click('Generate Password');
$password = $I->grabTextFrom('#password');
@@ -357,54 +305,41 @@ $I->click('Login');
$I->fillField('email', 'miles@davis.com');
$I->fillField('password', $password);
$I->click('Log in!');
-
-{% endhighlight %}
+```
Grabbers allow you to get a single value from the current page with commands:
-{% highlight php %}
-
-grabTextFrom('.token');
$password = $I->grabTextFrom("descendant::input/descendant::*[@id = 'password']");
$api_key = $I->grabValueFrom('input[name=api]');
-
-{% endhighlight %}
+```
#### Cookies, URLs, Title, etc
Actions for cookies:
-{% highlight php %}
-
-setCookie('auth', '123345');
$I->grabCookie('auth');
$I->seeCookie('auth');
-
-{% endhighlight %}
+```
Actions for checking the page title:
-{% highlight php %}
-
-seeInTitle('Login');
$I->dontSeeInTitle('Register');
-
-{% endhighlight %}
+```
Actions for URLs:
-{% highlight php %}
-
-seeCurrentUrlEquals('/login');
$I->seeCurrentUrlMatches('~^/users/(\d+)~');
$I->seeInCurrentUrl('user/1');
$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~');
-
-{% endhighlight %}
+```
## WebDriver
@@ -457,8 +392,7 @@ To execute a test in a browser you need to change the suite configuration to use
Modify your `acceptance.suite.yml` file:
-{% highlight yaml %}
-
+```yaml
actor: AcceptanceTester
modules:
enabled:
@@ -466,20 +400,16 @@ modules:
url: {{your site URL}}
browser: chrome
- \Helper\Acceptance
-
-{% endhighlight %}
+```
See [WebDriver Module](https://codeception.com/docs/modules/WebDriver) 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:
-{% highlight php %}
-
-seeElement('#modal');
-
-{% endhighlight %}
+```
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:
@@ -492,13 +422,10 @@ They can be used to specify what event you expect to occur on a page, before con
For example:
-{% highlight php %}
-
-waitForElement('#agree_button', 30); // secs
$I->click('#agree_button');
-
-{% endhighlight %}
+```
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](https://codeception.com/docs/modules/WebDriver#waitForText),
@@ -506,12 +433,9 @@ the test will fail. There are other `wait` methods you may use, like [waitForTex
If you don't know what exact element you need to wait for, you can simply pause execution with using `$I->wait()`
-{% highlight php %}
-
-wait(3); // wait for 3 secs
-
-{% endhighlight %}
+```
#### SmartWait
@@ -522,23 +446,18 @@ Codeception enables implicit wait only when searching for a specific element and
SmartWait can be enabled by setting `wait` option in WebDriver config. It expects the number of seconds to wait. Example:
-{% highlight yaml %}
-
+```yaml
wait: 5
-
-{% endhighlight %}
+```
With this config we have the following test:
-{% highlight php %}
-
-waitForElement(['css' => '#click-me'], 5);
// to wait for element on page
$I->click(['css' => '#click-me']);
-
-{% endhighlight %}
+```
It is important to understand that SmartWait works only with a specific locators:
@@ -549,9 +468,7 @@ It is important to understand that SmartWait works only with a specific locators
But it won't be executed for all other locator types.
See the example:
-{% highlight php %}
-
-click('Login'); // DISABLED, not a specific locator
$I->fillField('user', 'davert'); // DISABLED, not a specific locator
$I->fillField(['name' => 'password'], '123456'); // ENABLED, strict locator
@@ -560,8 +477,7 @@ $I->see('Hello, Davert'); // DISABLED, Not a locator
$I->seeElement('#userbar'); // ENABLED
$I->dontSeeElement('#login'); // DISABLED, can't wait for element to hide
$I->seeNumberOfElements(['css' => 'button.link'], 5); // DISABLED, can wait only for one element
-
-{% endhighlight %}
+```
#### Retry
@@ -569,24 +485,18 @@ When it's hard to define condition to wait for, we can retry a command few times
For instance, if you try to click while it's animating you can try to do it few times until it freezes.
Each action and assertion have an alias prefixed with `retry` which allows to retry a flaky command.
-{% highlight php %}
-
-retryClick('flaky element');
$I->retrySee('Something changed');
-
-{% endhighlight %}
+```
Retry can be configured via `$I->retry()` command, where you can set number of retries and initial interval:
interval will be doubled on each unsuccessful execution.
-{% highlight php %}
-
- 400ms + 800ms + 1600ms + 3200ms = 6000ms
$I->retry(4, 400);
-
-{% endhighlight %}
+```
`$I->retry` takes 2 parameters:
* number of retries (1 by default)
@@ -596,28 +506,23 @@ Retries are disabled by default. To enable them you should add retry step decora
> If you started project as `codecept init acceptance` they should be already enabled in config
-{% highlight yaml %}
-
+```yaml
# in acceptance.suite.yml
# or in codeception.yml inside suites section
step_decorators:
- \Codeception\Step\Retry
-
-{% endhighlight %}
+```
Then add `\Codeception\Lib\Actor\Shared\Retry` trait into `AcceptanceTester` class:
-{% highlight php %}
-
-performOn('.confirm', \Codeception\Util\ActionSequence::build()
->see('Warning')
->see('Are you sure you want to delete this?')
->click('Yes')
);
-
-{% endhighlight %}
+```
Alternatively, this can be executed using a callback, in this case the `WebDriver` instance is passed as argument
-{% highlight php %}
-
-performOn('.confirm', function(\Codeception\Module\WebDriver $I) {
$I->see('Warning');
$I->see('Are you sure you want to delete this?');
$I->click('Yes');
});
-
-{% endhighlight %}
+```
For more options see [`performOn()` reference](https://codeception.com/docs/modules/WebDriver#performOn).
@@ -663,39 +562,31 @@ We may try to hit the "close" button but if this action fails (no popup on page)
This is how it can be implemented:
-{% highlight php %}
-
-amOnPage('/');
$I->tryToClick('x', '.alert');
// continue execution
-
-{% endhighlight %}
+```
You can also use `tryTo` as condition for your tests:
-{% highlight php %}
-
-tryToSeeElement('.alert')) {
$I->waitForText('Do you accept cookies?');
$I->click('Yes');
}
-
-{% endhighlight %}
+```
A/B testing is disabled by default. To enable it you should add corresponding step decorators to suite config:
> If you started project as `codecept init acceptance` in Codeception >= 3.0 they should be already enabled in config
-{% highlight yaml %}
-
+```yaml
# in acceptance.suite.yml
# or in codeception.yml inside suites section
step_decorators:
- \Codeception\Step\TryTo
-
-{% endhighlight %}
+```
Then rebuild actors with `codecept build` command.
@@ -705,9 +596,7 @@ Codeception allows you to execute actions in concurrent sessions. The most obvio
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**:
-{% highlight php %}
-
-amOnPage('/messages');
$nick = $I->haveFriend('nick');
$nick->does(function(AcceptanceTester $I) {
@@ -718,38 +607,31 @@ $nick->does(function(AcceptanceTester $I) {
});
$I->wait(3);
$I->see('Hello all!', '.message');
-
-{% endhighlight %}
+```
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 `leave()`.
You can also specify roles for a friend:
-{% highlight php %}
-
-haveFriend('nickAdmin', adminStep::class);
$nickAdmin->does(function(adminStep $I) {
// Admin does ...
});
$nickAdmin->leave();
-
-{% endhighlight %}
+```
Multi session testing is disabled by default. To enable it, add `\Codeception\Lib\Actor\Shared\Friend` into `AcceptanceTester`.
-{% highlight php %}
-
-grabTextFrom('#name'));
-
-{% endhighlight %}
+```
On each failure, the snapshot of the last shown page will be stored in the `tests/_output` directory.
PhpBrowser will store the HTML code and WebDriver will save a screenshot of the page.
@@ -805,9 +684,7 @@ Let's see how common problems of acceptance testing can be solved with Codecepti
It is recommended to put widely used actions inside an Actor class. A good example is the `login` action
which would probably be actively involved in acceptance or functional testing:
-{% highlight php %}
-
-see($name, '.navbar');
}
}
-
-{% endhighlight %}
+```
Now you can use the `login` method inside your tests:
-{% highlight php %}
-
-login('miles', '123456');
-
-{% endhighlight %}
+```
However, implementing all actions for reuse in a single actor class may lead to
breaking the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle).
@@ -851,10 +724,8 @@ Codeception allows you to share cookies between tests, so a test user can stay l
Let's improve the code of our `login` method, executing the form submission only once
and restoring the session from cookies for each subsequent login function call:
-{% highlight php %}
-
-saveSessionSnapshot('login');
}
-
-{% endhighlight %}
+```
Note that session restoration only works for `WebDriver` modules
(modules implementing `Codeception\Lib\Interfaces\SessionSnapshot`).
@@ -899,13 +769,11 @@ By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error report
In acceptance tests you might want to change this level depending on your framework's error policy.
The error reporting level can be set in the suite configuration file:
-{% highlight yaml %}
-
+```yaml
actor: AcceptanceTester
-...
+# ...
error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
-
-{% endhighlight %}
+```
`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
@@ -916,10 +784,4 @@ You can easily test your Joomla, Drupal, WordPress sites, as well as those made
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](https://codeception.com/docs/modules/Db).
-
-
-
-* **Next Chapter: [FunctionalTests >](/docs/04-FunctionalTests)**
-* **Previous Chapter: [< GettingStarted](/docs/02-GettingStarted)**
-
-
+
diff --git a/docs/04-FunctionalTests.md b/docs/04-FunctionalTests.md
index d28e407cf..189c54dc8 100644
--- a/docs/04-FunctionalTests.md
+++ b/docs/04-FunctionalTests.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 04-FunctionalTests - Codeception - Documentation
+title: Functional Tests - Codeception Docs
---
+
# Functional Tests
Now that we've written some acceptance tests, functional tests are almost the same, with one major difference:
@@ -273,10 +274,4 @@ and manipulate their internal state. This makes your tests shorter and faster. I
if you don't use frameworks there is no practical reason to write functional tests.
If you are using a framework other than the ones listed here, create a module for it and share it with the community.
-
-
-
-* **Next Chapter: [UnitTests >](/docs/05-UnitTests)**
-* **Previous Chapter: [< AcceptanceTests](/docs/03-AcceptanceTests)**
-
-
+
diff --git a/docs/05-UnitTests.md b/docs/05-UnitTests.md
index 0981b361d..7cb34457a 100644
--- a/docs/05-UnitTests.md
+++ b/docs/05-UnitTests.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 05-UnitTests - Codeception - Documentation
+title: Unit Tests - Codeception Docs
---
+
# Unit & Integration Tests
Codeception uses PHPUnit as a backend for running its tests. Thus, any PHPUnit test can be added to a Codeception test suite
@@ -537,10 +538,4 @@ you don't need to install PHPUnit separately, but use Codeception directly to ex
Some nice features can be added to common unit tests by integrating Codeception modules.
For most unit and integration testing, PHPUnit tests are enough. They run fast, and are easy to maintain.
-
-
-
-* **Next Chapter: [ModulesAndHelpers >](/docs/06-ModulesAndHelpers)**
-* **Previous Chapter: [< FunctionalTests](/docs/04-FunctionalTests)**
-
-
+
diff --git a/docs/06-Debugging.md b/docs/06-Debugging.md
new file mode 100644
index 000000000..92ea54c56
--- /dev/null
+++ b/docs/06-Debugging.md
@@ -0,0 +1,73 @@
+---
+layout: doc
+title: Debugging - Codeception Docs
+---
+
+
+# Debugging
+
+Writing a test is always the process of learning the code and the application.
+It is ok, if a test can't be writtng from scratch or you don't understand the effects of the code.
+By looking into the following debugging practices you will learn how to get all required information inside a test to finish it.
+
+## Output
+
+Codeception provides `codecept_debug` function to print a debug output when running test.
+Think of it as `var_dump` but for testing:
+
+{% highlight php %}
+codecept_debug($user);
+{% endhighlight %}
+
+Unlinke var_dump, the output will be printed to screen only if tests are executed with `--debug` flag.
+
+```
+php vendor/bin/codecept run --debug
+```
+
+So it is safe to keep `codecept_debug` inside a test, it won't affect the code running on Continuous Integration server.
+
+`codecept_debug` can be used in any place of your tests, but it is prohibited to use it in application code.
+This function is loaded only by Codeception, so the application may be broken trying to call this line.
+
+Inside a [Helper](/docs/06-ModulesAndHelpers#Helpers) you can use analogs of this function to provide a debug output for a complex action.
+
+
+{% highlight php %}
+// print variable from helper
+$this->debug($response);
+
+// print variable with a short comment
+$this->debugSection('Response', $response);
+{% endhighlight %}
+
+Codeception Modules use debug output to give more information to user about the data used by a test. For instance, in debug mode you can see request and responses body when testing REST API.
+
+
+## Pause
+
+When running acceptance or functional test it might be needed to pause execution at one point to figure out what to do next. For instance, when interacting with a page in a web browser, you might need the execution to be paused to interact with elements on a page, discover proper locators, and next steps for the scenario. That's why Codeception has an interactive pause mode (powered by [PsySH](https://psysh.org)) which can be started by `codecept_pause` function or `$I->pause()`.
+
+Writing a new acceptance from scratch can be more convenient if you hold a browser window open. It is recommended to start writing a new acceptance test with these two commands:
+
+{% highlight php %}
+$I->amOnPage('/');
+$I->pause();
+{% endhighlight %}
+
+Interactive pause is launched only when `--debug ` option is enabled:
+
+```
+php vendor/bin/codecept run --debug
+```
+
+To launch interactive pause in a context when the `$I` object is not available, use `codecept_pause` function instead. To inspect local variables pass them into interactive shell using an array:
+
+{% highlight php %}
+$I->pause(['user' => $user])
+// or
+codecept_pause(['user' => $user]);
+{% endhighlight %}
+
+
+
diff --git a/docs/06-ModulesAndHelpers.md b/docs/06-ModulesAndHelpers.md
index 0a0e0cb25..147b2e4f6 100644
--- a/docs/06-ModulesAndHelpers.md
+++ b/docs/06-ModulesAndHelpers.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 06-ModulesAndHelpers - Codeception - Documentation
+title: Modules And Helpers - Codeception Docs
---
+
# Modules and Helpers
Codeception uses modularity to create a comfortable testing environment for every test suite you write.
@@ -612,10 +613,4 @@ you are free to write your own! Use Helpers (custom modules) for everything that
Helpers also can be used to extend the functionality of the original modules.
-
-
-* **Next Chapter: [ReusingTestCode >](/docs/06-ReusingTestCode)**
-* **Previous Chapter: [< UnitTests](/docs/05-UnitTests)**
-
-
-
+
diff --git a/docs/06-ReusingTestCode.md b/docs/06-ReusingTestCode.md
index 3c429e5fc..4d4ed1fc5 100644
--- a/docs/06-ReusingTestCode.md
+++ b/docs/06-ReusingTestCode.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 06-ReusingTestCode - Codeception - Documentation
+title: Reusing Test Code - Codeception Docs
---
+
# Reusing Test Code
Codeception uses modularity to create a comfortable testing environment for every test suite you write.
@@ -292,7 +293,4 @@ Scenario-driven tests should not contain anything more complex than `$I->doSomet
Following this approach will allow you to keep your tests clean, readable, stable and make them easy to maintain.
-
-
-* **Next Chapter: [AdvancedUsage >](/docs/07-AdvancedUsage)**
-* **Previous Chapter: [< ModulesAndHelpers](/docs/06-ModulesAndHelpers)**
+
diff --git a/docs/07-AdvancedUsage.md b/docs/07-AdvancedUsage.md
index 747627239..bfc6e3283 100644
--- a/docs/07-AdvancedUsage.md
+++ b/docs/07-AdvancedUsage.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 07-AdvancedUsage - Codeception - Documentation
+title: Advanced Usage - Codeception Docs
---
+
# Advanced Usage
In this chapter we will cover some techniques and options that you can use to improve your testing experience
@@ -106,25 +107,23 @@ passing all dependencies as arguments. This may be useful when working with Help
{% highlight php %}
signUp = $signUp;
$this->navBar = $navBar;
}
- public function signUp(\AcceptanceTester $I)
+ public function signUp(AcceptanceTester $I)
{
$this->navBar->click('Sign up');
$this->signUp->register([
@@ -144,17 +143,12 @@ And for Test classes:
{% highlight php %}
](/docs/07-BDD)**
-* **Previous Chapter: [< ReusingTestCode](/docs/06-ReusingTestCode)**
-
-
-
+
diff --git a/docs/07-BDD.md b/docs/07-BDD.md
index 893b1eef2..2db9cc76f 100644
--- a/docs/07-BDD.md
+++ b/docs/07-BDD.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 07-BDD - Codeception - Documentation
+title: BDD - Codeception Docs
---
+
# Behavior Driven Development
Behavior Driven Development (BDD) is a popular software development methodology. BDD is considered an extension of TDD, and is greatly inspired by [Agile](https://agilemanifesto.org/) practices. The primary reason to choose BDD as your development process is to break down communication barriers between business and technical teams. BDD encourages the use of automated testing to verify all documented features of a project from the very beginning. This is why it is common to talk about BDD in the context of test frameworks (like Codeception). The BDD approach, however, is about much more than testing - it is a common language for all team members to use during the development process.
@@ -639,7 +640,4 @@ Inside `@depends` block you should use test signature. Execute your feature with
If you like the concept of Behavior Driven Development or prefer to keep test scenarios in human readable format, Codeception allows you to write and execute scenarios in Gherkin. Feature files is just another test format inside Codeception, so it can be combined with Cept and Cest files inside the same suite. Steps definitions of your scenarios can use all the power of Codeception modules, PageObjects, and StepObjects.
-
-
-* **Next Chapter: [Customization >](/docs/08-Customization)**
-* **Previous Chapter: [< AdvancedUsage](/docs/07-AdvancedUsage)**
+
diff --git a/docs/08-Customization.md b/docs/08-Customization.md
index b8a48b5ce..e8bf5a4fa 100644
--- a/docs/08-Customization.md
+++ b/docs/08-Customization.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 08-Customization - Codeception - Documentation
+title: Customization - Codeception Docs
---
+
# Customization
In this chapter we will explain how you can extend and customize the file structure and test execution routines.
@@ -512,8 +513,4 @@ If you see you have a problem that can be solved using these extensions, then gi
-
-* **Next Chapter: [Data >](/docs/09-Data)**
-* **Previous Chapter: [< BDD](/docs/07-BDD)**
-
-
+
diff --git a/docs/09-Data.md b/docs/09-Data.md
index 2a593ff9b..3e2a0dedc 100644
--- a/docs/09-Data.md
+++ b/docs/09-Data.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 09-Data - Codeception - Documentation
+title: Data - Codeception Docs
---
+
# Working with Data
Tests should not affect each other. That's a rule of thumb. When tests interact with a database,
@@ -418,9 +419,4 @@ and cleaning up are bundled within the `Db` module. If you use ORM, you can use
to operate with database through a data abstraction layer, and use the DataFactory module to generate new records with ease.
-
-
-* **Next Chapter: [APITesting >](/docs/10-APITesting)**
-* **Previous Chapter: [< Customization](/docs/08-Customization)**
-
-
+
diff --git a/docs/10-APITesting.md b/docs/10-APITesting.md
index d9b1e5bca..82e94c16d 100644
--- a/docs/10-APITesting.md
+++ b/docs/10-APITesting.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 10-APITesting - Codeception - Documentation
+title: API Testing - Codeception Docs
---
+
# API Testing
The same way we tested a web site, Codeception allows you to test web services. They are very hard to test manually, so it's a really good idea to automate web service testing. We have SOAP and REST as standards, which are represented in corresponding modules, which we will cover in this chapter.
@@ -431,7 +432,5 @@ class Api extends \Codeception\Module {
Codeception has two modules that will help you to test various web services. They need a new `api` suite to be created. Remember, you are not limited to test only response body. By including `Db` module you may check if a user has been created after the `CreateUser` call. You can improve testing scenarios by using REST or SOAP responses in your helper methods.
-* **Next Chapter: [Codecoverage >](/docs/11-Codecoverage)**
-* **Previous Chapter: [< Data](/docs/09-Data)**
-
+
diff --git a/docs/11-Codecoverage.md b/docs/11-Codecoverage.md
index ab338278c..e2ea554b0 100644
--- a/docs/11-Codecoverage.md
+++ b/docs/11-Codecoverage.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 11-Codecoverage - Codeception - Documentation
+title: Codecoverage - Codeception Docs
---
+
# Code Coverage
At some point you want to review which parts of your application are tested well and which are not.
@@ -216,8 +217,4 @@ Context stream options are [well documented at php.net](https://php.net/manual/e
It's never been easier to setup local and remote code coverage. Just one config and one additional file to include!
**With Codeception you can easily generate CodeCoverage reports for your Selenium tests** (or other acceptance or api tests). Mixing reports for `acceptance`, `functional`, and `unit` suites provides you with the most complete information on which parts of your applications are tested and which are not.
-* **Next Chapter: [ContinuousIntegration >](/docs/12-ContinuousIntegration)**
-* **Previous Chapter: [< APITesting](/docs/10-APITesting)**
-
-
-
+
diff --git a/docs/11-Reporting.md b/docs/11-Reporting.md
new file mode 100644
index 000000000..0e8a8cdad
--- /dev/null
+++ b/docs/11-Reporting.md
@@ -0,0 +1,137 @@
+---
+layout: doc
+title: Reporting - Codeception Docs
+---
+
+
+## Reporting
+
+Clear reports gives a picture of the current state of the system. Which tests are passed, which tests are failed, and if failed what was the reason. Reports may vary on the level of detail and by the technical information collected. Codeception provides as built-in reporters and customizable API to create your own reporter.
+
+## CLI
+
+The standard reporter you already is CLI reporter. It is great for writing and debugging tests as well, as checking the results on CI. On failure, CLI reporter prints a list of all failed tests, if test includes some valuable data like last send requests for REST module, it will also be printed under 'artifacts' section of a test.
+
+
+
+To launch CLI reporter in minimal mode, simply execute tests:
+
+```
+php vendor/bin/codecept run
+```
+
+To see step-by-step execution in a runtime use `--steps` flag:
+
+```
+php vendor/bin/codecept run --steps
+```
+
+To get additional information which may be handful for debugging tests use `--debug` flag.
+This flag is your best friend for writing new tests.
+
+```
+php vendor/bin/codecept run --debug
+```
+
+More CLI options are available:
+
+* Artifacts report can be disabled with `--no-artifacts` option.
+* To explicitly enable ANSI colors use `--colors`, and `--no-colors` to disable them.
+* Use `--silent` to get the minimal possible output
+
+Codeception will exit with exit code 1 if tests are failed.
+This is how CI can mark the job as failed.
+
+## HTML
+
+More information can be presented via HTML report.
+
+
+
+Run tests with `--html` flag to create html report
+
+```
+php vendor/bin/codecept run --html
+```
+
+HTML report is valuable to present for non-tech colleagues. If you create HTML reports on CI you need to store a report as artifact to display it after. Codeception generates a static HTML file so no additional web server is needed to show it.
+
+## Testomat.io
+
+While HTML report can be pretty good for a single test run, more advanced reporting can be enabled by using Testomat.io. Testomat.io is a SaaS service which can store and present reports, and could be used by developers, QAs and managers. It is a complete test management system, which allows you track the history of tests, detect flaky tests, and work on planning new tests.
+
+Testomat.io reports are easy to set up and without storing artifacts on CI system.
+
+
+
+> 😻 Testomat.io is free for small teams, so you can use its reporting features with Codeception.
+
+Testomat.io imports all tests into UI, so your managers, business analysts, and manual QAs can see all your unit, funcitonal, and acceptance tests listed in one place:
+
+
+
+To start, create a new project at Testomat.io and import all your Codeception tests into it. Install testomatio packages for reporting and importing Codeception tests:
+
+```
+composer require testomatio/list-tests --dev
+composer require testomatio/reporter --dev
+```
+
+Obtain API key from a newly created Testomat.io project and import tests:
+
+```
+TESTOMATIO={apiKey} php vendor/bin/list-tests tests
+```
+
+After tests imported you can get a complete report while executing them:
+
+```
+TESTOMATIO={apiKey} php vendor/bin/codecept run --ext "Testomatio\Reporter\Codeception"
+```
+
+Data from test runs will be sent to Testomat.io server and you will see tests statuses are reported in realtime.
+
+Testomat.io not only provides reports for test executions, it also collects historical data for tests, allows attaching tests to Jira issues, and provides useful analytics, and allows planning new tests.
+
+Check an [Example Project](https://github.com/testomatio/examples/tree/master/codeception) to try it.
+
+## Recorder
+
+By default Codeception saves the screenshot for a failed test for acceptance tests and show it in HTML report. However, can't be possible to understand cause of failure just by one screenshot. This is where Recorder extension is handy, it saves a screenshot after each step and shows them in a slideshow.
+
+
+
+Selenium WebDriver doesn't have a simple way to record a video of a test execution, so slideshow is the simplest solution you can use to debug your tests.
+
+To use Recorder enable it as an extension inside config file:
+
+```yml
+extensions:
+ enabled:
+ - Codeception\Extension\Recorder
+```
+More config options are available on [Extension page](https://codeception.com/extensions#Recorder).
+
+## XML
+
+JUnit XML is a reporting standard for testing frameworks. CI platforms like Jenkins can visualize JUnit reports.
+
+```
+php vendor/bin/codecept run --xml
+```
+
+## Allure
+
+
+
+[Allure](https://docs.qameta.io/allure/) is a popular open-source reporting tool. It can be paired with Codeception to get a detailed run report. Use [Allure extension](https://github.com/allure-framework/allure-codeception) to generate report which can be passed to Allure to display it.
+
+## Custom Reporter
+
+Custom reporter can be built as an [Extension](https://codeception.com/docs/08-Customization#Extension). Extension can listen to all test events and log data from them.
+Look into the basic reporting extensions like [DotReporter](https://codeception.com/extensions#DotReporter) or [Logger](https://codeception.com/extensions#Logger) to learn how to build your own.
+
+
+
+
+
diff --git a/docs/12-ContinuousIntegration.md b/docs/12-ContinuousIntegration.md
index 750a9b1f1..51ce13804 100644
--- a/docs/12-ContinuousIntegration.md
+++ b/docs/12-ContinuousIntegration.md
@@ -1,8 +1,9 @@
---
layout: doc
-title: 12-ContinuousIntegration - Codeception - Documentation
+title: Continuous Integration - Codeception Docs
---
+
# Continuous Integration
Once you get testing suite up and running you are interested in running your tests regularly. If you ensure that tests are running on every code change or at least once a day you can be sure that no regression is introduced. This allows to keep you system stable. But developers are not so passionate about running all tests manually, they also can forget to execute tests before pushing code to production... The solution is simple, test execution should be automated. Instead of running them locally it is better to have dedicated server responsible for running tests for a team. This way we can ensure that everyone's tests executed, which commit made a regression in codebase, and that we can deploy only once tests pass.
@@ -207,7 +208,5 @@ test:
It is highly recommended to use Continuous Integration system in development. Codeception is easy to install and run in any CI systems. However, each of them has their differences you should take into account. You can use different reporters to provide output in format expected by CI system.
-* **Next Chapter: [ParallelExecution >](/docs/12-ParallelExecution)**
-* **Previous Chapter: [< Codecoverage](/docs/11-Codecoverage)**
-
+
diff --git a/docs/12-ParallelExecution.md b/docs/12-ParallelExecution.md
index c5b9b21ab..5f5ebb359 100644
--- a/docs/12-ParallelExecution.md
+++ b/docs/12-ParallelExecution.md
@@ -1,144 +1,75 @@
---
layout: doc
-title: 12-ParallelExecution - Codeception - Documentation
+title: Parallel Execution - Codeception Docs
---
-# Parallel Execution
-
-When execution time of your tests is longer than a coffee break, it is a good reason to think about making your tests faster. If you have already tried to run them on SSD drive, and the execution time still upsets you, it might be a good idea to run your tests in parallel.
-
-## Where to start
-
-Codeception does not provide a command like `run-parallel`. There is no common solution that can play well for everyone. Here are the questions you will need to answer:
-
-* How parallel processes will be executed?
-* How parallel processes won't affect each other?
-* Will they use different databases?
-* Will they use different hosts?
-* How should I split my tests across parallel processes?
-
-There are two approaches to achieve parallelization. We can use [Docker](https://docker.com) and run each process inside isolated containers, and have those containers executed simultaneously.
-
-Docker works really well for isolating testing environments.
-By the time of writing this chapter, we didn't have an awesome tool like it. This chapter demonstrates how to manage parallel execution manually. As you will see we spend too much effort trying to isolate tests which Docker does for free. Today we recommend using Docker for parallel testing.
-
-## Docker
-
-Please make sure you have `docker` installed. Docker experience is required as well.
-
-### Using Codeception Docker image
-
-Run official Codeception image from DockerHub:
-
- docker run codeception/codeception
-
-Running tests from a project, by mounting the current path as a host-volume into the container.
-The **default working directory in the container is `/project`**.
-
- docker run -v ${PWD}:/project codeception/codeception run
-
-To prepare application and tests to be executed inside containers you will need to use [Docker Compose](https://docs.docker.com/compose/) to run multiple containers and connect them together.
-
-Define all required services in `docker-compose.yml` file. Make sure to follow Docker philisophy: 1 service = 1 container. So each process should be defined as its own service. Those services can use official Docker images pulled from DockerHub. Directories with code and tests should be mounted using `volume` directive. And exposed ports should be explicitly set using `ports` directive.
-
-We prepared a sample config with codeception, web server, database, and selenium with Chrome to be executed together.
-
-{% highlight yaml %}
-
-version: '3'
-services:
- codecept:
- image: codeception/codeception
- depends_on:
- - chrome
- - web
- volumes:
- - .:/project
- web:
- image: php:7-apache
- depends_on:
- - db
- volumes:
- - .:/var/www/html
- db:
- image: percona:5.6
- chrome:
- image: selenium/standalone-chrome
-
-{% endhighlight %}
-Codeception service will execute command `codecept run` but only after all services are started. This is defined using `depends_on` parameter.
+# Parallel Execution
-It is easy to add more custom services. For instance to use Redis you just simple add this lines:
+When execution time of your tests is longer than a coffee break, it is a good reason to think about making your tests faster. If you have already tried to run them on SSD drive, and the execution time still upsets you, it might be a good idea to run your tests in parallel. However, PHP runs in a single-process and you can't parallelize tests natively similarly to how this works in Java or in NodeJS.
-{% highlight yaml %}
+Depending on the project size and requirements you can choose how the best to implement parallel testing for your case.
+In this guide we will overview possible options.
- redis:
- image: redis:3
+## Sharding
-{% endhighlight %}
+Minimal setup can be implemented by executing several independent CI jobs and running.
+Sharding in Codeception allows to combine stages 1 and 2 so tests could be split by groups on the fly.
+In this case a pipeline could be simplified to one stage with several jobs.
-By default the image has codecept as its entrypoint, to run the tests simply supply the run command
+
-{% highlight yaml %}
-docker-compose run --rm codecept help
+Each job should have Codeception running a subset of tests set by `--shard` option:
-{% endhighlight %}
+```
+# first job
+./venodor/bin/codecept run --shard 1/3
-Run suite
+# second job
+./venodor/bin/codecept run --shard 2/3
-{% highlight yaml %}
-docker-compose run --rm codecept run acceptance
+# third job
+./venodor/bin/codecept run --shard 3/3
+```
-{% endhighlight %}
+For each job you specify on how many groups tests should be split and the group that should be executed on this agent.
+I.e. `--shard` option takes 2 params: `--shard {currentGroup}/{numberOfGroups}`. So to split tests on 5 machines you need to create 5 jobs with Codeception running these shards: 1/5, 2/5, 3/5, 4/5, 5/5.
-{% highlight yaml %}
-docker-compose run --rm codecept run acceptance LoginCest
+Splitting test by shards is done automatically with zero-config. However, in this case you receive as many reports as jobs you have. To aggregate jobs store HTML, XML, and CodeCoverage results as artifacts and add an extra job in the end to merge them. Merging can be done with Robo-paracept toolset described below.
-{% endhighlight %}
-Development bash
+To get an aggregated report without an extra stage and without managing artifacts use [Testomat.io](https://testomat.io). This is a SaaS platform that can receive test results from different parallel run and show them in the one interface.
-{% highlight yaml %}
-docker-compose run --rm --entrypoint bash codecept
+
-{% endhighlight %}
+By running tests with Testomat.io reporter attached results will be sent to a centralized server. By default each execution will create its own report. To store results from different shards in one report set the Run title for them. You can use a common environment variable, like number of a build, to create the unique title which will be the same for all jobs. If build id is stored as $BUILDID variable, execution script for shard #3 can be following:
-And finally to execute testing in parallel you should define how you split your tests and run parallel processes for `docker-compose`. Here we split tests by suites, but you can use different groups to split your tests. In section below you will learn how to do that with Robo.
+```
+TESTOMATIO={apiKey} TESTOMATIO_TITLE="Build $BUILDID" ./vendor/bin/codecept run --shard 3/4
+```
-{% highlight yaml %}
-docker-compose --project-name test-web run -d --rm codecept run --html report-web.html web & \
-docker-compose --project-name test-unit run -d --rm codecept run --html report-unit.html unit & \
-docker-compose --project-name test-functional run -d --rm codecept run --html report-functional.html functional
-
-{% endhighlight %}
-At the end, it is worth specifying that Docker setup can be complicated and please make sure you understand Docker and Docker Compose before proceed. We prepared some links that might help you:
+## Building Pipeline
-* [Acceptance Tests Demo Repository](https://github.com/dmstr/docker-acception)
-* [Dockerized Codeception Internal Tests](https://github.com/Codeception/Codeception/blob/master/tests/README.md#dockerized-testing)
-* [Phundament App with Codeception](https://gist.github.com/schmunk42/d6893a64963509ff93daea80f722f694)
+While sharding provides a simplified setup for testing the complete pipeline schema may look like this.
-If you want to automate splitting tests by parallel processes, and executing them using PHP script you should use Robo task runner to do that.
+
-## Robo
+* On the first stage, tests should be split into groups. The group file should be committed into the repository or passed to next stage as an artifact.
+* On the second stage tests are executed. XML, HTML, and CodeCoverage reports must be stored as artifacts.
+* On the third stage the results from previous jobs must be collected or aggregated.
-### What to do
-Parallel Test Execution consists of 3 steps:
+To get more control on how the jobs are split excuted and results aggregated you can use a task runner.
-* splitting tests
-* running tests in parallel
-* merging results
+Codeception provides a toolset for [Robo task runner](https://robo.li) called [robo-paracept](https://github.com/Codeception/robo-paracept) for splitting tests into groups and merging resulting JUnit XML reports.
-We propose to perform those steps using a task runner. In this guide we will use [**Robo**](https://robo.li) task runner. It is a modern PHP task runner that is very easy to use. It uses [Symfony Process](https://symfony.com/doc/current/components/process.html) to spawn background and parallel processes. Just what we need for the step 2! What about steps 1 and 3? We have created robo [tasks](https://github.com/Codeception/robo-paracept) for splitting tests into groups and merging resulting JUnit XML reports.
-
-To conclude, we need:
+To sum up, we need to install:
* [Robo](https://robo.li), a task runner.
* [robo-paracept](https://github.com/Codeception/robo-paracept) - Codeception tasks for parallel execution.
-## Preparing Robo and Robo-paracept
+## Using Robo and Robo-paracept
Execute this command in an empty folder to install Robo and Robo-paracept :
{% highlight bash %}
@@ -147,21 +78,12 @@ $ composer require codeception/robo-paracept --dev
{% endhighlight %}
-You need to install Codeception after, if codeception is already installed it will not work.
-{% highlight bash %}
-
-$ composer require codeception/codeception
-
-{% endhighlight %}
-
-### Preparing Robo
+### Setting up Robo
Initializes basic RoboFile in the root of your project
{% highlight bash %}
-
-$ robo init
-
+robo init
{% endhighlight %}
Open `RoboFile.php` to edit it
@@ -177,7 +99,7 @@ class RoboFile extends \Robo\Tasks
{% endhighlight %}
-Each public method in robofile can be executed as a command from console. Let's define commands for 3 steps and include autoload.
+Each public method in robofile can be executed as a command from console. Let's define commands for 3 stages and include autoload.
{% highlight php %}
@@ -186,8 +108,8 @@ require_once 'vendor/autoload.php';
class Robofile extends \Robo\Tasks
{
- use \Codeception\Task\MergeReports;
- use \Codeception\Task\SplitTestsByGroups;
+ use Codeception\Task\Merger\ReportMerger;
+ use Codeception\Task\Splitter\TestsSplitterTrait;
public function parallelSplitTests()
{
@@ -207,34 +129,13 @@ class Robofile extends \Robo\Tasks
{% endhighlight %}
-If you run `robo`, you can see the respective commands:
-
-{% highlight bash %}
-
-$ robo
-Robo version 0.6.0
-
-Usage:
- command [options] [arguments]
-
-Options:
- -h, --help Display this help message
- -q, --quiet Do not output any message
- -V, --version Display this application version
- --ansi Force ANSI output
- --no-ansi Disable ANSI output
- -n, --no-interaction Do not ask any interactive question
- -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
-
-Available commands:
- help Displays help for a command
- list Lists commands
- parallel
- parallel:merge-results
- parallel:run
- parallel:split-tests
+When running `robo` you should see all 3 that these methods availble as CLI commands:
-{% endhighlight %}
+```
+parallel:split-tests
+parallel:run
+parallel:merge-results
+```
#### Step 1: Split Tests
@@ -275,10 +176,13 @@ Tasks from `\Codeception\Task\SplitTestsByGroups` will generate non-intersecting
{% endhighlight %}
+But what if one group of your tests runs for 5 mins and other for 20mins. In this case, you can balance execution time by using [SplitTestsByTime](https://github.com/Codeception/robo-paracept#splittestsbytime) task. It will generate balanced groups taking the execution speed into account.
+
+> More splitting strategies are implemented within [Robo-paracept](https://github.com/Codeception/robo-paracept#tasks) package.
+
Let's prepare group files:
{% highlight bash %}
-
$ robo parallel:split-tests
[Codeception\Task\SplitTestFilesByGroupsTask] Processing 33 files
@@ -303,38 +207,20 @@ Let's try to execute tests from the second group:
{% highlight bash %}
-$ codecept run acceptance -g paracept_2
+$ php vendor/bin/codecept run acceptance -g paracept_2
{% endhighlight %}
#### Step 2: Running Tests
-Robo has `ParallelExec` task to spawn background processes.
-
-##### Inside Container
+At this point you should decide if tests are executed on the same job or use multiple jobs for them. We recommend using multiple jobs, as in this case the burden of parallelization goes to CI server. This makes a lot of sense as a single machine has limited resources. If you split tests into CI jobs, you are limited only to the number of agents (build servers) that the CI can provide. For cloud-based services like GitHub Actions, GitLab CI, CircleCI, etc, this number is unlimited.
-If you are using [Docker](#docker) containers you can launch multiple Codeception containers for different groups:
+> Please refer to documentation of your CI platform to learn how to set up multiple jobs runnninng in parallel. Then proceed to merging of results.
-{% highlight php %}
-
-public function parallelRun()
-{
- $parallel = $this->taskParallelExec();
- for ($i = 1; $i <= 5; $i++) {
- $parallel->process(
- $this->taskExec('docker-compose run --rm codecept run')
- ->option('group', "paracept_$i") // run for groups paracept_*
- ->option('xml', "tests/_log/result_$i.xml") // provide xml report
- );
- }
- return $parallel->run();
-}
-
-{% endhighlight %}
+In some situations you may want to keep tests running on the same machine and scale it up with more resourses. This makes sense if you have heavy application setup for each test run and setting it up for each machine can waste a lot of resources.
-##### Locally
-If you want to run tests locally just use preinstalled `taskCodecept` task of Robo to define Codeception commands and put them inside `parallelExec`.
+To execute tests in multiple processes Robo has `ParallelExec` task to spawn background processes.
{% highlight php %}
@@ -355,64 +241,6 @@ public function parallelRun()
{% endhighlight %}
-In case you don't use containers you can isolate processes by starting different web servers and databases per each test process.
-
-We can define different databases for different processes. This can be done using [Environments](https://codeception.com/docs/07-AdvancedUsage#Environments). Let's define 5 new environments in `acceptance.suite.yml`:
-
-{% highlight yaml %}
-
-actor: AcceptanceTester
-modules:
- enabled:
- - Db:
- dsn: 'mysql:dbname=testdb;host=127.0.0.1'
- user: 'root'
- dump: 'tests/_data/dump.sql'
- populate: true
- cleanup: true
- - WebDriver:
- url: 'http://localhost/'
-env:
- env1:
- modules:
- config:
- Db:
- dsn: 'mysql:dbname=testdb_1;host=127.0.0.1'
- WebDriver:
- url: 'http://test1.localhost/'
- env2:
- modules:
- config:
- Db:
- dsn: 'mysql:dbname=testdb_2;host=127.0.0.1'
- WebDriver:
- url: 'http://test2.localhost/'
- env3:
- modules:
- config:
- Db:
- dsn: 'mysql:dbname=testdb_3;host=127.0.0.1'
- WebDriver:
- url: 'http://test3.localhost/'
- env4:
- modules:
- config:
- Db:
- dsn: 'mysql:dbname=testdb_4;host=127.0.0.1'
- WebDriver:
- url: 'http://test4.localhost/'
- env5:
- modules:
- config:
- Db:
- dsn: 'mysql:dbname=testdb_5;host=127.0.0.1'
- WebDriver:
- url: 'http://test5.localhost/'
-
-{% endhighlight %}
-
-----
-
After the `parallelRun` method is defined you can execute tests with
{% highlight bash %}
@@ -426,9 +254,8 @@ $ robo parallel:run
In case of `parallelExec` task we recommend to save results as JUnit XML, which can be merged and plugged into Continuous Integration server.
{% highlight php %}
-
taskMergeXmlReports();
for ($i=1; $i<=5; $i++) {
@@ -436,8 +263,6 @@ In case of `parallelExec` task we recommend to save results as JUnit XML, which
}
$merge->into("tests/_output/result_paracept.xml")->run();
}
-
-
{% endhighlight %}
Now, we can execute :
{% highlight bash %}
@@ -445,30 +270,23 @@ Now, we can execute :
$ robo parallel:merge-results
{% endhighlight %}
-`result_paracept.xml` file will be generated. It can be processed and analyzed.
-#### All Together
+`result_paracept.xml` file will be generated. It can be processed and analyzed.
-To create one command to rule them all we can define new public method `parallelAll` and execute all commands. We will save the result of `parallelRun` and use it for our final exit code:
+If you prefer HTML reports, they can be generated in the same way:
{% highlight php %}
-
-parallelSplitTests();
- $result = $this->parallelRun();
- $this->parallelMergeResults();
- return $result;
+ $merge = $this->taskMergeHtmlReports();
+ for ($i=1; $i<=5; $i++) {
+ $merge->from("tests/_output/result_$i.html");
+ }
+ $merge->into("tests/_output/result.html")->run();
}
-
{% endhighlight %}
-## Conclusion
-
-Codeception does not provide tools for parallel test execution. This is a complex task and solutions may vary depending on a project. We use [Robo](https://robo.li) task runner as an external tool to perform all required steps. To prepare our tests to be executed in parallel we use Codeception features of dynamic groups and environments. To do even more we can create Extensions and Group classes to perform dynamic configuration depending on a test process.
-* **Previous Chapter: [< ContinuousIntegration](/docs/12-ContinuousIntegration)**
-
+
diff --git a/docs/APITesting.md b/docs/APITesting.md
new file mode 100644
index 000000000..82e94c16d
--- /dev/null
+++ b/docs/APITesting.md
@@ -0,0 +1,436 @@
+---
+layout: doc
+title: API Testing - Codeception Docs
+---
+
+
+# API Testing
+
+The same way we tested a web site, Codeception allows you to test web services. They are very hard to test manually, so it's a really good idea to automate web service testing. We have SOAP and REST as standards, which are represented in corresponding modules, which we will cover in this chapter.
+
+You should start by creating a new test suite, (which was not provided by the `bootstrap` command). We recommend calling it **api** and using the `ApiTester` class for it.
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:suite api
+
+{% endhighlight %}
+
+We will put all the api tests there.
+
+## REST API
+
+> **NOTE:** REST API testing requires the `codeception/module-rest` package to be installed.
+
+The REST web service is accessed via HTTP with standard methods: `GET`, `POST`, `PUT`, `DELETE`. They allow users to receive and manipulate entities from the service. Accessing a WebService requires an HTTP client, so for using it you need the module `PhpBrowser` or one of framework modules set up. For example, we can use the `Symfony` module for Symfony2 applications in order to ignore web server and test web service internally.
+
+Configure modules in `api.suite.yml`:
+
+{% highlight yaml %}
+
+actor: ApiTester
+modules:
+ enabled:
+ - REST:
+ url: http://serviceapp/api/v1/
+ depends: PhpBrowser
+
+{% endhighlight %}
+
+The REST module will connect to `PhpBrowser` according to this configuration. Depending on the web service we may deal with XML or JSON responses. Codeception handles both data formats well, however If you don't need one of them, you can explicitly specify that the JSON or XML parts of the module will be used:
+
+{% highlight yaml %}
+
+actor: ApiTester
+modules:
+ enabled:
+ - REST:
+ url: http://serviceapp/api/v1/
+ depends: PhpBrowser
+ part: Json
+
+{% endhighlight %}
+
+API tests can be functional and be executed using Symfony, Laravel5, Zend, or any other framework module. You will need slightly update configuration for it:
+
+{% highlight yaml %}
+
+actor: ApiTester
+modules:
+ enabled:
+ - REST:
+ url: /api/v1/
+ depends: Laravel5
+
+{% endhighlight %}
+
+Once we have configured our new testing suite, we can create the first sample test:
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:cest api CreateUser
+
+{% endhighlight %}
+
+It will be called `CreateUserCest.php`.
+We need to implement a public method for each test. Let's make `createUserViaAPI` to test creation of a user via the REST API.
+
+{% highlight php %}
+
+amHttpAuthenticated('service_user', '123456');
+ $I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
+ $I->sendPost('/users', [
+ 'name' => 'davert',
+ 'email' => 'davert@codeception.com'
+ ]);
+ $I->seeResponseCodeIsSuccessful();
+ $I->seeResponseIsJson();
+ $I->seeResponseContains('{"result":"ok"}');
+
+ }
+}
+
+{% endhighlight %}
+
+### Authorization
+
+To authorize requests to external resources, usually provider requires you to authorize using headers. Additional headers can be set before request using `haveHttpHeader` command:
+
+
+{% highlight php %}
+
+haveHttpHeader('api_key', 'special-key');
+
+{% endhighlight %}
+
+For common authorization patterns use one of the following methods:
+
+* `amAWSAuthenticated`
+* `amBearerAuthenticated`
+* `amDigestAuthenticated`
+* `amHttpAuthenticated`
+* `amNTLMAuthenticated`
+
+### Sending Requests
+
+The real action in a test happens only when a request is sent. Before a request you may provide additional http headers which will be used in a next request to set authorization or expected content format.
+
+{% highlight php %}
+
+haveHttpHeader('accept', 'application/json');
+$I->haveHttpHeader('content-type', 'application/json');
+
+{% endhighlight %}
+
+When headers are set, you can send a request. To obtain data use `sendGet`:
+
+{% highlight php %}
+
+sendGet('/posts', [ 'status' => 'pending' ]);
+$I->seeResponseCodeIs(200);
+$I->seeResponseIsJson();
+
+{% endhighlight %}
+
+To create or update data you can use other common methods:
+
+* `sendPost`
+* `sendPut`
+* `sendPatch`
+* `sendDelete`
+* `sendPatch`
+
+To send a request with custom method use `send` action:
+
+{% highlight php %}
+
+send('TRACE', '/posts');
+{% endhighlight %}
+
+> sendAsJson methods were introduced in module-rest 1.4.1
+
+If API endpoint accepts JSON you can use `send` methods with `AsJson` suffix to convert data automatically.
+In this case `Content-Type` header is sent with `application/json` value and response if JSON is parsed:
+
+{% highlight php %}
+$I->sendPostAsJson('/users', ['name' => 'old name']);
+$users = $I->sendGetAsJson('/users');
+$I->sendPutAsJson('/users/' . $users[0]['id'], ['name' => 'new name']);
+$I->sendDeleteAsJson('/users/' . $users[1]['id']);
+{% endhighlight %}
+
+To enable steps with `AsJson` suffix enable `Codeception\Step\AsJson` step decorator in suite config:
+
+```yaml
+actor: ApiTester
+step_decorators:
+ - \Codeception\Step\AsJson
+```
+and rebuild actions:
+
+```
+php vendor/bin/codecept build
+```
+
+> `sendGetAsJson`, `sendPutAsJson`, and others, are implemented as a [Step Decorator](https://codeception.com/docs/08-Customization#Step-Decorators).
+
+
+### JSON Structure Validation
+
+If we expect a JSON response to be received we can check its structure with [JSONPath](https://goessner.net/articles/JsonPath/). It looks and sounds like XPath but is designed to work with JSON data, however we can convert JSON into XML and use XPath to validate the structure. Both approaches are valid and can be used in the REST module:
+
+{% highlight php %}
+
+sendGet('/users');
+$I->seeResponseCodeIs(HttpCode::OK); // 200
+$I->seeResponseIsJson();
+$I->seeResponseJsonMatchesJsonPath('$[0].user.login');
+$I->seeResponseJsonMatchesXpath('//user/login');
+
+{% endhighlight %}
+
+More detailed check can be applied if you need to validate the type of fields in a response.
+You can do that by using with a [seeResponseMatchesJsonType](https://codeception.com/docs/modules/REST#seeResponseMatchesJsonType) action in which you define the structure of JSON response.
+
+{% highlight php %}
+
+sendGet('/users/1');
+$I->seeResponseCodeIs(HttpCode::OK); // 200
+$I->seeResponseIsJson();
+$I->seeResponseMatchesJsonType([
+ 'id' => 'integer',
+ 'name' => 'string',
+ 'email' => 'string:email',
+ 'homepage' => 'string:url|null',
+ 'created_at' => 'string:date',
+ 'is_active' => 'boolean'
+]);
+
+
+{% endhighlight %}
+
+Codeception uses this simple and lightweight definitions format which can be [easily learned and extended](https://codeception.com/docs/modules/REST#seeResponseMatchesJsonType).
+
+### Working with Responses
+
+Responses are returned from `send*` methods:
+
+{% highlight php %}
+sendGet('/users');
+
+// alternatively
+
+$users = $I->grabResponse();
+
+{% endhighlight %}
+
+When you need to obtain a value from a response and use it in next requests you can use `grab*` methods. For instance, use `grabDataFromResponseByJsonPath` allows to query JSON for a value.
+
+{% highlight php %}
+grabDataFromResponseByJsonPath('$.id');
+$I->sendGet('/pet/' . $id);
+
+{% endhighlight %}
+
+### Validating Data JSON Responses
+
+The last line of the previous example verified that the response contained the provided string. However we shouldn't rely on it, as depending on content formatting we can receive different results with the same data. What we actually need is to check that the response can be parsed and it contains some of the values we expect. In the case of JSON we can use the `seeResponseContainsJson` method
+
+{% highlight php %}
+
+seeResponseContainsJson(['result' => 'ok']);
+// it can match tree-like structures as well
+$I->seeResponseContainsJson([
+ 'user' => [
+ 'name' => 'davert',
+ 'email' => 'davert@codeception.com',
+ 'status' => 'inactive'
+ ]
+]);
+
+
+{% endhighlight %}
+
+You may want to perform even more complex assertions on a response. This can be done by writing your own methods in the [Helper](https://codeception.com/docs/06-ReusingTestCode#Modules-and-Helpers) classes. To access the latest JSON response you will need to get the `response` property of the `REST` module. Let's demonstrate it with the `seeResponseIsHtml` method:
+
+{% highlight php %}
+
+getModule('REST')->response;
+ $this->assertRegExp('~^.*?<\/html>~m', $response);
+ }
+}
+
+
+{% endhighlight %}
+
+The same way you can receive request parameters and headers.
+
+### Testing XML Responses
+
+In case your REST API works with XML format you can use similar methods to test its data and structure.
+There is `seeXmlResponseIncludes` method to match inclusion of XML parts in response, and `seeXmlResponseMatchesXpath` to validate its structure.
+
+{% highlight php %}
+
+sendGet('/users.xml');
+$I->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
+$I->seeResponseIsXml();
+$I->seeXmlResponseMatchesXpath('//user/login');
+$I->seeXmlResponseIncludes(\Codeception\Util\Xml::toXml([
+ 'user' => [
+ 'name' => 'davert',
+ 'email' => 'davert@codeception.com',
+ 'status' => 'inactive'
+ ]
+]));
+
+
+{% endhighlight %}
+
+We are using `Codeception\Util\Xml` class which allows us to build XML structures in a clean manner. The `toXml` method may accept a string or array and returns \DOMDocument instance. If your XML contains attributes and so can't be represented as a PHP array you can create XML using the [XmlBuilder](https://codeception.com/docs/reference/XmlBuilder) class. We will take a look at it a bit more in next section.
+
+> Use `\Codeception\Util\Xml::build()` to create XmlBuilder instance.
+
+## SOAP API
+
+SOAP web services are usually more complex. You will need PHP [configured with SOAP support](https://php.net/manual/en/soap.installation.php). Good knowledge of XML is required too. `SOAP` module uses specially formatted POST request to connect to WSDL web services. Codeception uses `PhpBrowser` or one of framework modules to perform interactions. If you choose using a framework module, SOAP will automatically connect to the underlying framework. That may improve the speed of a test execution and will provide you with more detailed stack traces.
+
+Let's configure `SOAP` module to be used with `PhpBrowser`:
+
+{% highlight yaml %}
+
+actor: ApiTester
+modules:
+ enabled:
+ - SOAP:
+ depends: PhpBrowser
+ endpoint: http://serviceapp/api/v1/
+
+{% endhighlight %}
+
+SOAP request may contain application specific information, like authentication or payment. This information is provided with SOAP header inside the `` element of XML request. In case you need to submit such header, you can use `haveSoapHeader` action. For example, next line of code
+
+{% highlight php %}
+
+haveSoapHeader('Auth', ['username' => 'Miles', 'password' => '123456']);
+
+{% endhighlight %}
+will produce this XML header
+
+{% highlight xml %}
+
+
+
+ Miles
+ 123456
+
+
+
+{% endhighlight %}
+
+Use `sendSoapRequest` method to define the body of your request.
+
+{% highlight php %}
+
+sendSoapRequest('CreateUser', 'Miles Davismiles@davis.com');
+
+
+{% endhighlight %}
+
+This call will be translated to XML:
+
+{% highlight xml %}
+
+
+
+ Miles Davis
+ miles@davis.com
+
+
+
+{% endhighlight %}
+
+And here is the list of sample assertions that can be used with SOAP.
+
+{% highlight php %}
+
+seeSoapResponseEquals('500');
+$I->seeSoapResponseIncludes('1');
+$I->seeSoapResponseContainsStructure('');
+$I->seeSoapResponseContainsXPath('//result/user/name[@id=1]');
+
+
+{% endhighlight %}
+
+In case you don't want to write long XML strings, consider using [XmlBuilder](https://codeception.com/docs/reference/XmlBuilder) class. It will help you to build complex XMLs in jQuery-like style.
+In the next example we will use `XmlBuilder` instead of regular XML.
+
+{% highlight php %}
+
+haveSoapHeader('Session', array('token' => '123456'));
+$I->sendSoapRequest('CreateUser', Xml::build()
+ ->user->email->val('miles@davis.com'));
+$I->seeSoapResponseIncludes(\Codeception\Util\Xml::build()
+ ->result->val('Ok')
+ ->user->attr('id', 1)
+);
+
+
+{% endhighlight %}
+
+It's up to you to decide whether to use `XmlBuilder` or plain XML. `XmlBuilder` will return XML string as well.
+
+You may extend current functionality by using `SOAP` module in your helper class. To access the SOAP response as `\DOMDocument` you can use `response` property of `SOAP` module.
+
+{% highlight php %}
+
+getModule('SOAP')->response;
+ $this->assertTrue($response->schemaValidate($schema));
+ }
+}
+
+
+{% endhighlight %}
+
+## Conclusion
+
+Codeception has two modules that will help you to test various web services. They need a new `api` suite to be created. Remember, you are not limited to test only response body. By including `Db` module you may check if a user has been created after the `CreateUser` call. You can improve testing scenarios by using REST or SOAP responses in your helper methods.
+
+
+
diff --git a/docs/AcceptanceTests.md b/docs/AcceptanceTests.md
new file mode 100644
index 000000000..c4dc6b6e1
--- /dev/null
+++ b/docs/AcceptanceTests.md
@@ -0,0 +1,787 @@
+---
+layout: doc
+title: Acceptance Tests - Codeception Docs
+---
+
+
+# Acceptance Testing
+
+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.
+
+## Sample Scenario
+
+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:
+
+```php
+$I->amOnPage('/login');
+$I->fillField('username', 'davert');
+$I->fillField('password', 'qwerty');
+$I->click('LOGIN');
+$I->see('Welcome, Davert!');
+```
+
+**This scenario can be performed either by PhpBrowser or by a "real" browser through WebDriver**.
+
+| | PhpBrowser | WebDriver |
+| --- | --- | --- |
+| Browser Engine | Guzzle + Symfony BrowserKit | Chrome or Firefox |
+| JavaScript | No | Yes |
+| `see`/`seeElement` checks if… | …text is present in the HTML source | …text is actually visible to the user |
+| Access to HTTP response headers and status codes | Yes | No |
+| System requirements | PHP with [ext-curl](https://php.net/manual/book.curl.php) | Chrome or Firefox; optionally with Selenium Standalone Server |
+| Speed | Fast | Slow |
+
+We will start writing our first acceptance tests with PhpBrowser.
+
+## 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](https://guzzlephp.org) and [Symfony BrowserKit](https://symfony.com/doc/current/components/browser_kit.html) 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:
+
+```yaml
+# acceptance.suite.yml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://www.example.com/
+ - \Helper\Acceptance
+```
+
+We should start by creating a test with the next command:
+
+```
+php vendor/bin/codecept g:cest acceptance Signin
+```
+
+It will be placed into `tests/acceptance` directory.
+
+```php
+class SigninCest
+{
+ public function tryToTest(AcceptanceTester $I)
+ {
+ }
+}
+```
+
+The `$I` object is used to write all interactions.
+The methods of the `$I` object are taken from the [PhpBrowser Module](https://codeception.com/docs/modules/PhpBrowser). We will briefly describe them here:
+
+```php
+$I->amOnPage('/login');
+```
+
+We will assume that all actions starting with `am` and `have` describe the initial environment.
+The `amOnPage` action sets the starting point of a test to the `/login` page.
+
+With the `PhpBrowser` you can click the links and fill in the forms. That will probably be the majority of your actions.
+
+#### Click
+
+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.
+
+```php
+$I->click('Log in');
+// CSS selector applied
+$I->click('#login a');
+// XPath
+$I->click('//a[@id=login]');
+// Using context as second argument
+$I->click('Login', '.nav');
+```
+
+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:
+
+* id
+* name
+* css
+* xpath
+* link
+* class
+
+```php
+// By specifying locator type
+$I->click(['link' => 'Login']);
+$I->click(['class' => 'btn']);
+```
+
+There is a special class [`Codeception\Util\Locator`](https://codeception.com/docs/reference/Locator)
+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:
+
+```php
+$I->click('Edit' , \Codeception\Util\Locator::elementAt('//table/tr', -1));
+```
+
+#### Forms
+
+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:
+
+```html
+
+```
+
+From a user's perspective, a form consists of fields which should be filled in, and then a submit button clicked:
+
+```php
+// we are using label to match user_name field
+$I->fillField('Name', 'Miles');
+// we can use input name or id
+$I->fillField('user[email]','miles@davis.com');
+$I->selectOption('Gender','Male');
+$I->click('Update');
+```
+
+To match fields by their labels, you should write a `for` attribute in the `label` tag.
+
+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:
+
+```php
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm'
+)));
+```
+
+The `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
+or that fields have unclean names or badly written IDs, or the form is sent by a JavaScript call.
+
+By default, `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:
+
+```php
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm'
+)), 'submitButton');
+// this would have the same effect, but the value has to be explicitly specified
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm',
+ 'submitButton' => 'Update'
+)));
+```
+
+##### 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.
+
+```php
+use \Codeception\Step\Argument\PasswordArgument;
+
+$I->amOnPage('/form/password_argument');
+$I->fillField('password', new PasswordArgument('thisissecret'));
+```
+
+`thisissecret` will be filled into a form but it won't be shown in output and logs.
+
+#### Assertions
+
+In the `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 `see()`:
+
+```php
+// We check that 'Thank you, Miles' is on the page.
+$I->see('Thank you, Miles');
+// We check that 'Thank you, Miles' is inside an element with 'notice' class.
+$I->see('Thank you, Miles', '.notice');
+// Or using XPath locators
+$I->see('Thank you, Miles', "//table/tr[2]");
+// We check this message is *not* on the page.
+$I->dontSee('Form is filled incorrectly');
+```
+
+You can check that a specific HTML element exists (or doesn't) on a page:
+
+```php
+$I->seeElement('.notice');
+$I->dontSeeElement('.error');
+```
+
+We also have other useful commands to perform checks. Please note that they all start with the `see` prefix:
+
+```php
+$I->seeInCurrentUrl('/user/miles');
+$I->seeCheckboxIsChecked('#agree');
+$I->seeInField('user[name]', 'Miles');
+$I->seeLink('Login');
+```
+
+#### Conditional Assertions
+
+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.
+Each `see` method has a corresponding `canSee` method, and `dontSee` has a `cantSee` method:
+
+```php
+$I->canSeeInCurrentUrl('/user/miles');
+$I->canSeeCheckboxIsChecked('#agree');
+$I->cantSeeInField('user[name]', 'Miles');
+```
+
+Each failed assertion will be shown in the test results, but it won't stop the test.
+
+Conditional assertions are disabled in bootstrap setup. To enable them you should add corresponding step decorators to suite config:
+
+> If you started project as `codecept init acceptance` they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\ConditionalAssertion
+```
+
+Then rebuild actors with `codecept build` command.
+
+#### Comments
+
+Within a long scenario, you should describe what actions you are going to perform and what results should be achieved.
+Comment methods like `amGoingTo`, `expect`, `expectTo` help you in making tests more descriptive:
+
+```php
+$I->amGoingTo('submit user form with invalid values');
+$I->fillField('user[email]', 'miles');
+$I->click('Update');
+$I->expect('the form is not submitted');
+$I->see('Form is filled incorrectly');
+```
+
+#### Grabbers
+
+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:
+
+```php
+$I->fillField('email', 'miles@davis.com');
+$I->click('Generate Password');
+$password = $I->grabTextFrom('#password');
+$I->click('Login');
+$I->fillField('email', 'miles@davis.com');
+$I->fillField('password', $password);
+$I->click('Log in!');
+```
+
+Grabbers allow you to get a single value from the current page with commands:
+
+```php
+$token = $I->grabTextFrom('.token');
+$password = $I->grabTextFrom("descendant::input/descendant::*[@id = 'password']");
+$api_key = $I->grabValueFrom('input[name=api]');
+```
+
+#### Cookies, URLs, Title, etc
+
+Actions for cookies:
+
+```php
+$I->setCookie('auth', '123345');
+$I->grabCookie('auth');
+$I->seeCookie('auth');
+```
+
+Actions for checking the page title:
+
+```php
+$I->seeInTitle('Login');
+$I->dontSeeInTitle('Register');
+```
+
+Actions for URLs:
+
+```php
+$I->seeCurrentUrlEquals('/login');
+$I->seeCurrentUrlMatches('~^/users/(\d+)~');
+$I->seeInCurrentUrl('user/1');
+$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~');
+```
+
+## WebDriver
+
+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](https://www.w3.org/TR/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 [php-webdriver/php-webdriver](https://github.com/php-webdriver/php-webdriver) as a PHP implementation of the 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.
+
+### Local Setup
+
+### Selenium Server
+
+[Selenium](https://www.selenium.dev) is required to launch and control browsers from Codeception.
+Selenium Server is required to be installed and started before running tests.
+
+The fastest way of getting Selenium is using [selenium-standalone](https://www.npmjs.com/package/selenium-standalone) NodeJS Package.
+It automatically installs Selenium and all required dependencies and starts server. It requires **NodeJS and Java** to be installed.
+
+```
+npm install selenium-standalone -g
+selenium-standalone install
+```
+
+Launch this command in a separate terminal:
+
+```
+selenium-standalone start
+```
+
+
+
+Now, you are ready to run WebDriver tests using Codeception.
+
+> Alternatively, Selenium Server can be installed manually. [Download it](https://www.selenium.dev/downloads/) from the official site and launch a server with Java: `java -jar selenium-server-....jar`. In this case ChromeDriver and GeckoDriver must be installed separately.
+
+* For more information refer to [Installation Instructions](https://codeception.com/docs/modules/WebDriver#Selenium)
+* Enable [RunProcess](https://codeception.com/extensions#RunProcess) extension to start/stop Selenium automatically *(optional)*.
+
+
+### Configuration
+
+To execute a test in a browser you need to change the suite configuration to use **WebDriver** module.
+
+Modify your `acceptance.suite.yml` file:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - WebDriver:
+ url: {{your site URL}}
+ browser: chrome
+ - \Helper\Acceptance
+```
+
+See [WebDriver Module](https://codeception.com/docs/modules/WebDriver) 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:
+
+```php
+$I->seeElement('#modal');
+```
+
+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:
+
+#### Wait
+
+While testing web application, you may need to wait for JavaScript events to occur. Due to its asynchronous nature,
+complex JavaScript interactions are hard to test. That's why you may need to use waiters, actions with `wait` prefix.
+They can be used to specify what event you expect to occur on a page, before continuing the test.
+
+For example:
+
+```php
+$I->waitForElement('#agree_button', 30); // secs
+$I->click('#agree_button');
+```
+
+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](https://codeception.com/docs/modules/WebDriver#waitForText),
+[waitForElementVisible](https://codeception.com/docs/modules/WebDriver#waitForElementVisible) and others.
+
+If you don't know what exact element you need to wait for, you can simply pause execution with using `$I->wait()`
+
+```php
+$I->wait(3); // wait for 3 secs
+```
+
+#### SmartWait
+
+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](https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits) 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:
+
+```yaml
+wait: 5
+```
+
+With this config we have the following test:
+
+```php
+// we use wait: 5 instead of
+// $I->waitForElement(['css' => '#click-me'], 5);
+// to wait for element on page
+$I->click(['css' => '#click-me']);
+```
+
+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:
+
+```php
+$I->click('Login'); // DISABLED, not a specific locator
+$I->fillField('user', 'davert'); // DISABLED, not a specific locator
+$I->fillField(['name' => 'password'], '123456'); // ENABLED, strict locator
+$I->click('#login'); // ENABLED, locator is CSS ID
+$I->see('Hello, Davert'); // DISABLED, Not a locator
+$I->seeElement('#userbar'); // ENABLED
+$I->dontSeeElement('#login'); // DISABLED, can't wait for element to hide
+$I->seeNumberOfElements(['css' => 'button.link'], 5); // DISABLED, can wait only for one element
+```
+
+#### Retry
+
+When it's hard to define condition to wait for, we can retry a command few times until it succeeds.
+For instance, if you try to click while it's animating you can try to do it few times until it freezes.
+Each action and assertion have an alias prefixed with `retry` which allows to retry a flaky command.
+
+```php
+$I->retryClick('flaky element');
+$I->retrySee('Something changed');
+```
+
+Retry can be configured via `$I->retry()` command, where you can set number of retries and initial interval:
+interval will be doubled on each unsuccessful execution.
+
+```php
+// Retry up to 6 sec: 4 times, for 400ms initial interval => 400ms + 800ms + 1600ms + 3200ms = 6000ms
+$I->retry(4, 400);
+```
+
+`$I->retry` takes 2 parameters:
+* number of retries (1 by default)
+* initial interval (200ms by default)
+
+Retries are disabled by default. To enable them you should add retry step decorators to suite config:
+
+> If you started project as `codecept init acceptance` they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\Retry
+```
+
+Then add `\Codeception\Lib\Actor\Shared\Retry` trait into `AcceptanceTester` class:
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ use _generated\AcceptanceTesterActions;
+
+ use \Codeception\Lib\Actor\Shared\Retry;
+}
+```
+
+Run `codecept build` to recreate actions. New `retry*` actions are available for tests.
+Keep in mind, that you can change retry policy dynamically for each test.
+
+#### Wait and Act
+
+To combine `waitForElement` with actions inside that element you can use the [performOn](https://codeception.com/docs/modules/WebDriver#performOn) method.
+Let's see how you can perform some actions inside an HTML popup:
+
+```php
+$I->performOn('.confirm', \Codeception\Util\ActionSequence::build()
+ ->see('Warning')
+ ->see('Are you sure you want to delete this?')
+ ->click('Yes')
+);
+```
+Alternatively, this can be executed using a callback, in this case the `WebDriver` instance is passed as argument
+
+```php
+$I->performOn('.confirm', function(\Codeception\Module\WebDriver $I) {
+ $I->see('Warning');
+ $I->see('Are you sure you want to delete this?');
+ $I->click('Yes');
+});
+```
+
+For more options see [`performOn()` reference](https://codeception.com/docs/modules/WebDriver#performOn).
+
+#### A/B Testing
+
+When a web site acts unpredictably you may need to react on that change.
+This happens if site configured for A/B testing, or shows different popups, based on environment.
+
+Since Codeception 3.0 you can have some actions to fail silently, if they are errored.
+Let's say, you open a page and some times there is a popup which should be closed.
+We may try to hit the "close" button but if this action fails (no popup on page) we just continue the test.
+
+This is how it can be implemented:
+
+```php
+$I->amOnPage('/');
+$I->tryToClick('x', '.alert');
+// continue execution
+```
+
+You can also use `tryTo` as condition for your tests:
+
+```php
+if ($I->tryToSeeElement('.alert')) {
+ $I->waitForText('Do you accept cookies?');
+ $I->click('Yes');
+}
+```
+
+A/B testing is disabled by default. To enable it you should add corresponding step decorators to suite config:
+
+> If you started project as `codecept init acceptance` in Codeception >= 3.0 they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\TryTo
+```
+
+Then rebuild actors with `codecept build` command.
+
+### 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**:
+
+```php
+$I->amOnPage('/messages');
+$nick = $I->haveFriend('nick');
+$nick->does(function(AcceptanceTester $I) {
+ $I->amOnPage('/messages/new');
+ $I->fillField('body', 'Hello all!');
+ $I->click('Send');
+ $I->see('Hello all!', '.message');
+});
+$I->wait(3);
+$I->see('Hello all!', '.message');
+```
+
+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 `leave()`.
+You can also specify roles for a friend:
+
+```php
+$nickAdmin = $I->haveFriend('nickAdmin', adminStep::class);
+$nickAdmin->does(function(adminStep $I) {
+ // Admin does ...
+});
+$nickAdmin->leave();
+```
+
+Multi session testing is disabled by default. To enable it, add `\Codeception\Lib\Actor\Shared\Friend` into `AcceptanceTester`.
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ use _generated\AcceptanceTesterActions;
+
+ use \Codeception\Lib\Actor\Shared\Friend;
+}
+```
+
+### Cloud Testing
+
+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](https://saucelabs.com), [BrowserStack](https://www.browserstack.com/)
+and [others](https://codeception.com/docs/modules/WebDriver#Cloud-Testing) 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](https://codeception.com/docs/modules/WebDriver#Cloud-Testing) to:
+
+* specify the host to connect to (depends on the cloud provider)
+* authentication details (to use your account)
+* browser
+* OS
+
+We recommend using [params](https://codeception.com/docs/06-ModulesAndHelpers#Dynamic-Configuration-With-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.
+
+### Debugging
+
+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 `codecept_debug` function:
+
+```php
+codecept_debug($I->grabTextFrom('#name'));
+```
+
+On each failure, the snapshot of the last shown page will be stored in the `tests/_output` directory.
+PhpBrowser will store the HTML code and WebDriver will save a screenshot of the page.
+
+Additional debugging features by Codeception:
+
+* [Interactive Pause](https://codeception.com/docs/02-GettingStarted#Interactive-Pause) is a REPL that allows to type and check commands for instant feedback.
+* [Recorder Extension](https://codeception.com/addons#CodeceptionExtensionRecorder) allows to record tests step-by-steps and show them in slideshow
+
+### Common Cases
+
+Let's see how common problems of acceptance testing can be solved with Codeception.
+
+#### Login
+
+It is recommended to put widely used actions inside an Actor class. A good example is the `login` action
+which would probably be actively involved in acceptance or functional testing:
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ // do not ever remove this line!
+ use _generated\AcceptanceTesterActions;
+
+ public function login($name, $password)
+ {
+ $I = $this;
+ $I->amOnPage('/login');
+ $I->submitForm('#loginForm', [
+ 'login' => $name,
+ 'password' => $password
+ ]);
+ $I->see($name, '.navbar');
+ }
+}
+```
+
+Now you can use the `login` method inside your tests:
+
+```php
+// $I is AcceptanceTester
+$I->login('miles', '123456');
+```
+
+However, implementing all actions for reuse in a single actor class may lead to
+breaking the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle).
+
+#### Single Login
+
+If you need to authorize a user for each test, you can do so by submitting the login form at the beginning of every test.
+Running those steps takes time, and in the case of Selenium tests (which are slow by themselves)
+that time loss can become significant.
+
+Codeception allows you to share cookies between tests, so a test user can stay logged in for other tests.
+
+Let's improve the code of our `login` method, executing the form submission only once
+and restoring the session from cookies for each subsequent login function call:
+
+```php
+public function login($name, $password)
+ {
+ $I = $this;
+ // if snapshot exists - skipping login
+ if ($I->loadSessionSnapshot('login')) {
+ return;
+ }
+ // logging in
+ $I->amOnPage('/login');
+ $I->submitForm('#loginForm', [
+ 'login' => $name,
+ 'password' => $password
+ ]);
+ $I->see($name, '.navbar');
+ // saving snapshot
+ $I->saveSessionSnapshot('login');
+ }
+```
+
+Note that session restoration only works for `WebDriver` modules
+(modules implementing `Codeception\Lib\Interfaces\SessionSnapshot`).
+
+
+### 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](https://codeception.com/docs/06-ModulesAndHelpers#Helpers).
+
+WebDriver module provides advanced methods for the browser session, however, they can only be used from Helpers.
+
+* [_initializeSession](https://codeception.com/docs/modules/WebDriver#_initializeSession) - starts a new browser session
+* [_closeSession](https://codeception.com/docs/modules/WebDriver#_closeSession) - stops the browser session
+* [_restart](https://codeception.com/docs/modules/WebDriver#_restart) - updates configuration and restarts browser
+* [_capabilities](https://codeception.com/docs/modules/WebDriver#_capabilities) - set [desired capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities) programmatically.
+
+Those methods can be used to create custom commands like `$I->startBrowser()` or used in [before/after](https://codeception.com/docs/06-ModulesAndHelpers#Hooks) hooks.
+
+## Error Reporting
+
+By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
+In acceptance tests you might want to change this level depending on your framework's error policy.
+The error reporting level can be set in the suite configuration file:
+
+```yaml
+actor: AcceptanceTester
+# ...
+error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
+```
+
+`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
+
+## Conclusion
+
+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](https://codeception.com/docs/modules/Db).
+
+
diff --git a/docs/AdvancedUsage.md b/docs/AdvancedUsage.md
new file mode 100644
index 000000000..a0437e5dc
--- /dev/null
+++ b/docs/AdvancedUsage.md
@@ -0,0 +1,801 @@
+---
+layout: doc
+title: Advanced Usage - Codeception Docs
+---
+
+
+# Advanced Usage
+
+In this chapter we will cover some techniques and options that you can use to improve your testing experience
+and keep your project better organized.
+
+## Cest Classes
+
+If you want to get a class-like structure for your Cepts, you can use the Cest format instead of plain PHP.
+It is very simple and is fully compatible with Cept scenarios. It means that if you feel that your test is long enough
+and you want to split it, you can easily move it into classes.
+
+You can create a Cest file by running the command:
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:cest suitename CestName
+
+{% endhighlight %}
+
+The generated file will look like this:
+
+{% highlight php %}
+
+amOnPage('/');
+ $I->click('Login');
+ $I->fillField('username', 'john');
+ $I->fillField('password', 'coltrane');
+ $I->click('Enter');
+ $I->see('Hello, John');
+ $I->seeInCurrentUrl('/account');
+ }
+}
+
+{% endhighlight %}
+
+As you see, Cest classes have no parents.
+This is done intentionally. It allows you to extend your classes with common behaviors and workarounds
+that may be used in child classes. But don't forget to make these methods `protected` so they won't be executed as tests.
+
+Cest format also can contain hooks based on test results:
+
+* `_failed` will be executed on failed test
+* `_passed` will be executed on passed test
+
+{% highlight php %}
+
+signUp = $signUp;
+ $this->navBar = $navBar;
+ }
+
+ public function signUp(AcceptanceTester $I)
+ {
+ $this->navBar->click('Sign up');
+ $this->signUp->register([
+ 'first_name' => 'Joe',
+ 'last_name' => 'Jones',
+ 'email' => 'joe@jones.com',
+ 'password' => '1234',
+ 'password_confirmation' => '1234'
+ ]);
+ }
+}
+
+{% endhighlight %}
+
+And for Test classes:
+
+{% highlight php %}
+
+math = $math;
+ }
+
+ public function testAll()
+ {
+ $this->assertEquals(3, $this->math->add(1, 2));
+ $this->assertEquals(1, $this->math->subtract(3, 2));
+ }
+}
+
+{% endhighlight %}
+
+However, Dependency Injection is not limited to this. It allows you to **inject any class**,
+which can be constructed with arguments known to Codeception.
+
+In order to make auto-wiring work, you will need to implement the `_inject()` method with the list of desired arguments.
+It is important to specify the type of arguments, so Codeception can guess which objects are expected to be received.
+The `_inject()` will only be invoked once, just after creation of the TestCase object (either Cest or Test).
+Dependency Injection will also work in a similar manner for Helper and Actor classes.
+
+Each test of a Cest class can declare its own dependencies and receive them from method arguments:
+
+{% highlight php %}
+
+createDummyUser();
+ $userPage->login($user->getName(), $user->getPassword());
+ $userPage->updateProfile(['name' => 'Bill']);
+ $I->see('Profile was saved');
+ $I->see('Profile of Bill','h1');
+ }
+}
+
+{% endhighlight %}
+
+Moreover, Codeception can resolve dependencies recursively (when `A` depends on `B`, and `B` depends on `C` etc.)
+and handle parameters of primitive types with default values (like `$param = 'default'`).
+Of course, you are not allowed to have *cyclic dependencies*.
+
+## Example Annotation
+
+What if you want to execute the same test scenario with different data? In this case you can inject examples
+as `\Codeception\Example` instances.
+Data is defined via the `@example` annotation, using JSON or Doctrine-style notation (limited to a single line). Doctrine-style:
+
+{% highlight php %}
+
+sendGet($example[0]);
+ $I->seeResponseCodeIs($example[1]);
+ }
+}
+
+{% endhighlight %}
+
+JSON:
+
+{% highlight php %}
+
+amOnPage($example['url']);
+ $I->see($example['title'], 'h1');
+ $I->seeInTitle($example['title']);
+ }
+}
+
+{% endhighlight %}
+
+
+If you use JSON notation please keep in mind that all string keys
+and values should be enclosed in double quotes (`"`) according to JSON standard.
+
+
+Key-value data in Doctrine-style annotation syntax:
+
+{% highlight php %}
+
+amOnPage($example['url']);
+ $I->see($example['title'], 'h1');
+ $I->seeInTitle($example['title']);
+ }
+}
+
+{% endhighlight %}
+
+## DataProvider Annotations
+
+You can also use the `@dataProvider` annotation for creating dynamic examples for [Cest classes](#Cest-Classes), using a **protected method** for providing example data:
+
+{% highlight php %}
+
+amOnPage($example['url']);
+ $I->see($example['title'], 'h1');
+ $I->seeInTitle($example['title']);
+ }
+
+ /**
+ * @return array
+ */
+ protected function pageProvider() // alternatively, if you want the function to be public, be sure to prefix it with `_`
+ {
+ return [
+ ['url'=>"/", 'title'=>"Welcome"],
+ ['url'=>"/info", 'title'=>"Info"],
+ ['url'=>"/about", 'title'=>"About Us"],
+ ['url'=>"/contact", 'title'=>"Contact Us"]
+ ];
+ }
+}
+
+{% endhighlight %}
+
+`@dataprovider` annotation is also available for [unit tests](https://codeception.com/docs/05-UnitTests), in this case the data provider **method must be public**.
+For more details about how to use data provider for unit tests, please refer to [PHPUnit documentation](https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers).
+
+## Before/After Annotations
+
+You can control execution flow with `@before` and `@after` annotations. You may move common actions
+into protected (non-test) methods and invoke them before or after the test method by putting them into annotations.
+It is possible to invoke several methods by using more than one `@before` or `@after` annotation.
+Methods are invoked in order from top to bottom.
+
+{% highlight php %}
+
+amOnPage('/login');
+ $I->fillField('Username', 'miles');
+ $I->fillField('Password', 'davis');
+ $I->click('Login');
+ }
+
+ /**
+ * @before login
+ */
+ public function banUser(AcceptanceTester $I)
+ {
+ $I->amOnPage('/users/charlie-parker');
+ $I->see('Ban', '.button');
+ $I->click('Ban');
+ }
+
+ /**
+ * @before login
+ * @before cleanup
+ * @after logout
+ * @after close
+ */
+ public function addUser(AcceptanceTester $I)
+ {
+ $I->amOnPage('/users/charlie-parker');
+ $I->see('Ban', '.button');
+ $I->click('Ban');
+ }
+}
+
+{% endhighlight %}
+
+## Environments
+
+For cases where you need to run tests with different configurations you can define different config environments.
+The most typical use cases are running acceptance tests in different browsers,
+or running database tests using different database engines.
+
+Let's demonstrate the usage of environments for the browsers case.
+
+We need to add some new lines to `acceptance.suite.yml`:
+
+{% highlight yaml %}
+
+actor: AcceptanceTester
+modules:
+ enabled:
+ - WebDriver
+ - \Helper\Acceptance
+ config:
+ WebDriver:
+ url: 'http://127.0.0.1:8000/'
+ browser: 'firefox'
+env:
+ chrome:
+ modules:
+ config:
+ WebDriver:
+ browser: 'chrome'
+
+ firefox:
+ # nothing changed
+
+{% endhighlight %}
+
+Basically you can define different environments inside the `env` root, name them (`chrome`, `firefox` etc.),
+and then redefine any configuration parameters that were set before.
+
+You can also define environments in separate configuration files placed in the directory specified by the `envs` option in
+the `paths` configuration:
+
+{% highlight yaml %}
+
+paths:
+ envs: tests/_envs
+
+{% endhighlight %}
+
+The names of these files are used as environments names
+(e.g. `chrome.yml` or `chrome.dist.yml` for an environment named `chrome`).
+You can generate a new file with this environment configuration by using the `generate:environment` command:
+
+{% highlight bash %}
+
+$ php vendor/bin/codecept g:env chrome
+
+{% endhighlight %}
+
+In that file you can specify just the options you wish to override:
+
+{% highlight yaml %}
+
+modules:
+ config:
+ WebDriver:
+ browser: 'chrome'
+
+{% endhighlight %}
+
+The environment configuration files are merged into the main configuration before the suite configuration is merged.
+
+You can easily switch between those configs by running tests with `--env` option.
+To run the tests only for Firefox you just need to pass `--env firefox` as an option:
+
+{% highlight bash %}
+
+$ php vendor/bin/codecept run acceptance --env firefox
+
+{% endhighlight %}
+
+To run the tests in all browsers, list all the environments:
+
+{% highlight bash %}
+
+$ php vendor/bin/codecept run acceptance --env chrome --env firefox
+
+{% endhighlight %}
+
+The tests will be executed 3 times, each time in a different browser.
+
+It's also possible to merge multiple environments into a single configuration by separating them with a comma:
+
+{% highlight bash %}
+
+$ php vendor/bin/codecept run acceptance --env dev,firefox --env dev,chrome --env dev,firefox
+
+{% endhighlight %}
+
+The configuration is merged in the order given.
+This way you can easily create multiple combinations of your environment configurations.
+
+Depending on the environment, you may choose which tests are to be executed.
+For example, you might need some tests to be executed in Firefox only, and some tests in Chrome only.
+
+The desired environments can be specified with the `@env` annotation for tests in Test and Cest formats:
+
+{% highlight php %}
+current()` method.
+
+{% highlight php %}
+
+current('env');
+
+// list of all enabled modules
+$scenario->current('modules');
+
+// test name
+$scenario->current('name');
+
+// browser name (if WebDriver module enabled)
+$scenario->current('browser');
+
+// capabilities (if WebDriver module enabled)
+$scenario->current('capabilities');
+
+{% endhighlight %}
+
+You can inject `\Codeception\Scenario` like this:
+
+{% highlight php %}
+current('browser') == 'chrome') {
+ // ...
+ }
+}
+{% endhighlight %}
+
+`Codeception\Scenario` is also available in Actor classes and StepObjects. You can access it with `$this->getScenario()`.
+
+## Shuffle
+
+By default Codeception runs tests in alphabetic order.
+To ensure that tests are not depending on each other (unless explicitly declared via `@depends`) you can enable `shuffle` option.
+
+{% highlight yaml %}
+
+# inside codeception.yml
+settings:
+ shuffle: true
+
+{% endhighlight %}
+
+Alternatively, you may run tests in shuffle without changing the config:
+
+{% highlight yaml %}
+codecept run -o "settings: shuffle: true"
+
+{% endhighlight %}
+
+
+Tests will be randomly reordered on each run. When tests executed in shuffle mode a seed value will be printed.
+Copy this seed value from output to be able to rerun tests in the same order.
+
+{% highlight yaml %}
+$ codecept run
+Codeception PHP Testing Framework v2.4.5
+Powered by PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
+[Seed] 1872290562
+
+{% endhighlight %}
+
+Pass the copied seed into `--seed` option:
+
+{% highlight yaml %}
+codecept run --seed 1872290562
+
+{% endhighlight %}
+
+### Dependencies
+
+With the `@depends` annotation you can specify a test that should be passed before the current one.
+If that test fails, the current test will be skipped. You should pass the method name of the test you are relying on.
+
+{% highlight php %}
+
+settings = $settings;
+ }
+
+ public function loadTests($filename)
+ {
+ //Load file and create tests
+ }
+
+ public function getTests()
+ {
+ return $this->tests;
+ }
+
+ public function getPattern()
+ {
+ return '~Myformat\.php$~';
+ }
+}
+
+{% endhighlight %}
+
+## Shell auto-completion
+
+For bash and zsh shells, you can use auto-completion for your Codeception projects by executing the following in your shell (or add it to your .bashrc/.zshrc):
+{% highlight bash %}
+
+# BASH ~4.x, ZSH
+source <([codecept location] _completion --generate-hook --program codecept --use-vendor-bin)
+
+# BASH ~3.x, ZSH
+[codecept location] _completion --generate-hook --program codecept --use-vendor-bin | source /dev/stdin
+
+# BASH (any version)
+eval $([codecept location] _completion --generate-hook --program codecept --use-vendor-bin)
+
+{% endhighlight %}
+
+### Explanation
+
+By using the above code in your shell, Codeception will try to autocomplete the following:
+* Commands
+* Suites
+* Test paths
+
+Usage of `-use-vendor-bin` is optional. This option will work for most Codeception projects, where Codeception is located in your `vendor/bin` folder.
+But in case you are using a global Codeception installation for example, you wouldn't use this option.
+
+Note that with the `-use-vendor-bin` option, your commands will be completed using the Codeception binary located in your project's root.
+Without the option, it will use whatever Codeception binary you originally used to generate the completion script ('codecept location' in the above examples)
+
+## Conclusion
+
+Codeception is a framework which may look simple at first glance
+but it allows you to build powerful tests with a single API, refactor them,
+and write them faster using the interactive console. Codeception tests can be easily organized in groups or Cest classes.
+
+
+
diff --git a/docs/BDD.md b/docs/BDD.md
new file mode 100644
index 000000000..2db9cc76f
--- /dev/null
+++ b/docs/BDD.md
@@ -0,0 +1,643 @@
+---
+layout: doc
+title: BDD - Codeception Docs
+---
+
+
+# Behavior Driven Development
+
+Behavior Driven Development (BDD) is a popular software development methodology. BDD is considered an extension of TDD, and is greatly inspired by [Agile](https://agilemanifesto.org/) practices. The primary reason to choose BDD as your development process is to break down communication barriers between business and technical teams. BDD encourages the use of automated testing to verify all documented features of a project from the very beginning. This is why it is common to talk about BDD in the context of test frameworks (like Codeception). The BDD approach, however, is about much more than testing - it is a common language for all team members to use during the development process.
+
+## What is Behavior Driven Development
+
+BDD was introduced by [Dan North](https://dannorth.net/introducing-bdd/). He described it as:
+
+> outside-in, pull-based, multiple-stakeholder, multiple-scale, high-automation, agile methodology. It describes a cycle of interactions with well-defined outputs, resulting in the delivery of working, tested software that matters.
+
+BDD has its own evolution from the days it was born, started by replacing "test" to "should" in unit tests, and moving towards powerful tools like Cucumber and Behat, which made user stories (human readable text) to be executed as an acceptance test.
+
+The idea of story BDD can be narrowed to:
+
+* describe features in a scenario with a formal text
+* use examples to make abstract things concrete
+* implement each step of a scenario for testing
+* write actual code implementing the feature
+
+By writing every feature in User Story format that is automatically executable as a test we ensure that: business, developers, QAs and managers are in the same boat.
+
+BDD encourages exploration and debate in order to formalize the requirements and the features that needs to be implemented by requesting to write the User Stories in a way that everyone can understand.
+
+By making tests to be a part of User Story, BDD allows non-technical personnel to write (or edit) Acceptance tests.
+
+With this procedure we also ensure that everyone in a team knows what has been developed, what has not, what has been tested and what has not.
+
+### Ubiquitous Language
+
+The ubiquitous language is always referred as *common* language. That is it's main benefit. It is not a couple of our business specification's words, and not a couple of developer's technical terms. It is a common words and terms that can be understood by people for whom we are building the software and should be understood by developers. Establishing correct communication between this two groups people is vital for building successful project that will fit the domain and fulfill all business needs.
+
+Each feature of a product should be born from a talk between
+
+* business (analysts, product owner)
+* developers
+* QAs
+
+which are known in BDD as "three amigos".
+
+Such talks should produce written stories. There should be an actor that doing some things, the feature that should be fulfilled within the story and the result achieved.
+
+We can try to write such simple story:
+
+{% highlight yaml %}
+As a customer I want to buy several products
+I put first product with $600 price to my cart
+And then another one with $1000 price
+When I go to checkout process
+I should see that total number of products I want to buy is 2
+And my order amount is $1600
+
+{% endhighlight %}
+
+As we can see this simple story highlights core concepts that are called *contracts*. We should fulfill those contracts to model software correctly. But how we can verify that those contracts are being satisfied? [Cucumber](https://cucumber.io) introduced a special language for such stories called **Gherkin**. Same story transformed to Gherkin will look like this:
+
+{% highlight gherkin %}
+
+Feature: checkout process
+ In order to buy products
+ As a customer
+ I want to be able to buy several products
+
+ Scenario:
+ Given I have product with $600 price in my cart
+ And I have product with $1000 price
+ When I go to checkout process
+ Then I should see that total number of products is 2
+ And my order amount is $1600
+
+{% endhighlight %}
+
+Cucumber, Behat, and sure, **Codeception** can execute this scenario step by step as an automated test.
+Every step in this scenario requires a code which defines it.
+
+## Gherkin
+
+Let's learn some more about Gherkin format and then we will see how to execute it with Codeception:
+
+### Features
+
+Whenever you start writing a story you are describing a specific feature of an application, with a set of scenarios and examples describing this feature.
+
+Feature file is written in Gherkin format. Codeception can generate a feature file for you.
+We will assume that we will use scenarios in feature files for acceptance tests, so feature files to be placed in `acceptance` suite directory:
+
+{% highlight bash %}
+
+php vendor/bin/codecept g:feature acceptance checkout
+
+{% endhighlight %}
+
+Generated template will look like this:
+
+{% highlight gherkin %}
+
+Feature: checkout
+ In order to ...
+ As a ...
+ I need to ...
+
+ Scenario: try checkout
+
+{% endhighlight %}
+
+This template can be fulfilled by setting actor and goals:
+
+{% highlight gherkin %}
+
+Feature: checkout
+ In order to buy product
+ As a customer
+ I need to be able to checkout the selected products
+
+{% endhighlight %}
+
+Next, we will describe this feature by writing examples for it
+
+#### Scenarios
+
+Scenarios are live examples of feature usage. Inside a feature file it should be written inside a *Feature* block. Each scenario should contain its title:
+
+{% highlight gherkin %}
+
+Feature: checkout
+ In order to buy product
+ As a customer
+ I need to be able to checkout the selected products
+
+Scenario: order several products
+
+{% endhighlight %}
+
+Scenarios are written in step-by-step manner using Given-When-Then approach. At start, scenario should describe its context with **Given** keyword:
+
+{% highlight gherkin %}
+
+ Given I have product with $600 price in my cart
+ And I have product with $1000 price in my cart
+
+{% endhighlight %}
+
+Here we also use word **And** to extend the Given and not to repeat it in each line.
+
+This is how we described the initial conditions. Next, we perform some action. We use **When** keyword for it:
+
+{% highlight gherkin %}
+
+ When I go to checkout process
+
+{% endhighlight %}
+
+And in the end we are verifying our expectation using **Then** keyword. The action changed the initial given state, and produced some results. Let's check that those results are what we actually expect.
+
+{% highlight gherkin %}
+
+ Then I should see that total number of products is 2
+ And my order amount is $1600
+
+{% endhighlight %}
+
+We can test this scenario by executing it in dry-run mode. In this mode test won't be executed (actually, we didn't define any step for it, so it won't be executed in any case).
+
+{% highlight bash %}
+
+$ codecept dry-run acceptance checkout.feature
+
+{% endhighlight %}
+
+{% highlight bash %}
+
+checkout: order several products
+Signature: checkout:order several products
+Test: tests/acceptance/checkout.feature:order several products
+Scenario --
+ In order to buy product
+ As a customer
+ I need to be able to checkout the selected products
+ Given i have product with $600 price in my cart
+ And i have product with $1000 price in my cart
+ When i go to checkout process
+ Then i should see that total number of products is 2
+ And my order amount is $1600
+
+ INCOMPLETE
+Step definition for `I have product with $600 price in my cart` not found in contexts
+Step definition for `I have product with $1000 price` not found in contexts
+Step definition for `I go to checkout process` not found in contexts
+Step definition for `I should see that total number of products is 2` not found in contexts
+Step definition for `my order amount is $1600` not found in contexts
+Run gherkin:snippets to define missing steps
+
+{% endhighlight %}
+
+Besides the scenario steps listed we got the notification that our steps are not defined yet.
+We can define them easily by executing `gherkin:snippets` command for the given suite:
+
+{% highlight bash %}
+
+codecept gherkin:snippets acceptance
+
+{% endhighlight %}
+
+This will produce code templates for all undefined steps in all feature files of this suite.
+Our next step will be to define those steps and transforming feature-file into valid test.
+
+### Step Definitions
+
+To match steps from a feature file to PHP code we use annotation which are added to class methods.
+By default Codeception expects that all methods marked with `@Given`, `@When`, `@Then` annotation.
+Each annotation should contain a step string.
+
+{% highlight yaml %}
+/** @Given I am logged as admin */
+
+{% endhighlight %}
+
+Steps can also be matched with regex expressions. This way we can make more flexible steps
+
+{% highlight yaml %}
+/** @Given /I am (logged|authorized) as admin/ */
+
+{% endhighlight %}
+
+Please note that regular expressions should start and end with `/` char. Regex is also used to match parameters and pass them as arguments into methods.
+
+{% highlight php %}
+
+`. You can use `amOnPage`, `click`, `see` methods inside a step definitions, so each Gherkin scenario step to be extended with basic Codeception steps. Let's show how it can be implemented in our case:
+
+{% highlight php %}
+
+haveRecord('Product', ['name' => 'randomProduct'.uniqid(), 'price' => $num1]);
+ $this->amOnPage("/item/$productId");
+ $this->click('Order');
+ }
+
+ /**
+ * @When I go to checkout process
+ */
+ public function iGoToCheckoutProcess()
+ {
+ $this->amOnPage('/checkout');
+ }
+
+ /**
+ * @Then I should see that total number of products is :num1
+ */
+ public function iShouldSeeThatTotalNumberOfProductsIs($num1)
+ {
+ $this->see($num1, '.products-count');
+ }
+
+ /**
+ * @Then my order amount is :num1
+ */
+ public function myOrderAmountIs($num1)
+ {
+ $this->see($num1, '.total');
+ }
+}
+
+{% endhighlight %}
+
+To make testing more effective we assumed that we are using one of the ActiveRecord frameworks like Laravel, Yii, or Phalcon so we are able to dynamically create records in database with `haveRecord` method. After that we are opening browser and testing our web pages to see that after selecting those products we really see the price was calculated correctly.
+
+We can dry-run (or run) our feature file to see that Given/When/Then are expanded with substeps:
+
+{% highlight bash %}
+
+ Given i have product with $600 price in my cart
+ I have record 'Product',{"name":"randomProduct571fad4f88a04","price":"600"}
+ I am on page "/item/1"
+ I click "Order"
+ And i have product with $1000 price in my cart
+ I have record 'Product',{"name":"randomProduct571fad4f88b14","price":"1000"}
+ I am on page "/item/2"
+ I click "Order"
+ When i go to checkout process
+ I am on page "/checkout"
+ Then i should see that total number of products is 2
+ I see "2",".products-count"
+ And my order amount is $1600
+ I see "1600",".total"
+
+{% endhighlight %}
+
+This way feature file runs just the same as any other Codeception test. Substeps give us detailed information of how the scenario is being executed.
+
+One of the criticism for testing with Gherkin was that only technical team were aware of how the test scenario is executed. This could have lead to false-positive tests. Developers could have used empty steps for scenarios (or irrelevant ones) and produced invalid tests for valid scenarios. Codeception brings communication to a next level, everyone in a team can understand what happens on a lower (technical) level. Scenario expanding to substeps shows the actual test execution process. Anyone in a team can read the output, and invest their efforts into improving the test suite.
+
+## Advanced Gherkin
+
+Let's improve our BDD suite by using the advanced features of Gherkin language.
+
+### Background
+
+If a group of scenarios have the same initial steps, let's that for dashboard we always need to be logged in as administrator. We can use *Background* section to do the required preparations and not to repeat same steps across scenarios.
+
+{% highlight gherkin %}
+
+Feature: Dashboard
+ In order to view current state of business
+ As an owner
+ I need to be able to see reports on dashboard
+
+ Background:
+ Given I am logged in as administrator
+ And I open dashboard page
+
+{% endhighlight %}
+
+Steps in background are defined the same way as in scenarios.
+
+### Tables
+
+Scenarios can become more descriptive when you represent repeating data as tables. Instead of writing several steps "I have product with :num1 $ price in my cart" we can have one step with multiple values in it.
+
+{% highlight gherkin %}
+
+ Given i have products in my cart
+ | name | category | price |
+ | Harry Potter | Books | 5 |
+ | iPhone 5 | Smartphones | 1200 |
+ | Nuclear Bomb | Weapons | 100000 |
+
+{% endhighlight %}
+
+Tables is a recommended ways to pass arrays into test scenarios.
+Inside a step definition data is stored in argument passed as `\Behat\Gherkin\Node\TableNode` instance.
+
+{% highlight php %}
+
+getRows() as $index => $row) {
+ if ($index === 0) { // first row to define fields
+ $keys = $row;
+ continue;
+ }
+ $this->haveRecord('Product', array_combine($keys, $row));
+ }
+ }
+
+{% endhighlight %}
+
+### Examples
+
+In case scenarios represent the same logic but differ on data, we can use *Scenario Outline* to provide different examples for the same behavior. Scenario outline is just like a basic scenario with some values replaced with placeholders, which are filled from a table. Each set of values is executed as a different test.
+
+{% highlight gherkin %}
+
+ Scenario Outline: order discount
+ Given I have product with price $ in my cart
+ And discount for orders greater than $20 is 10 %
+ When I go to checkout
+ Then I should see overall price is "" $
+
+ Examples:
+ | price | total |
+ | 10 | 10 |
+ | 20 | 20 |
+ | 21 | 18.9 |
+ | 30 | 27 |
+ | 50 | 45 |
+
+{% endhighlight %}
+
+### Long Strings
+
+Text values inside a scenarios can be set inside a `"""` block:
+
+{% highlight gherkin %}
+
+ Then i see in file "codeception.yml"
+"""
+paths:
+ tests: tests
+ log: tests/_output
+ data: tests/_data
+ helpers: tests/_support
+ envs: tests/_envs
+"""
+
+{% endhighlight %}
+
+This string is passed as a standard PHP string parameter
+
+{% highlight php %}
+
+fail("File $fileName not found");
+ }
+ $this->assertEquals(file_get_contents($fileName), $fileContents);
+ }
+
+{% endhighlight %}
+
+### Tags
+
+Gherkin scenarios and features can contain tags marked with `@`. Tags are equal to groups in Codeception.
+This way if you define a feature with `@important` tag, you can execute it inside `important` group by running:
+
+{% highlight bash %}
+
+codecept run -g important
+
+{% endhighlight %}
+
+Tag should be placed before *Scenario:* or before *Feature:* keyword. In the last case all scenarios of that feature will be added to corresponding group.
+
+## Configuration
+
+As we mentioned earlier, steps should be defined inside context classes. By default all the steps are defined inside an Actor class, for instance, `AcceptanceTester`. However, you can include more contexts. This can be configured inside global `codeception.yml` or suite configuration file:
+
+{% highlight yaml %}
+
+gherkin:
+ contexts:
+ default:
+ - AcceptanceTester
+ - AdditionalSteps
+
+{% endhighlight %}
+
+`AdditionalSteps` file should be accessible by autoloader and can be created by `Codeception\Lib\Di`. This means that practically any class can be a context. If a class receives an actor class in constructor or in `_inject` method, DI can inject it into it.
+
+{% highlight php %}
+
+I = $I;
+ }
+
+ /**
+ * @When I do something
+ */
+ function additionalActions()
+ {
+ }
+}
+
+{% endhighlight %}
+This way PageObjects, Helpers and StepObjects can become contexts as well. But more preferable to include context classes by their tags or roles.
+
+If you have `Step\Admin` class which defines only admin steps, it is a good idea to use it as context for all features containing with "As an admin". In this case "admin" is a role and we can configure it to use additional context.
+
+{% highlight yaml %}
+
+gherkin:
+ contexts:
+ role:
+ admin:
+ - "Step\Admin"
+
+{% endhighlight %}
+
+Contexts can be attached to tags as well. This may be useful if you want to redefine steps for some scenarios. Let's say we want to bypass login steps for some scenarios loading already defined session. In this case we can create `Step\FastLogin` class with redefined step "I am logged in as".
+
+{% highlight yaml %}
+
+gherkin:
+ contexts:
+ tag:
+ fastlogin:
+ - "Step\FastLogin"
+
+{% endhighlight %}
+
+Contexts can be autoloaded as well:
+{% highlight yaml %}
+
+gherkin:
+ contexts:
+ path: tests/_support/Steps
+ namespace_prefix: Steps
+ default:
+ - AcceptanceTester
+
+{% endhighlight %}
+This will load all context from the given path and prefix it with the given namespace.
+
+## Migrating From Behat
+
+While Behat is a great tool for Behavior Driven Development, you still may prefer to use Codeception as your primary testing framework. In case you want to unify all your tests (unit/functional/acceptance), and make them be executed with one runner, Codeception is a good choice. Also Codeception provides rich set of well-maintained modules for various testing backends like Selenium Webdriver, Symfony, Laravel, etc.
+
+If you decided to run your features with Codeception, we recommend to start with symlinking your `features` directory into one of the test suites:
+
+{% highlight bash %}
+
+ln -s $PWD/features tests/acceptance
+
+{% endhighlight %}
+
+Then you will need to implement all step definitions. Run `gherkin:snippets` to generate stubs for them.
+By default it is recommended to place step definitions into actor class (Tester) and use its methods for steps implementation.
+
+## Tests vs Features
+
+It is common to think that BDD scenario is equal to test. But it's actually not. Not every test should be described as a feature. Not every test is written to test real business value. For instance, regression tests or negative scenario tests are not bringing any value to business. Business analysts don't care about scenario reproducing bug #13, or what error message is displayed when user tries to enter wrong password on login screen. Writing all the tests inside a feature files creates informational overflow.
+
+In Codeception you can combine tests written in Gherkin format with tests written in Cept/Cest/Test formats. This way you can keep your feature files compact with minimal set of scenarios, and write regular tests to cover all cases.
+
+Corresponding features and tests can be attached to the same group. And what is more interesting, you can make tests to depend on feature scenarios. Let's say we have `login.feature` file with "Log regular user" scenario in it. In this case you can specify that every test which requires login to pass to depend on "Log regular user" scenario:
+
+{% highlight yaml %}
+@depends login:Log regular user
+
+{% endhighlight %}
+
+Inside `@depends` block you should use test signature. Execute your feature with `dry-run` to see signatures for all scenarios in it. By marking tests with `@depends` you ensure that this test won't be executed before the test it depends on.
+
+## Conclusions
+
+If you like the concept of Behavior Driven Development or prefer to keep test scenarios in human readable format, Codeception allows you to write and execute scenarios in Gherkin. Feature files is just another test format inside Codeception, so it can be combined with Cept and Cest files inside the same suite. Steps definitions of your scenarios can use all the power of Codeception modules, PageObjects, and StepObjects.
+
+
+
diff --git a/docs/Codecoverage.md b/docs/Codecoverage.md
new file mode 100644
index 000000000..e2ea554b0
--- /dev/null
+++ b/docs/Codecoverage.md
@@ -0,0 +1,220 @@
+---
+layout: doc
+title: Codecoverage - Codeception Docs
+---
+
+
+# Code Coverage
+
+At some point you want to review which parts of your application are tested well and which are not.
+Just for this case the [CodeCoverage](https://en.wikipedia.org/wiki/Code_coverage) is used. When you execute your tests to collect coverage report,
+you will receive statistics of all classes, methods, and lines triggered by these tests.
+The ratio between all lines in script and all touched lines is a main coverage criterion. In the ideal world you should get 100% code coverage, but in reality 80% is really enough. Because even 100% code coverage rate doesn't save you from fatal errors and crashes.
+
+The required information is provided by [SebastianBergmann\CodeCoverage](https://github.com/sebastianbergmann/php-code-coverage), and you can use any of the supported drivers.
+
+| Driver | Description |
+| --- | --- |
+| [Xdebug](https://github.com/xdebug/xdebug) | Great for debugging, but too slow when collecting coverage |
+| [phpdbg](https://www.php.net/manual/en/book.phpdbg.php) | Faster than `Xdebug` but inaccurate |
+| [pcov](https://github.com/krakjoe/pcov) | Fast and accurate, but no debug functionality — perfect for CI |
+
+
+
+Coverage data can be collected manually for both local and remote tests. Remote tests may be executed on different nodes,
+or locally but running through web server. It may look hard to collect code coverage for Selenium tests or PhpBrowser tests. But Codeception supports remote codecoverage as well as local.
+
+### Configuration
+
+To enable code coverage put these lines in the global configuration file `codeception.yml`:
+
+{% highlight yaml %}
+
+coverage:
+ enabled: true
+
+{% endhighlight %}
+
+That's ok for now. But what files should be present in final coverage report?
+Pass an array of files or directory to include/exclude sections. The path ending with '\*' matches the directory.
+Also you can use '\*' mask in a file name, i.e. `app/models/*Model.php` to match all models.
+
+There is a shortcut if you don't need that complex filters:
+
+{% highlight yaml %}
+
+coverage:
+ enabled: true
+ include:
+ - app/*
+ exclude:
+ - app/cache/*
+
+{% endhighlight %}
+Include and exclude options can be redefined for each suite in corresponding config files.
+
+By default, if coverage is reported to be < 35% it is marked as low, and >70% is high coverage.
+You can also define high and low boundaries with `low_limit` and `high_limit` config options:
+
+{% highlight yaml %}
+
+coverage:
+ enabled: true
+ low_limit: 30
+ high_limit: 60
+
+{% endhighlight %}
+
+By default, show all whitelisted files in `--coverage-text` output not just the ones with coverage information is set to false, config option:
+
+{% highlight yaml %}
+
+coverage:
+ enabled: true
+ show_uncovered: false
+
+{% endhighlight %}
+
+By default, show only the coverage report summary in `--coverage-text` output is set to false, config option:
+
+{% highlight yaml %}
+
+coverage:
+ enabled: true
+ show_only_summary: false
+
+{% endhighlight %}
+
+For further information please refer to the [PHPUnit configuration docs](https://phpunit.readthedocs.io/en/latest/configuration.html)
+
+## Local CodeCoverage
+
+The basic codecoverage can be collected for functional and unit tests.
+If you performed configuration steps from above, you are ready to go.
+All you need is to execute codeception with `--coverage` option.
+
+To generate a clover xml report or a tasty html report append also `--coverage-xml` and `--coverage-html` options.
+
+{% highlight yaml %}
+
+codecept run --coverage --coverage-xml --coverage-html
+
+{% endhighlight %}
+
+XML and HTML reports are stored to the `_output` directory. The best way to review report is to open `index.html` from `tests/_output/coverage` in your browser.
+XML clover reports are used by IDEs (like PHPStorm) or Continuous Integration servers (like Jenkins).
+
+## Remote CodeCoverage
+
+### Local Server
+
+If you run your application via Webserver (Apache, Nginx, PHP WebServer) you don't have a direct access to tested code,
+so collecting coverage becomes a non-trivial task. The same goes for scripts that are tested on different nodes.
+To get access to this code you need `xdebug` installed with `remote_enable` option turned on.
+Codeception also requires a little spy to interact with your application. As your application runs standalone,
+without even knowing it is being tested, a small file should be included in order to collect coverage info.
+
+This file is called `c3.php` and is [available on GitHub](https://github.com/Codeception/c3).
+`c3.php` should be downloaded and included in your application at the very first line from controller.
+By sending special headers Codeception will command your application when to start codecoverage collection and when to stop it.
+After the suite is finished, a report will be stored and Codeception will grab it from your application.
+
+Please, follow installation instructions described in a [readme file](https://github.com/Codeception/c3).
+
+To connect to `c3` Codeception uses url config from PhpBrowser or WebDriver module.
+But URL of index with `c3.php` included can be specified explicitly with `c3_url` parameter defined:
+
+{% highlight yaml %}
+
+coverage:
+ # url of file which includes c3 router.
+ c3_url: 'http://127.0.0.1:8000/index-test.php/'
+
+{% endhighlight %}
+> note: we can't have multiple `c3_url` on same host difference only by port. Please, use alias of domain
+(i.e. `frontend.test:8000`,`backend.test:8080`) instead.
+
+After the `c3.php` file is included in application you can start gather coverage.
+In case you execute your application locally there is nothing to be changed in config.
+All codecoverage reports will be collected as usual and merged afterwards.
+Think of it: Codeception runs remote coverage in the same way as local.
+
+#### Custom cookie domain
+
+It's possible to override the cookie domain set by Codeception during code coverage. Typical case for that is when you
+have several subdomains that your acceptance tests are visiting, e.g. `mysite.com` and `admin.mysite.com`. By default,
+Codeception will run code coverage only for the domain set in the url of the `WebDriver/url` (or `c3_url` if defined),
+thus leaving out other subdomains from code coverage. To avoid that and to include all relevant subdomains in code
+covereage, it's advised to set `.mysite.com` as the cookie domain option:
+
+{% highlight yaml %}
+
+coverage:
+ cookie_domain: ".mysite.com"
+
+{% endhighlight %}
+
+### Remote Server
+
+But if you run tests on different server (or your webserver doesn't use code from current directory) a single option `remote` should be added to config.
+For example, let's turn on remote coverage for acceptance suite in `acceptance.suite.yml`:
+
+{% highlight yaml %}
+
+coverage:
+ remote: true
+
+{% endhighlight %}
+
+In this case remote Code Coverage results won't be merged with local ones, if this option is enabled.
+Merging is possible only in case a remote and local files have the same path.
+But in case of running tests on a remote server we are not sure of it.
+
+CodeCoverage results from remote server will be saved to `tests/_output` directory. Please note that remote codecoverage results won't be displayed in console by the reason mentioned above: local and remote results can't be merged, and console displays results for local codecoverage.
+
+### Working Directory (Docker/Shared Mounts)
+
+If your remote server is accessed through a shared mount, or a mounted folder (IE: Docker Volumes), you can still get merged coverage details.
+Use the `work_dir` option to specify the work directory. When CodeCoverage runs, Codeception will update any path that matches the `work_dir` option to match the local current project directory.
+
+Given a docker command similar to:
+{% highlight bash %}
+
+docker run -v $(pwd):/workdir -w /workdir...
+
+{% endhighlight %}
+
+Use the below configuration to allow coverage mergers.
+{% highlight yaml %}
+
+coverage:
+ remote: false
+ work_dir: /workdir
+
+
+{% endhighlight %}
+
+### Remote Context Options
+
+HTML report generation can at times take a little more time than the default 30 second timeout. Or maybe you want to alter SSL settings (verify_peer, for example)
+To alter the way c3 sends it's service requests to your webserver (be it a local or a remote one), you can use the `remote_context_options` key in `coverage` settings.
+
+{% highlight yaml %}
+
+coverage:
+ remote_context_options:
+ http:
+ timeout: 60
+ ssl:
+ verify_peer: false
+
+{% endhighlight %}
+
+Context stream options are [well documented at php.net](https://php.net/manual/en/context.php)
+
+## Conclusion
+
+It's never been easier to setup local and remote code coverage. Just one config and one additional file to include!
+**With Codeception you can easily generate CodeCoverage reports for your Selenium tests** (or other acceptance or api tests). Mixing reports for `acceptance`, `functional`, and `unit` suites provides you with the most complete information on which parts of your applications are tested and which are not.
+
+
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
new file mode 100644
index 000000000..51ce13804
--- /dev/null
+++ b/docs/ContinuousIntegration.md
@@ -0,0 +1,212 @@
+---
+layout: doc
+title: Continuous Integration - Codeception Docs
+---
+
+
+# Continuous Integration
+
+Once you get testing suite up and running you are interested in running your tests regularly. If you ensure that tests are running on every code change or at least once a day you can be sure that no regression is introduced. This allows to keep you system stable. But developers are not so passionate about running all tests manually, they also can forget to execute tests before pushing code to production... The solution is simple, test execution should be automated. Instead of running them locally it is better to have dedicated server responsible for running tests for a team. This way we can ensure that everyone's tests executed, which commit made a regression in codebase, and that we can deploy only once tests pass.
+
+There are many Continuous Integration Servers out there. We will try to list basic steps to setup Codeception tests with them. If your CI system is not mentioned, you can get the idea by analogy. Please also help us to extend this guide by adding instructions for different CIs.
+
+## Jenkins
+
+
+
+[Jenkins](https://jenkins-ci.org/) is one of the most popular open-source solution on market. It is easy to setup and is easy to customize by applying various plugins.
+
+
+
+### Preparing Jenkins
+
+It is recommended to have the next plugins installed:
+
+* **Git Plugin** - for building tests for Git repo
+* **Green Balls** - to display success results in green.
+* **xUnit Plugin**, **jUnit Plugin** - to process and display Codeception XML reports
+* **HTML Publisher Plugin** - to process Codeception HTML reports
+* **AnsiColor** - to show colorized console output.
+
+
+
+### Basic Setup
+
+At first we need to create build project. Depending on your needs you can set up periodical build or trigger build once the change is pushed to GitHub (you will need GitHub plugin for that).
+
+We need to define build steps. The most simple setup may look like this:
+
+{% highlight php %}
+ vendor/bin/codecept run
+
+{% endhighlight %}
+
+
+
+Then we can start the very first job and check the execution progress. If tests fail we will see that in console:
+
+
+
+### XML Reports
+
+But we don't want to analyze console output for each failing build. Especially If Jenkins can collect and display the results inside its web UI. Codeception can export its results using JUnit XML format. To generate XML report on each build we will need to append `--xml` option to Codeception execution command. Codeception will print `result.xml` file containing information about test status with steps and stack traces for failing tests.
+
+Now let's update our build step to generate xml:
+
+{% highlight php %}
+ vendor/bin/codecept run --xml
+
+{% endhighlight %}
+
+and ask Jenkins to collect resulted XML. This can be done as part of Post-build actions. Let's add *Publish xUnit test result report* action and configure it to use with PHPUnit reports.
+
+
+
+Now we should specify path to PHPUnit style XML reports. In case of standard Codeception setup we should specify `tests/_output/*.xml` as a pattern for matching resulted XMLs. Now we save the project and rebuild it.
+
+
+
+Now for all builds we will see results trend graph that shows us percentage of passing and failing tests. We also will see a **Latest Test Result** link which will lead to to the page where all executed tests and their stats listed in a table.
+
+### HTML Reports
+
+To get more details on steps executed you can generate HTML report and use Jenkins to display them.
+
+{% highlight php %}
+ vendor/bin/codecept run --html
+
+{% endhighlight %}
+
+Now we need HTML Publisher plugin configured to display generated HTML files. It should be added as post-build action similar way we did it for XML reports.
+
+
+
+Jenkins should locate `report.html` at `tests/_output/`. Now Jenkins will display HTML reports for each build.
+
+
+
+
+## TeamCity
+
+
+
+TeamCity is a hosted solution from JetBrains. The setup of it can be a bit tricky as TeamCity uses its own reporter format for parsing test results. PHPUnit since version 5.x has integrated support for this format, so does Codeception. What we need to do is to configure Codeception to use custom reporter. By default there is `--report` option which provides an alternative output. You can change the reporter class in `codeception.yml` configuration:
+
+{% highlight yaml %}
+
+reporters:
+ report: PHPUnit_Util_Log_TeamCity
+
+{% endhighlight %}
+
+As an alternative you can use 3rd-party [TeamCity extension](https://github.com/neronmoon/TeamcityCodeception) for better reporting.
+
+After you create build project you should define build step with Codeception which is
+
+{% highlight php %}
+ vendor/bin/codecept run --report
+
+{% endhighlight %}
+
+
+
+Once you execute your first build you should see detailed report inside TeamCity interface:
+
+
+
+## TravisCI
+
+
+
+Travis CI is popular service CI with good GitHub integration. Codeception is self-tested with Travis CI. There nothing special about configuration. Just add to the bottom line of travis configuration:
+
+{% highlight yaml %}
+
+php vendor/bin/codecept run
+
+{% endhighlight %}
+
+More details on configuration can be learned from Codeception's [`.travis.yml`](https://github.com/Codeception/Codeception/blob/3.0/.travis.yml).
+
+Travis doesn't provide visualization for XML or HTML reports so you can't view reports in format any different than console output. However, Codeception produces nice console output with detailed error reports.
+
+## GitLab
+
+
+
+If a file `.gitlab-ci.yml` exists in the root of the git repository, GitLab will run a pipeline each time you push to the gitlab server. The file configures the docker image that will be called. Below is a sample which loads a php7 docker image, clones your files, installs composer dependencies, runs the built-in php webserver and finally runs codeception:
+
+{% highlight yaml %}
+
+# Select image from https://hub.docker.com/_/php/
+image: php:7.0
+
+# Select what we should cache
+cache:
+ paths:
+ - vendor/
+
+before_script:
+# Install git and unzip (composer will need them)
+- apt-get update && apt-get install -qqy git unzip
+# Install composer
+- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
+# Install all project dependencies
+- composer install
+# Run webserver
+- php -S localhost:8085 --docroot public &>/dev/null&
+
+# Test
+test:
+ script:
+ - vendor/bin/codecept run
+
+{% endhighlight %}
+
+
+
+For acceptance testing you can use `codeception/codeception` docker image as base. See example below:
+
+{% highlight yaml %}
+
+
+image:
+ name: codeception/codeception
+ # clear image entrypoint to make bash being available
+ entrypoint: [""]
+
+# run selenium chrome as a local service (put "host: 'selenium__standalone-chrome'" in environment configuration)
+services:
+ - selenium/standalone-chrome:latest
+
+# Select what we should cache
+cache:
+ paths:
+ - vendor/
+
+before_script:
+# Install all project dependencies
+- composer install
+
+# Test
+test:
+ script:
+ - vendor/bin/codecept run acceptance --xml --html
+ artifacts:
+ when: always
+ expire_in: 1 week
+ paths:
+ - tests/_output
+ # make the report available in Gitlab UI. see https://docs.gitlab.com/ee/ci/unit_test_reports.html
+ reports:
+ junit: tests/_output/report.xml
+
+{% endhighlight %}
+
+
+## Conclusion
+
+It is highly recommended to use Continuous Integration system in development. Codeception is easy to install and run in any CI systems. However, each of them has their differences you should take into account. You can use different reporters to provide output in format expected by CI system.
+
+
+
diff --git a/docs/Customization.md b/docs/Customization.md
new file mode 100644
index 000000000..4b60b7de4
--- /dev/null
+++ b/docs/Customization.md
@@ -0,0 +1,499 @@
+---
+layout: doc
+title: Customization - Codeception Docs
+---
+
+
+# Customization
+
+In this chapter we will explain how you can extend and customize the file structure and test execution routines.
+
+### Namespaces
+
+To avoid naming conflicts between Actor classes and Helper classes, they should be separated into namespaces.
+To create test suites with namespaces you can add `--namespace` option to the bootstrap command:
+
+{% highlight bash %}
+
+php vendor/bin/codecept bootstrap --namespace frontend
+
+{% endhighlight %}
+
+This will bootstrap a new project with the `namespace: frontend` parameter in the `codeception.yml` file.
+Helpers will be in the `frontend\Codeception\Module` namespace and Actor classes will be in the `frontend` namespace.
+
+Once each of your applications (bundles) has its own namespace and different Helper or Actor classes,
+you can execute all the tests in a single runner. Run the Codeception tests as usual, using the meta-config we created earlier:
+
+{% highlight bash %}
+
+php vendor/bin/codecept run
+
+{% endhighlight %}
+
+This will launch the test suites for all three applications and merge the reports from all of them.
+This is very useful when you run your tests on a Continuous Integration server
+and you want to get a single report in JUnit and HTML format. The code coverage report will be merged too.
+
+If you want to run a specific suite from the application you can execute:
+
+{% highlight php %}
+ vendor/bin/codecept run unit -c frontend
+
+{% endhighlight %}
+
+Where `unit` is the name of suite and the `-c` option specifies the path to the `codeception.yml` configuration file to use.
+In this example we will assume that there is `frontend/codeception.yml` configuration file
+and that we will execute the unit tests for only that app.
+
+## Bootstrap
+
+To prepare environment for testing you can execute custom PHP script before all tests or just before a specific suite.
+This way you can initialize autoloader, check availability of a website, etc.
+
+### Global Bootstrap
+
+To run bootstrap script before all suites place it in `tests` directory (absolute paths supported as well).
+Then set a `bootstrap` config key in `codeception.yml`:
+
+{% highlight yaml %}
+yml
+# file will be loaded from tests/bootstrap.php
+bootstrap: bootstrap.php
+
+{% endhighlight %}
+
+### Suite Bootstrap
+
+To run a script for a specific suite, place it into the suite directory and add to suite config:
+
+{% highlight yaml %}
+yml
+# inside .suite.yml
+# file will be loaded from tests//bootstrap.php
+bootstrap: bootstrap.php
+
+{% endhighlight %}
+
+### On Fly Bootstrap
+
+Bootstrap script can be executed with `--bootstrap` option for `codecept run` command:
+
+{% highlight php %}
+ vendor/bin/codecept run --bootstrap bootstrap.php
+
+{% endhighlight %}
+
+In this case, bootstrap script will be executed before the Codeception is initialized.
+Bootstrap script should be located in current working directory or by an absolute path.
+
+> Bootstrap is a classical way to run custom PHP code before your tests.
+However, we recommend you to use Extensions instead of bootstrap scripts for better flexibility.
+If you need configuration, conditional enabling or disabling bootstrap script, extensions should work for you better.
+
+## Extension
+
+Codeception has limited capabilities to extend its core features.
+Extensions are not supposed to override current functionality,
+but can be useful if you are an experienced developer and you want to hook into the testing flow.
+
+By default, one `RunFailed` Extension is already enabled in your global `codeception.yml`.
+It allows you to rerun failed tests by using the `-g failed` option:
+
+{% highlight php %}
+ vendor/bin/codecept run -g failed
+
+{% endhighlight %}
+
+Codeception comes with bundled extensions located in `ext` directory.
+For instance, you can enable the Logger extension to log the test execution with Monolog:
+
+{% highlight yaml %}
+
+extensions:
+ enabled:
+ - Codeception\Extension\RunFailed # default extension
+ - Codeception\Extension\Logger: # enabled extension
+ max_files: 5 # logger configuration
+
+{% endhighlight %}
+
+But what are extensions, anyway? Basically speaking, extensions are nothing more than event listeners
+based on the [Symfony Event Dispatcher](https://symfony.com/doc/current/components/event_dispatcher/introduction.html) component.
+
+### Events
+
+Here are the events and event classes. The events are listed in the order in which they happen during execution.
+All listed events are available as constants in `Codeception\Events` class.
+
+| Event | When? | Triggered by
+|:--------------------:| --------------------------------------- | --------------------------:
+| `suite.before` | Before suite is executed | [Suite, Settings](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/SuiteEvent.php)
+| `test.start` | Before test is executed | [Test](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/TestEvent.php)
+| `test.before` | At the very beginning of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/TestEvent.php)
+| `step.before` | Before step | [Step](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/StepEvent.php)
+| `step.after` | After step | [Step](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/StepEvent.php)
+| `step.fail` | After failed step | [Step](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/StepEvent.php)
+| `test.fail` | After failed test | [Test, Fail](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/FailEvent.php)
+| `test.error` | After test ended with error | [Test, Fail](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/FailEvent.php)
+| `test.incomplete` | After executing incomplete test | [Test, Fail](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/FailEvent.php)
+| `test.skipped` | After executing skipped test | [Test, Fail](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/FailEvent.php)
+| `test.success` | After executing successful test | [Test](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/TestEvent.php)
+| `test.after` | At the end of test execution | [Codeception Test](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/TestEvent.php)
+| `test.end` | After test execution | [Test](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/TestEvent.php)
+| `suite.after` | After suite was executed | [Suite, Result, Settings](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/SuiteEvent.php)
+| `test.fail.print` | When test fails are printed | [Test, Fail](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/FailEvent.php)
+| `result.print.after` | After result was printed | [Result, Printer](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Event/PrintResultEvent.php)
+
+There may be some confusion between `test.start`/`test.before` and `test.after`/`test.end`.
+The start and end events are triggered by PHPUnit, but the before and after events are triggered by Codeception.
+Thus, when you are using classical PHPUnit tests (extended from `PHPUnit\Framework\TestCase`),
+the before/after events won't be triggered for them. During the `test.before` event you can mark a test
+as skipped or incomplete, which is not possible in `test.start`. You can learn more from
+[Codeception internal event listeners](https://github.com/Codeception/Codeception/tree/4.0/src/Codeception/Subscriber).
+
+The extension class itself is inherited from `Codeception\Extension`:
+
+{% highlight php %}
+
+ 'afterSuite',
+ Events::TEST_BEFORE => 'beforeTest',
+ Events::STEP_BEFORE => 'beforeStep',
+ Events::TEST_FAIL => 'testFailed',
+ Events::RESULT_PRINT_AFTER => 'print',
+ );
+
+ // methods that handle events
+
+ public function afterSuite(\Codeception\Event\SuiteEvent $e) {}
+
+ public function beforeTest(\Codeception\Event\TestEvent $e) {}
+
+ public function beforeStep(\Codeception\Event\StepEvent $e) {}
+
+ public function testFailed(\Codeception\Event\FailEvent $e) {}
+
+ public function print(\Codeception\Event\PrintResultEvent $e) {}
+}
+
+{% endhighlight %}
+
+By implementing event handling methods you can listen for events and even update passed objects.
+Extensions have some basic methods you can use:
+
+* `write` - prints to the screen
+* `writeln` - prints to the screen with a new-line character at the end
+* `getModule` - allows you to access a module
+* `hasModule` - checks if a module is enabled
+* `getModuleNames` - list all enabled modules
+* `_reconfigure` - can be implemented instead of overriding the constructor
+
+### Enabling Extension
+
+Once you've implemented a simple extension class, you can require it in `tests/_bootstrap.php`,
+load it with Composer's autoloader defined in `composer.json`, or store the class inside `tests/_support`dir.
+
+You can then enable it in `codeception.yml`
+
+{% highlight yaml %}
+
+extensions:
+ enabled: [MyCustomExtension]
+
+{% endhighlight %}
+
+Extensions can also be enabled per suite inside suite configs (like `acceptance.suite.yml`) and for a specific environment.
+
+To enable extension dynamically, execute the `run` command with `--ext` option.
+Provide a class name as a parameter:
+
+{% highlight bash %}
+
+php vendor/bin/codecept run --ext MyCustomExtension
+php vendor/bin/codecept run --ext "\My\Extension"
+
+{% endhighlight %}
+
+If a class is in a `Codeception\Extension` namespace you can skip it and provide only a shortname.
+So Recorder extension can be started like this:
+
+{% highlight bash %}
+
+php vendor/bin/codecept run --ext Recorder
+
+{% endhighlight %}
+
+### Configuring Extension
+
+In the extension, you can access the currently passed options via the `options` property.
+You also can access the global configuration via the `\Codeception\Configuration::config()` method.
+If you want to have custom options for your extension, you can pass them in the `codeception.yml` file:
+
+{% highlight yaml %}
+
+extensions:
+ enabled: [MyCustomExtension]
+ config:
+ MyCustomExtension:
+ param: value
+
+{% endhighlight %}
+
+The passed in configuration is accessible via the `config` property: `$this->config['param']`.
+
+Check out a very basic extension [Notifier](https://github.com/Codeception/Notifier).
+
+### Custom Commands
+
+You can add your own commands to Codeception.
+
+Your custom commands have to implement the interface Codeception\CustomCommandInterface,
+because there has to be a function to get the name of the command.
+
+You have to register your command in the file `codeception.yml`:
+
+{% highlight yaml %}
+
+extensions:
+ commands: [Project\Command\MyCustomCommand]
+
+{% endhighlight %}
+
+If you want to activate the Command globally, because you are using more then one `codeception.yml` file,
+you have to register your command in the `codeception.dist.yml` in the root folder of your project.
+
+Please see the [complete example](https://github.com/Codeception/Codeception/blob/4.0/tests/data/register_command/examples/MyCustomCommand.php)
+
+## Group Objects
+
+Group Objects are extensions listening for the events of tests belonging to a specific group.
+When a test is added to a group:
+
+{% highlight php %}
+
+writeln('inserting additional admin users...');
+
+ $db = $this->getModule('Db');
+ $db->haveInDatabase('users', ['name' => 'bill', 'role' => 'admin']);
+ $db->haveInDatabase('users', ['name' => 'john', 'role' => 'admin']);
+ $db->haveInDatabase('users', ['name' => 'mark', 'role' => 'banned']);
+ }
+
+ public function _after(\Codeception\Event\TestEvent $e)
+ {
+ $this->writeln('cleaning up admin users...');
+ // ...
+ }
+}
+
+{% endhighlight %}
+
+GroupObjects can also be used to update the module configuration before running a test.
+For instance, for `nocleanup` group we prevent Doctrine2 module from wrapping test into transaction:
+
+{% highlight php %}
+
+getModule('Doctrine2')->_reconfigure(['cleanup' => false]);
+ }
+
+{% endhighlight %}
+
+A group class can be created with `php vendor/bin/codecept generate:group groupname` command.
+Group classes will be stored in the `tests/_support/Group` directory.
+
+A group class can be enabled just like you enable an extension class. In the file `codeception.yml`:
+
+{% highlight yaml %}
+
+extensions:
+ enabled: [Group\Admin]
+
+{% endhighlight %}
+
+Now the Admin group class will listen for all events of tests that belong to the `admin` group.
+
+## Step Decorators
+
+Actor classes include generated steps taken from corresponding modules and helpers.
+You can introduce wrappers for those steps by using step decorators.
+
+Step decorators are used to implement conditional assertions.
+When enabled, conditional assertions take all method prefixed by `see` or `dontSee` and introduce new steps prefixed with `canSee` and `cantSee`.
+Contrary to standard assertions those assertions won't stop test on failure. This is done by wrapping action into try/catch blocks.
+
+List of available step decorators:
+
+- [ConditionalAssertion](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Step/ConditionalAssertion.php) - failed assertion will be logged, but test will continue.
+- [TryTo](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Step/TryTo.php) - failed action will be ignored.
+- [Retry](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Step/Retry.php) - failed action will be retried automatically.
+
+Step decorators can be added to suite config inside `steps` block:
+
+{% highlight yaml %}
+yml
+step_decorators:
+ - Codeception/Step/TryTo
+ - Codeception/Step/Retry
+ - Codeception/Step/ConditionalAssertion
+
+{% endhighlight %}
+
+You can introduce your own step decorators. Take a look into sample decorator classes and create your own class which implements `Codeception\Step\GeneratedStep` interface.
+A class should provide `getTemplate` method which returns a code block and variables passed into a template.
+Make your class accessible by autoloader and you can have your own step decorators working.
+
+## Custom Reporters
+
+Alternative reporters can be implemented as extension.
+There are [DotReporter](https://codeception.com/extensions#DotReporter) and [SimpleReporter](https://codeception.com/extensions#SimpleReporter) extensions included.
+Use them to change output or use them as an example to build your own reporter. They can be easily enabled with `--ext` option
+
+{% highlight bash %}
+
+php vendor/bin/codecept run --ext DotReporter
+
+{% endhighlight %}
+
+
+
+If you want to use it as default reporter enable it in `codeception.yml`.
+
+But what if you need to change the output format of the XML or JSON results triggered with the `--xml` or `--json` options?
+Codeception uses PHPUnit printers and overrides them. If you need to customize one of the standard reporters you can override them too.
+If you are thinking on implementing your own reporter you should add a `reporters` section to `codeception.yml`
+and override one of the standard printer classes with one of your own:
+
+{% highlight yaml %}
+
+reporters:
+ xml: Codeception\PHPUnit\Log\JUnit
+ html: Codeception\PHPUnit\ResultPrinter\HTML
+ report: Codeception\PHPUnit\ResultPrinter\Report
+
+{% endhighlight %}
+
+All PHPUnit printers implement the
+[PHPUnit_Framework_TestListener](https://phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener)
+interface. It is recommended to read the code of the original reporter before overriding it.
+
+## Installation Templates
+
+Codeception setup can be customized for the needs of your application.
+If you build a distributable application and you have a personalized configuration you can build an
+Installation template which will help your users to start testing on their projects.
+
+Codeception has built-in installation templates for
+
+* [Acceptance tests](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Template/Acceptance.php)
+* [Unit tests](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Template/Unit.php)
+* [REST API tests](https://github.com/Codeception/Codeception/blob/4.0/src/Codeception/Template/Api.php)
+
+They can be executed with `init` command:
+
+{% highlight bash %}
+
+php vendor/bin/codecept init Acceptance
+
+{% endhighlight %}
+To init tests in specific folder use `--path` option:
+
+{% highlight bash %}
+
+php vendor/bin/codecept init Acceptance --path acceptance_tests
+
+{% endhighlight %}
+
+You will be asked several questions and then config files will be generated and all necessary directories will be created.
+Learn from the examples above to build a custom Installation Template. Here are the basic rules you should follow:
+
+* Templates should be inherited from [`Codeception\InitTemplate`](https://codeception.com/docs/reference/InitTemplate) class and implement `setup` method.
+* Template class should be placed in `Codeception\Template` namespace so Codeception could locate them by class name
+* Use methods like `say`, `saySuccess`, `sayWarning`, `sayError`, `ask`, to interact with a user.
+* Use `createDirectoryFor`, `createEmptyDirectory` methods to create directories
+* Use `createHelper`, `createActor` methods to create helpers and actors.
+* Use [Codeception generators](https://github.com/Codeception/Codeception/tree/4.0/src/Codeception/Lib/Generator) to create other support classes.
+
+
+## One Runner for Multiple Applications
+
+If your project consists of several applications (frontend, admin, api) or you are using the Symfony framework
+with its bundles, you may be interested in having all tests for all applications (bundles) executed in one runner.
+In this case you will get one report that covers the whole project.
+
+Place the `codeception.yml` file into the root folder of your project
+and specify the paths to the other `codeception.yml` configurations that you want to include:
+
+{% highlight yaml %}
+
+include:
+ - frontend/src/*Bundle
+ - admin
+ - api/rest
+paths:
+ output: _output
+settings:
+ colors: false
+
+{% endhighlight %}
+
+You should also specify the path to the `log` directory, where the reports and logs will be saved.
+
+> Wildcards (*) can be used to specify multiple directories at once.
+
+
+## Conclusion
+
+Each feature mentioned above may help dramatically when using Codeception to automate the testing of large projects,
+although some features may require advanced knowledge of PHP. There is no "best practice" or "use cases"
+when we talk about groups, extensions, or other powerful features of Codeception.
+If you see you have a problem that can be solved using these extensions, then give them a try.
+
+
+
+
diff --git a/docs/Data.md b/docs/Data.md
new file mode 100644
index 000000000..3e2a0dedc
--- /dev/null
+++ b/docs/Data.md
@@ -0,0 +1,422 @@
+---
+layout: doc
+title: Data - Codeception Docs
+---
+
+
+# Working with Data
+
+Tests should not affect each other. That's a rule of thumb. When tests interact with a database,
+they may change the data inside it, which would eventually lead to data inconsistency.
+A test may try to insert a record that has already been inserted, or retrieve a deleted record.
+To avoid test failures, the database should be brought back to its initial state before each test.
+Codeception has different methods and approaches to get your data cleaned.
+
+This chapter summarizes all of the notices on clean-ups from the previous chapters
+and suggests the best strategies of how to choose data storage backends.
+
+When we decide to clean up a database, we should make this cleaning as fast as possible. Tests should always run fast.
+Rebuilding the database from scratch is not the best way, but might be the only one. In any case,
+you should use a special test database for testing. **Do not ever run tests on development or production databases!**
+
+## Db
+
+Codeception has a `Db` module, which takes on most of the tasks of database interaction.
+
+{% highlight yaml %}
+
+modules:
+ config:
+ Db:
+ dsn: 'PDO DSN HERE'
+ user: 'root'
+ password:
+
+{% endhighlight %}
+
+
+Use
module parameters
+to set the database credentials from environment variables or from application configuration files.
+
+
+Db module can cleanup database between tests by loading a database dump. This can be done by parsing SQL file and
+executing its commands using current connection
+
+{% highlight yaml %}
+
+modules:
+ config:
+ Db:
+ dsn: 'PDO DSN HERE'
+ user: 'root'
+ password:
+ dump: tests/_data/your-dump-name.sql
+ cleanup: true # reload dump between tests
+ populate: true # load dump before all tests
+
+
+{% endhighlight %}
+
+ Alternatively an external tool (like mysql client, or pg_restore) can be used. This approach is faster and won't produce parsing errors while loading a dump.
+ Use `populator` config option to specify the command. For MySQL it can look like this:
+
+{% highlight yaml %}
+
+ modules:
+ enabled:
+ - Db:
+ dsn: 'mysql:host=localhost;dbname=testdb'
+ user: 'root'
+ password: ''
+ cleanup: true # run populator before each test
+ populate: true # run populator before all test
+ populator: 'mysql -u $user $dbname < tests/_data/dump.sql'
+
+{% endhighlight %}
+
+See the [Db module reference](https://codeception.com/docs/modules/Db#SQL-data-dump) for more examples.
+
+To ensure database dump is loaded before all tests add `populate: true`. To clean current database and reload dump between tests use `cleanup: true`.
+
+
+A full database clean-up can be painfully slow if you use large database dumps. It is recommended to do more data testing
+on the functional and integration levels, this way you can get performance bonuses from using ORM.
+
+
+In acceptance tests, your tests are interacting with the application through a web server. This means that the test
+and the application work with the same database. You should provide the same credentials in the Db module
+that your application uses, then you can access the database for assertions (`seeInDatabase` actions)
+and to perform automatic clean-ups.
+
+The Db module provides actions to create and verify data inside a database.
+
+If you want to create a special database record for one test,
+you can use [`haveInDatabase`](https://codeception.com/docs/modules/Db#haveInDatabase) method of `Db` module:
+
+{% highlight php %}
+
+haveInDatabase('posts', [
+ 'title' => 'Top 10 Testing Frameworks',
+ 'body' => '1. Codeception'
+]);
+$I->amOnPage('/posts');
+$I->see('Top 10 Testing Frameworks');
+
+
+{% endhighlight %}
+
+`haveInDatabase` inserts a row with the provided values into the database.
+All added records will be deleted at the end of the test.
+
+If you want to check that a table record was created
+use [`seeInDatabase`](https://codeception.com/docs/modules/Db#haveInDatabase) method:
+
+{% highlight php %}
+
+amOnPage('/posts/1');
+$I->fillField('comment', 'This is nice!');
+$I->click('Submit');
+$I->seeInDatabase('comments', ['body' => 'This is nice!']);
+
+{% endhighlight %}
+
+See the module [reference](https://codeception.com/docs/modules/Db) for other methods you can use for database testing.
+
+There are also modules for [MongoDb](https://codeception.com/docs/modules/MongoDb),
+[Redis](https://codeception.com/docs/modules/Redis),
+and [Memcache](https://codeception.com/docs/modules/Memcache) which behave in a similar manner.
+
+### Sequence
+
+If the database clean-up takes too long, you can follow a different strategy: create new data for each test.
+This way, the only problem you might face is duplication of data records.
+[Sequence](https://codeception.com/docs/modules/Sequence) was created to solve this.
+It provides the `sq()` function which generates unique suffixes for creating data in tests.
+
+## ORM modules
+
+Your application is most likely using object-relational mapping (ORM) to work with the database. In this case,
+Codeception allows you to use the ORM methods to work with the database, instead of accessing the database directly.
+This way you can work with models and entities of a domain, and not on tables and rows.
+
+By using ORM in functional and integration tests, you can also improve performance of your tests.
+Instead of cleaning up the database after each test, the ORM module will wrap all the database actions into transactions
+and roll it back at the end. This way, no actual data will be written to the database.
+This clean-up strategy is enabled by default,
+you can disable it by setting `cleanup: false` in the configuration of any ORM module.
+
+### ActiveRecord
+
+Popular frameworks like Laravel, Yii, and Phalcon include an ActiveRecord data layer by default.
+Because of this tight integration, you just need to enable the framework module, and use its configuration for database access.
+
+Corresponding framework modules provide similar methods for ORM access:
+
+* `haveRecord`
+* `seeRecord`
+* `dontSeeRecord`
+* `grabRecord`
+
+They allow you to create and check data by model name and field names in the model. Here is the example in Laravel:
+
+{% highlight php %}
+
+haveRecord('posts', ['body' => 'My first blogpost', 'user_id' => 1]);
+$I->amOnPage('/posts/'.$id);
+$I->see('My first blogpost', 'article');
+// check record exists
+$I->seeRecord('posts', ['id' => $id]);
+$I->click('Delete');
+// record was deleted
+$I->dontSeeRecord('posts', ['id' => $id]);
+
+{% endhighlight %}
+
+Laravel5 module provides the method `have` which uses the [factory](https://laravel.com/docs/5.8/database-testing#generating-factories) method to generate models with fake data.
+
+If you want to use ORM for integration testing only, you should enable the framework module with only the `ORM` part enabled:
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Laravel5:
+ - part: ORM
+
+{% endhighlight %}
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Yii2:
+ - part: ORM
+
+{% endhighlight %}
+
+This way no web actions will be added to `$I` object.
+
+If you want to use ORM to work with data inside acceptance tests, you should also include only the ORM part of a module.
+Please note that inside acceptance tests, web applications work inside a webserver, so any test data can't be cleaned up
+by rolling back transactions. You will need to disable cleaning up,
+and use the `Db` module to clean the database up between tests. Here is a sample config:
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - WebDriver:
+ url: http://localhost
+ browser: firefox
+ - Laravel5:
+ cleanup: false
+ - Db
+
+{% endhighlight %}
+
+### Doctrine
+
+Doctrine is also a popular ORM, unlike some others it implements the DataMapper pattern and is not bound to any framework.
+The [Doctrine2](https://codeception.com/docs/modules/Doctrine2) module requires an `EntityManager` instance to work with.
+It can be obtained from a Symfony framework or Zend Framework (configured with Doctrine):
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Symfony
+ - Doctrine2:
+ depends: Symfony
+
+{% endhighlight %}
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - ZF2
+ - Doctrine2:
+ depends: ZF2
+
+{% endhighlight %}
+
+If no framework is used with Doctrine you should provide the `connection_callback` option
+with a valid callback to a function which returns an `EntityManager` instance.
+
+Doctrine2 also provides methods to create and check data:
+
+* `haveInRepository`
+* `grabFromRepository`
+* `grabEntitiesFromRepository`
+* `seeInRepository`
+* `dontSeeInRepository`
+
+### DataFactory
+
+Preparing data for testing is a very creative, although boring, task. If you create a record,
+you need to fill in all the fields of the model. It is much easier to use [Faker](https://github.com/fzaninotto/Faker)
+for this task, which is more effective to set up data generation rules for models.
+Such a set of rules is called *factories*
+and are provided by the [DataFactory](https://codeception.com/docs/modules/DataFactory) module.
+
+Once configured, it can create records with ease:
+
+{% highlight php %}
+
+have('App\Model\User');
+// creates 3 posts
+$I->haveMultiple('App\Model\Post', 3);
+
+{% endhighlight %}
+
+Created records will be deleted at the end of a test.
+The DataFactory module only works with ORM, so it requires one of the ORM modules to be enabled:
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Yii2:
+ configFile: path/to/config.php
+ - DataFactory:
+ depends: Yii2
+
+{% endhighlight %}
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Symfony
+ - Doctrine2:
+ depends: Symfony
+ - DataFactory:
+ depends: Doctrine2
+
+{% endhighlight %}
+
+DataFactory provides a powerful solution for managing data in integration/functional/acceptance tests.
+Read the [full reference](https://codeception.com/docs/modules/DataFactory) to learn how to set this module up.
+
+## Testing Dynamic Data with Snapshots
+
+What if you deal with data which you don't own? For instance, the page look depends on number of categories in database,
+and categories are set by admin user. How would you test that the page is still valid?
+
+There is a way to get it tested as well. Codeception allows you take a snapshot of a data on first run and compare with on next executions.
+This principle is so general that it can work for testing APIs, items on a web page, etc.
+
+Let's check that list of categories on a page is the same it was before.
+Create a snapshot class:
+
+{% highlight php %}
+ vendor/bin/codecept g:snapshot Categories
+
+{% endhighlight %}
+
+Inject an actor class via constructor and implement `fetchData` method which should return a data set from a test.
+
+{% highlight php %}
+
+i = $I;
+ }
+
+ protected function fetchData()
+ {
+ // fetch texts from all 'a.category' elements on a page
+ return $this->i->grabMultiple('a.category');
+ }
+}
+
+{% endhighlight %}
+
+Inside a test you can inject the snapshot class and call `assert` method on it:
+
+{% highlight php %}
+
+amOnPage('/categories');
+ // if previously saved array of users does not match current set, test will fail
+ // to update data in snapshot run test with --debug flag
+ $snapshot->assert();
+}
+
+{% endhighlight %}
+
+On the first run, data will be obtained via `fetchData` method and saved to `tests/_data` directory in json format.
+On next execution the obtained data will be compared with previously saved snapshot.
+
+> To update a snapshot with a new data run tests in `--debug` mode.
+
+By default Snapshot uses `assertEquals` assertion, however this can be customized by overriding `assertData` method.
+
+### Failed assertion output
+
+The assertion performed by `assertData` will not display the typical diff output from `assertEquals` or any customized failed assertion.
+To have the diff displayed when running tests, you can call the snapshot method `shouldShowDiffOnFail`:
+
+{% highlight php %}
+
+amOnPage('/categories');
+ // I want to see the diff in case the snapshot data changes
+ $snapshot->shouldShowDiffOnFail();
+ $snapshot->assert();
+}
+
+{% endhighlight %}
+
+If ever needed, the diff output can also be omitted by calling `shouldShowDiffOnFail(false)`.
+
+### Working with different data formats
+
+By default, all snapshot files are stored in json format, so if you have to work with different formats, neither the diff output or the snapshot file data will be helpful.
+To fix this, you can call the snapshot method `shouldSaveAsJson(false)` and set the file extension by calling `setSnapshotFileExtension()`:
+
+{% highlight php %}
+
+amOnPage('/categories.html');
+ // I want to see the diff in case the snapshot data changes
+ $snapshot->shouldSaveAsJson(false);
+ $snapshot->setSnapshotFileExtension('html');
+ $snapshot->assert();
+}
+
+{% endhighlight %}
+
+The snapshot file will be stored without encoding it to json format, and with the `.html` extension.
+
+> Beware that this option will not perform any changes in the data returned by `fetchData`, and store it as it is.
+
+## Conclusion
+
+Codeception also assists the developer when dealing with data. Tools for database population
+and cleaning up are bundled within the `Db` module. If you use ORM, you can use one of the provided framework modules
+to operate with database through a data abstraction layer, and use the DataFactory module to generate new records with ease.
+
+
+
diff --git a/docs/Debugging.md b/docs/Debugging.md
new file mode 100644
index 000000000..92ea54c56
--- /dev/null
+++ b/docs/Debugging.md
@@ -0,0 +1,73 @@
+---
+layout: doc
+title: Debugging - Codeception Docs
+---
+
+
+# Debugging
+
+Writing a test is always the process of learning the code and the application.
+It is ok, if a test can't be writtng from scratch or you don't understand the effects of the code.
+By looking into the following debugging practices you will learn how to get all required information inside a test to finish it.
+
+## Output
+
+Codeception provides `codecept_debug` function to print a debug output when running test.
+Think of it as `var_dump` but for testing:
+
+{% highlight php %}
+codecept_debug($user);
+{% endhighlight %}
+
+Unlinke var_dump, the output will be printed to screen only if tests are executed with `--debug` flag.
+
+```
+php vendor/bin/codecept run --debug
+```
+
+So it is safe to keep `codecept_debug` inside a test, it won't affect the code running on Continuous Integration server.
+
+`codecept_debug` can be used in any place of your tests, but it is prohibited to use it in application code.
+This function is loaded only by Codeception, so the application may be broken trying to call this line.
+
+Inside a [Helper](/docs/06-ModulesAndHelpers#Helpers) you can use analogs of this function to provide a debug output for a complex action.
+
+
+{% highlight php %}
+// print variable from helper
+$this->debug($response);
+
+// print variable with a short comment
+$this->debugSection('Response', $response);
+{% endhighlight %}
+
+Codeception Modules use debug output to give more information to user about the data used by a test. For instance, in debug mode you can see request and responses body when testing REST API.
+
+
+## Pause
+
+When running acceptance or functional test it might be needed to pause execution at one point to figure out what to do next. For instance, when interacting with a page in a web browser, you might need the execution to be paused to interact with elements on a page, discover proper locators, and next steps for the scenario. That's why Codeception has an interactive pause mode (powered by [PsySH](https://psysh.org)) which can be started by `codecept_pause` function or `$I->pause()`.
+
+Writing a new acceptance from scratch can be more convenient if you hold a browser window open. It is recommended to start writing a new acceptance test with these two commands:
+
+{% highlight php %}
+$I->amOnPage('/');
+$I->pause();
+{% endhighlight %}
+
+Interactive pause is launched only when `--debug ` option is enabled:
+
+```
+php vendor/bin/codecept run --debug
+```
+
+To launch interactive pause in a context when the `$I` object is not available, use `codecept_pause` function instead. To inspect local variables pass them into interactive shell using an array:
+
+{% highlight php %}
+$I->pause(['user' => $user])
+// or
+codecept_pause(['user' => $user]);
+{% endhighlight %}
+
+
+
diff --git a/docs/FunctionalTests.md b/docs/FunctionalTests.md
new file mode 100644
index 000000000..189c54dc8
--- /dev/null
+++ b/docs/FunctionalTests.md
@@ -0,0 +1,277 @@
+---
+layout: doc
+title: Functional Tests - Codeception Docs
+---
+
+
+# Functional Tests
+
+Now that we've written some acceptance tests, functional tests are almost the same, with one major difference:
+Functional tests don't require a web server.
+
+Under the hood, Codeception uses Symfony's [BrowserKit](https://symfony.com/doc/current/components/browser_kit.html)
+to "send" requests to your app. So there's no real HTTP request made, but rather a BrowserKit
+[Request object](https://github.com/symfony/browser-kit/blob/master/Request.php) with the required properties is
+passed to your framework's (front-)controller.
+
+As a first step, you need to enable Codeception's module for your framework in `functional.suite.yml` (see below).
+
+All of Codeception's framework modules share the same interface, and thus your tests are not bound to any one of them.
+This is a sample functional test:
+
+{% highlight php %}
+
+amOnPage('/');
+ $I->click('Login');
+ $I->fillField('Username', 'Miles');
+ $I->fillField('Password', 'Davis');
+ $I->click('Enter');
+ $I->see('Hello, Miles', 'h1');
+ // $I->seeEmailIsSent(); // only for Symfony
+ }
+}
+
+{% endhighlight %}
+
+As you see, the syntax is the same for functional and acceptance tests.
+
+## Limitations
+
+Functional tests are usually much faster than acceptance tests. But functional tests are less stable as they run Codeception
+and the application in one environment. If your application was not designed to run in long lived processes (e.g.
+if you use the `exit` operator or global variables), then functional tests are probably not for you.
+
+### Headers, Cookies, Sessions
+
+One of the common issues with functional tests is the use of PHP functions that deal with headers, sessions and cookies.
+As you may already know, the `header` function triggers an error if it is executed after PHP has already output something.
+In functional tests we run the application multiple times, thus we will get lots of irrelevant errors in the result.
+
+### External URLs
+
+Functional tests cannot access external URLs, just URLs within your project. You can use PhpBrowser to open external URLs.
+
+### Shared Memory
+
+In functional testing, unlike running the application the traditional way, the PHP application does not stop
+after it has finished processing a request. Since all requests are run in one memory container, they are not isolated.
+So **if you see that your tests are mysteriously failing when they shouldn't - try to execute a single test.**
+This will show if the tests were failing because they weren't isolated during the run.
+Keep your memory clean, avoid memory leaks and clean global and static variables.
+
+## Enabling Framework Modules
+
+You have a functional testing suite in the `tests/functional` directory.
+To start, you need to include one of the framework modules in the suite configuration file: `tests/functional.suite.yml`.
+
+### Symfony
+
+To perform Symfony integration you just need to include the Symfony module into your test suite. If you also use Doctrine2,
+don't forget to include it too. To make the Doctrine2 module connect using the `doctrine` service from Symfony,
+you should specify the Symfony module as a dependency for Doctrine2:
+
+{% highlight yaml %}
+
+# functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Symfony
+ - Doctrine2:
+ depends: Symfony # connect to Symfony
+
+{% endhighlight %}
+
+By default this module will search for AppKernel in the `app` directory.
+
+The module uses the Symfony Profiler to provide additional information and assertions.
+
+[See the full reference](https://codeception.com/docs/modules/Symfony)
+
+### Laravel5
+
+The [Laravel5](https://codeception.com/docs/modules/Laravel5) module is included and requires no configuration:
+
+{% highlight yaml %}
+
+# functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Laravel5
+
+{% endhighlight %}
+
+### Yii2
+
+Yii2 tests are included in [Basic](https://github.com/yiisoft/yii2-app-basic)
+and [Advanced](https://github.com/yiisoft/yii2-app-advanced) application templates. Follow the Yii2 guides to start.
+
+### Zend Framework 2
+
+Use [the ZF2 module](https://codeception.com/docs/modules/ZF2) to run functional tests inside Zend Framework 2:
+
+{% highlight yaml %}
+
+# functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - ZF2
+
+{% endhighlight %}
+
+### Zend Expressive
+
+[Zend Expressive](https://codeception.com/docs/modules/ZendExpressive) tests can be executed with enabling a corresponding module.
+
+{% highlight yaml %}
+
+# functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - ZendExpressive
+
+{% endhighlight %}
+
+> See module reference to more configuration options
+
+### Phalcon 4
+
+The `Phalcon4` module requires creating a bootstrap file which returns an instance of `\Phalcon\Mvc\Application`.
+To start writing functional tests with Phalcon support you should enable the `Phalcon4` module
+and provide the path to this bootstrap file:
+
+{% highlight yaml %}
+
+# functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Phalcon4:
+ bootstrap: 'app/config/bootstrap.php'
+ cleanup: true
+ savepoints: true
+
+{% endhighlight %}
+
+[See the full reference](https://codeception.com/docs/modules/Phalcon4)
+
+## Writing Functional Tests
+
+Functional tests are written in the same manner as [Acceptance Tests](https://codeception.com/docs/03-AcceptanceTests)
+with the `PhpBrowser` module enabled. All framework modules and the `PhpBrowser` module share the same methods
+and the same engine.
+
+Therefore we can open a web page with `amOnPage` method:
+
+{% highlight php %}
+
+amOnPage('/login');
+
+{% endhighlight %}
+
+We can click links to open web pages:
+
+{% highlight php %}
+
+click('Logout');
+// click link inside .nav element
+$I->click('Logout', '.nav');
+// click by CSS
+$I->click('a.logout');
+// click with strict locator
+$I->click(['class' => 'logout']);
+
+{% endhighlight %}
+
+We can submit forms as well:
+
+{% highlight php %}
+
+submitForm('form#login', ['name' => 'john', 'password' => '123456']);
+// alternatively
+$I->fillField('#login input[name=name]', 'john');
+$I->fillField('#login input[name=password]', '123456');
+$I->click('Submit', '#login');
+
+{% endhighlight %}
+
+And do assertions:
+
+{% highlight php %}
+
+see('Welcome, john');
+$I->see('Logged in successfully', '.notice');
+$I->seeCurrentUrlEquals('/profile/john');
+
+{% endhighlight %}
+
+Framework modules also contain additional methods to access framework internals. For instance, Laravel5, Phalcon,
+and Yii2 modules have a `seeRecord` method which uses the ActiveRecord layer to check that a record exists in the database.
+
+Take a look at the complete reference for the module you are using. Most of its methods are common to all modules
+but some of them are unique.
+
+You can also access framework globals inside a test or access the dependency injection container
+inside the `Helper\Functional` class:
+
+{% highlight php %}
+
+getModule('Symfony')->grabServiceFromContainer('myservice');
+ $service->doSomething();
+ }
+}
+
+{% endhighlight %}
+
+Also check all available *Public Properties* of the used modules to get full access to their data.
+
+## Error Reporting
+
+By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
+In functional tests you might want to change this level depending on your framework's error policy.
+The error reporting level can be set in the suite configuration file:
+
+{% highlight yaml %}
+
+actor: FunctionalTester
+...
+error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
+
+{% endhighlight %}
+
+`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
+
+## Conclusion
+
+Functional tests are great if you are using powerful frameworks. By using functional tests you can access
+and manipulate their internal state. This makes your tests shorter and faster. In other cases,
+if you don't use frameworks there is no practical reason to write functional tests.
+If you are using a framework other than the ones listed here, create a module for it and share it with the community.
+
+
diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md
new file mode 100644
index 000000000..6c81398a4
--- /dev/null
+++ b/docs/GettingStarted.md
@@ -0,0 +1,368 @@
+---
+layout: doc
+title: Getting Started - Codeception Docs
+---
+
+
+# Getting Started
+
+Let's take a look at Codeception's architecture. We'll assume that you have already [installed](https://codeception.com/install) it
+and bootstrapped your first test suites. Codeception has generated three of them: unit, functional, and acceptance.
+They are well described in the [previous chapter](https://codeception.com/docs/01-Introduction). Inside your __/tests__ folder you will have three `.yml` config files and three directories
+with names corresponding to these suites: `Unit`, `Functional`, `Acceptance`. Suites are independent groups of tests with a common purpose.
+
+## The Codeception Syntax
+
+Codeception follows simple naming rules to make it easy to remember (as well as easy to understand) its method names.
+
+* **Actions** start with a plain english verb, like "click" or "fill". Examples:
+
+```php
+$I->click('Login');
+$I->fillField('#input-username', 'John Dough');
+$I->pressKey('#input-remarks', 'foo');
+```
+
+* **Assertions** always start with "see" or "dontSee". Examples:
+
+```php
+$I->see('Welcome');
+$I->seeInTitle('My Company');
+$I->seeElement('nav');
+$I->dontSeeElement('#error-message');
+$I->dontSeeInPageSource('');
+```
+
+* **Grabbers** take information. The return value of those are meant to be saved as variables and used later. Example:
+
+```php
+$method = $I->grabAttributeFrom('#login-form', 'method');
+$I->assertEquals('post', $method);
+```
+
+
+## Actors
+
+One of the main concepts of Codeception is representation of tests as actions of a person. We have a UnitTester, who executes functions and tests the code. We also have a FunctionalTester, a qualified tester,
+who tests the application as a whole, with knowledge of its internals. Lastly we have an AcceptanceTester, a user who works with our application
+through an interface that we provide.
+
+Methods of actor classes are generally taken from [Codeception Modules](https://codeception.com/docs/06-ModulesAndHelpers). Each module provides predefined actions for different testing purposes, and they can be combined to fit the testing environment.
+Codeception tries to solve 90% of possible testing issues in its modules, so you don't have to reinvent the wheel.
+We think that you can spend more time on writing tests and less on writing support code to make those tests run.
+By default, AcceptanceTester relies on PhpBrowser module, which is set in the `tests/acceptance.suite.yml` configuration file:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost/myapp/
+ - \Helper\Acceptance
+```
+
+
+In this configuration file you can enable/disable and reconfigure modules for your needs.
+When you change the configuration, the actor classes are rebuilt automatically. If the actor classes are not created or updated as you expect,
+try to generate them manually with the `build` command:
+
+```bash
+php vendor/bin/codecept build
+```
+
+
+## Writing a Sample Test
+
+Codeception has its own testing format called Cest (Codecept + Test).
+To start writing a test we need to create a new Cest file. We can do that by running the following command:
+
+```bash
+php vendor/bin/codecept generate:cest Acceptance Signin
+```
+
+
+This will generate `SigninCest.php` file inside `tests/Acceptance` directory. Let's open it:
+
+```php
+amOnPage('/login');
+ $I->fillField('Username','davert');
+ $I->fillField('Password','qwerty');
+ $I->click('Login');
+ $I->see('Hello, davert');
+ }
+}
+```
+
+
+This scenario can probably be read by non-technical people. If you just remove all special chars like braces, arrows and `$`,
+this test transforms into plain English text:
+
+```yaml
+I amOnPage '/login'
+I fillField 'Username','davert'
+I fillField 'Password','qwerty'
+I click 'Login'
+I see 'Hello, davert'
+```
+
+
+Codeception generates this text representation from PHP code by executing:
+
+```bash
+php vendor/bin/codecept generate:scenarios
+```
+
+
+These generated scenarios will be stored in your `_data` directory in text files.
+
+Before we execute this test, we should make sure that the website is running on a local web server.
+Let's open the `tests/acceptance.suite.yml` file and replace the URL with the URL of your web application:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: 'http://myappurl.local'
+ - \Helper\Acceptance
+```
+
+
+After configuring the URL we can run this test with the `run` command:
+
+```bash
+php vendor/bin/codecept run
+```
+
+
+This is the output we should see:
+
+```bash
+Acceptance Tests (1) -------------------------------
+✔ SigninCest: sign in successfully
+----------------------------------------------------
+
+Time: 1 second, Memory: 21.00Mb
+
+OK (1 test, 1 assertions)
+```
+
+
+Let's get some detailed output:
+
+```
+php vendor/bin/codecept run acceptance --steps
+```
+
+
+We should see a step-by-step report on the performed actions:
+
+```bash
+Acceptance Tests (1) -------------------------------
+SigninCest: Login to website
+Signature: SigninCest.php:signInSuccessfully
+Test: tests/acceptance/SigninCest.php:signInSuccessfully
+Scenario --
+ I am on page "/login"
+ I fill field "Username" "davert"
+ I fill field "Password" "qwerty"
+ I click "Login"
+ I see "Hello, davert"
+ OK
+----------------------------------------------------
+
+Time: 0 seconds, Memory: 21.00Mb
+
+OK (1 test, 1 assertions)
+```
+
+
+This simple test can be extended to a complete scenario of site usage, therefore,
+by emulating the user's actions, you can test any of your websites.
+
+To run more tests create a public method for each of them. Include `AcceptanceTester` object as `$I` as a method parameter and use the same `$I->` API you've seen before.
+If your tests share common setup actions put them into `_before` method.
+
+For instance, to test CRUD we want 4 methods to be implemented and all next tests should start at `/task` page:
+
+```php
+amOnPage('/task');
+ }
+
+ function createTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function viewTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function updateTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function deleteTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+}
+```
+
+
+Learn more about the [Cest format](https://codeception.com/docs/07-AdvancedUsage#Cest-Classes) in the Advanced Testing section.
+
+## BDD
+
+Codeception allows execution of user stories in Gherkin format in a similar manner as is done in Cucumber or Behat.
+Please refer to [the BDD chapter](https://codeception.com/docs/07-BDD) to learn more.
+
+## Configuration
+
+Codeception has a global configuration in `codeception.yml` and a config for each suite. We also support `.dist` configuration files.
+If you have several developers in a project, put shared settings into `codeception.dist.yml` and personal settings into `codeception.yml`.
+The same goes for suite configs. For example, the `unit.suite.yml` will be merged with `unit.suite.dist.yml`.
+
+## Running Tests
+
+Tests can be started with the `run` command:
+
+```bash
+php vendor/bin/codecept run
+```
+
+
+With the first argument you can run all tests from one suite:
+
+```bash
+php vendor/bin/codecept run acceptance
+```
+
+
+To limit tests run to a single class, add a second argument. Provide a local path to the test class, from the suite directory:
+
+```bash
+php vendor/bin/codecept run acceptance SigninCest.php
+```
+
+
+Alternatively you can provide the full path to test file:
+
+```bash
+php vendor/bin/codecept run tests/acceptance/SigninCest.php
+```
+
+
+You can further filter which tests are run by appending a method name to the class, separated by a colon (for Cest or Test formats):
+
+```bash
+php vendor/bin/codecept run tests/acceptance/SigninCest.php:^anonymousLogin$
+```
+
+
+You can provide a directory path as well. This will execute all acceptance tests from the `backend` dir:
+
+```bash
+php vendor/bin/codecept run tests/acceptance/backend
+```
+
+
+Using regular expressions, you can even run many different test methods from the same directory or class.
+For example, this will execute all acceptance tests from the `backend` dir beginning with the word "login":
+
+```bash
+php vendor/bin/codecept run tests/acceptance/backend:^login
+```
+
+
+To execute a group of tests that are not stored in the same directory, you can organize them in [groups](https://codeception.com/docs/07-AdvancedUsage#Groups).
+
+### Reports
+
+To generate JUnit XML output, you can provide the `--xml` option, and `--html` for HTML report.
+
+```bash
+php vendor/bin/codecept run --steps --xml --html
+```
+
+
+This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be stored in the `tests/_output/` directory.
+
+Learn more about [available reports](/docs/Reporting).
+
+## Debugging
+
+To receive detailed output, tests can be executed with the `--debug` option.
+
+Learn more about [debugging](/docs/Debugging).
+
+### Generators
+
+There are plenty of useful Codeception commands:
+
+* `generate:cest` *suite* *filename* - Generates a sample Cest test
+* `generate:test` *suite* *filename* - Generates a sample PHPUnit Test with Codeception hooks
+* `generate:feature` *suite* *filename* - Generates Gherkin feature file
+* `generate:suite` *suite* *actor* - Generates a new suite with the given Actor class name
+* `generate:scenarios` *suite* - Generates text files containing scenarios from tests
+* `generate:helper` *filename* - Generates a sample Helper File
+* `generate:pageobject` *suite* *filename* - Generates a sample Page object
+* `generate:stepobject` *suite* *filename* - Generates a sample Step object
+* `generate:environment` *env* - Generates a sample Environment configuration
+* `generate:groupobject` *group* - Generates a sample Group Extension
+
+## Conclusion
+
+We have taken a look into the Codeception structure. Most of the things you need were already generated by the `bootstrap` command.
+After you have reviewed the basic concepts and configurations, you can start writing your first scenario.
+
+
diff --git a/docs/Introduction.md b/docs/Introduction.md
new file mode 100644
index 000000000..52db1708b
--- /dev/null
+++ b/docs/Introduction.md
@@ -0,0 +1,124 @@
+---
+layout: doc
+title: Introduction - Codeception Docs
+---
+
+
+# Introduction
+
+The idea behind testing is not new. You can't sleep well if you are not confident
+that your latest commit didn't take down the entire application.
+Having your application covered with tests gives you more trust in the stability of your application. That's all.
+
+In most cases tests don't guarantee that the application works 100% as it is supposed to.
+You can't predict all possible scenarios and exceptional situations for complex apps,
+but with tests you can cover the most important parts of your app and at least be sure they work as predicted.
+
+There are plenty of ways to test your application.
+The most popular paradigm is [Unit Testing](https://en.wikipedia.org/wiki/Unit_testing).
+For web applications, testing just the controller and/or the model doesn't prove that your application is working.
+To test the behavior of your application as a whole, you should write functional or acceptance tests.
+
+Codeception supports all three testing types.
+Out of the box you have tools for writing unit, functional, and acceptance tests in a unified framework.
+
+| | Unit Tests | Functional Tests | Acceptance Tests
+| --- | --- | --- | --- |
+| Scope of the test | Single PHP class | PHP Framework (Routing, Controllers, etc.) | Page in browser (Chrome, Firefox, or [PhpBrowser](https://codeception.com/docs/03-AcceptanceTests#PhpBrowser)) |
+| Testing computer needs access to project's PHP files | Yes | Yes | No |
+| Webserver required | No | No | Yes |
+| JavaScript | No | No | Yes |
+| Additional software required | None | None | Selenium for browser testing |
+| Speed | Fast | Fast | Slow |
+| Configuration file | `unit.suite.yml` | `functional.suite.yml` | `acceptance.suite.yml` |
+
+One of the main advantages of Codeception is that you don't have to decide on just *one* type of testing. You should have all three!
+And chances are, that you will (sooner or later) need all three. That's why Codeception consists of three so-called "suites":
+A "unit suite" for all unit tests, a "functional suite" for all functional tests, and an "acceptance suite" for all acceptance tests.
+
+Let's review those three testing types in reverse order.
+
+### Acceptance Tests
+
+How does your client, manager, tester, or any other non-technical person know your website is working? By opening the browser, accessing the site, clicking on links, filling in the forms, and actually seeing the content on a web page. They have no idea of the programming language, framework, database, web-server,
+or why the application did (or did not) behave as expected.
+
+This is what acceptance tests are doing. They cover scenarios from a user's perspective.
+With acceptance tests, you can be confident that users, following all the defined scenarios, won't get errors.
+
+> **Any website** can be covered with acceptance tests, even if you use a very exotic CMS or framework.
+
+#### Sample acceptance test
+
+```php
+$I->amOnPage('/');
+$I->click('Sign Up');
+$I->submitForm('#signup', [
+ 'username' => 'MilesDavis',
+ 'email' => 'miles@davis.com'
+]);
+$I->see('Thank you for Signing Up!');
+```
+
+### Functional Tests
+
+What if you could check our application without running it on a server?
+That way you could see detailed exceptions on errors, have our tests run faster, and check the database against predictable and expected results. That's what functional tests are for.
+
+For functional tests, you emulate a web request (`$_GET` and `$_POST` variables) which returns the HTML response. Inside a test, you can make assertions about the response, and you can check if the data was successfully stored in the database.
+
+For functional tests, your application needs to be structured in order to run in a test environment. Codeception provides connectors to all popular PHP frameworks.
+
+#### Sample functional test
+
+```php
+$I->amOnPage('/');
+$I->click('Sign Up');
+$I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']);
+$I->see('Thank you for Signing Up!');
+$I->seeEmailSent('miles@davis.com', 'Thank you for registration');
+$I->seeInDatabase('users', ['email' => 'miles@davis.com']);
+```
+
+> This looks very similar to acceptance tests. The behavior is the same, however, the test is executed inside PHP without launching a browser.
+
+### Unit Tests
+
+Testing pieces of code before coupling them together is highly important as well. This way,
+you can be sure that some deeply hidden feature still works, even if it was not covered by functional or acceptance tests.
+This also shows care in producing stable and testable code.
+
+Codeception is created on top of [PHPUnit](https://www.phpunit.de/). If you have experience writing unit tests with PHPUnit
+you can continue doing so. Codeception has no problem executing standard PHPUnit tests,
+but, additionally, Codeception provides some well-built tools to make your unit tests simpler and cleaner.
+
+Requirements and code can change rapidly,
+and unit tests should be updated every time to fit the requirements.
+The better you understand the testing scenario, the faster you can update it for new behavior.
+
+#### Sample integration test
+
+```php
+public function testSavingUser()
+{
+ $user = new User();
+ $user->setName('Miles');
+ $user->setSurname('Davis');
+ $user->save();
+ $this->assertEquals('Miles Davis', $user->getFullName());
+ $this->tester->seeInDatabase('users', [
+ 'name' => 'Miles',
+ 'surname' => 'Davis'
+ ]);
+}
+```
+
+## Conclusion
+
+The Codeception framework was developed to actually make testing fun.
+It allows writing unit, functional, integration, and acceptance tests in a single, coherent style.
+
+All Codeception tests are written in a descriptive manner.
+Just by looking at the test body, you can clearly understand what is being tested and how it is performed.
+
+
diff --git a/docs/ModulesAndHelpers.md b/docs/ModulesAndHelpers.md
new file mode 100644
index 000000000..147b2e4f6
--- /dev/null
+++ b/docs/ModulesAndHelpers.md
@@ -0,0 +1,616 @@
+---
+layout: doc
+title: Modules And Helpers - Codeception Docs
+---
+
+
+# Modules and Helpers
+
+Codeception uses modularity to create a comfortable testing environment for every test suite you write.
+
+All actions and assertions that can be performed by the Tester object in a class are defined in modules.
+You can extend the testing suite with your own actions and assertions by writing them into a custom module.
+
+Let's look at the following test:
+
+{% highlight php %}
+
+amOnPage('/');
+$I->see('Hello');
+$I->seeInDatabase('users', array('id' => 1));
+$I->seeFileFound('running.lock');
+
+{% endhighlight %}
+
+It can operate with different entities: the web page can be loaded with the PhpBrowser module,
+the database assertion uses the Db module, and file state can be checked with the Filesystem module.
+
+Modules are attached to the Actor classes in the suite configuration.
+For example, in `tests/functional.suite.yml` we should see:
+
+{% highlight yaml %}
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost
+ - Db:
+ dsn: "mysql:host=localhost;dbname=testdb"
+ - Filesystem
+
+{% endhighlight %}
+
+The FunctionalTester class has its methods defined in modules. Actually, it doesn't contain any of them,
+but rather acts as a proxy. It knows which module executes this action and passes parameters into it.
+To make your IDE see all of the FunctionalTester methods, you should run the `codecept build` command.
+It generates method signatures from enabled modules and saves them into a trait which is included in an actor.
+In the current example, the `tests/support/_generated/FunctionalTesterActions.php` file will be generated.
+By default, Codeception automatically rebuilds the Actions trait on each change of the suite configuration.
+
+## Standard Modules
+
+Codeception has many bundled modules which will help you run tests for different purposes and different environments.
+The idea of modules is to share common actions, so that developers and QA engineers can concentrate on testing
+and not on reinventing the wheel. Each module provides methods for testing its own part and
+by combining modules you can get a powerful setup to test an application at all levels.
+
+There is the `WebDriver` module for acceptance testing, modules for all popular PHP frameworks,
+`PHPBrowser` to emulate browser execution, `REST` for testing APIs, and more.
+Modules are considered to be the most valuable part of Codeception.
+They are constantly improving to provide the best testing experience, and be flexible to satisfy everyone's needs.
+
+### Module Conflicts
+
+Modules may conflict with one another. If a module implements `Codeception\Lib\Interfaces\ConflictsWithModule`,
+it might declare a conflict rule to be used with other modules. For instance, WebDriver conflicts
+with all modules implementing the `Codeception\Lib\Interfaces\Web` interface.
+
+{% highlight php %}
+
+public function _conflicts()
+{
+ return 'Codeception\Lib\Interfaces\Web';
+}
+
+{% endhighlight %}
+
+This way if you try to use two modules sharing the same conflicted interface you will get an exception.
+
+To avoid confusion, **Framework modules, PhpBrowser, and WebDriver** can't be used together. For instance,
+the `amOnPage` method exists in all those modules, and you should not try to guess which module will actually execute it.
+If you are doing acceptance testing, set up either WebDriver or PHPBrowser but do not set both up at the same time.
+If you are doing functional testing, enable only one of the framework modules.
+
+In case you need to use a module which depends on a conflicted one, specify it as a dependent module in the configuration.
+You may want to use `WebDriver` with the `REST` module which interacts with a server through `PhpBrowser`.
+In this case your config should look like this:
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - WebDriver:
+ browser: firefox
+ url: http://localhost
+ - REST:
+ url: http://localhost/api/v1
+ depends: PhpBrowser
+
+{% endhighlight %}
+
+This configuration will allow you to send GET/POST requests to the server's APIs while working with a site through a browser.
+
+If you only need some parts of a conflicted module to be loaded, refer to the next section.
+
+### Module Parts
+
+Modules with *Parts* section in their reference can be partially loaded. This way, the `$I` object will have actions
+belonging to only a specific part of that module. Partially loaded modules can be also used to avoid module conflicts.
+
+For instance, the Laravel5 module has an ORM part which contains database actions. You can enable the PhpBrowser module
+for testing and Laravel + ORM for connecting to the database and checking the data.
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost
+ - Laravel5:
+ part: ORM
+
+{% endhighlight %}
+
+The modules won't conflict as actions with the same names won't be loaded.
+
+The REST module has parts for `Xml` and `Json` in the same way. If you are testing a REST service with only JSON responses,
+you can enable just the JSON part of this module:
+
+{% highlight yaml %}
+
+actor: ApiTester
+modules:
+ enabled:
+ - REST:
+ url: http://serviceapp/api/v1/
+ depends: PhpBrowser
+ part: Json
+
+{% endhighlight %}
+
+## Helpers
+
+Codeception doesn't restrict you to only the modules from the main repository.
+Your project might need your own actions added to the test suite. By running the `bootstrap` command,
+Codeception generates three dummy modules for you, one for each of the newly created suites.
+These custom modules are called 'Helpers', and they can be found in the `tests/_support` directory.
+
+{% highlight php %}
+
+
+Public methods prefixed by `_` are treated as hidden and won't be added to your Actor class.
+
+
+Assertions can be a bit tricky. First of all, it's recommended to prefix all your assertion actions with `see` or `dontSee`.
+
+Name your assertions like this:
+
+{% highlight php %}
+
+seePageReloaded();
+$I->seeClassIsLoaded($classname);
+$I->dontSeeUserExist($user);
+
+{% endhighlight %}
+
+And then use them in your tests:
+
+{% highlight php %}
+
+seePageReloaded();
+$I->seeClassIsLoaded('FunctionalTester');
+$I->dontSeeUserExist($user);
+
+{% endhighlight %}
+
+You can define assertions by using assertXXX methods in your modules.
+
+{% highlight php %}
+
+assertTrue(class_exists($class));
+}
+
+{% endhighlight %}
+
+In your helpers you can use these assertions:
+
+{% highlight php %}
+
+assertTrue(isset($thing), "this thing is set");
+ $this->assertFalse(empty($any), "this thing is not empty");
+ $this->assertNotNull($thing, "this thing is not null");
+ $this->assertContains("world", $thing, "this thing contains 'world'");
+ $this->assertNotContains("bye", $thing, "this thing doesn't contain 'bye'");
+ $this->assertEquals("hello world", $thing, "this thing is 'Hello world'!");
+ // ...
+}
+
+{% endhighlight %}
+
+### Accessing Other Modules
+
+It's possible that you will need to access internal data or functions from other modules.
+For example, for your module you might need to access the responses or internal actions of other modules.
+
+Modules can interact with each other through the `getModule` method.
+Please note that this method will throw an exception if the required module was not loaded.
+
+Let's imagine that we are writing a module that reconnects to a database.
+It's supposed to use the dbh connection value from the Db module.
+
+{% highlight php %}
+
+getModule('Db')->dbh;
+ $dbh->close();
+ $dbh->open();
+}
+
+{% endhighlight %}
+
+By using the `getModule` function, you get access to all of the public methods and properties of the requested module.
+The `dbh` property was defined as public specifically to be available to other modules.
+
+Modules may also contain methods that are exposed for use in helper classes. Those methods start with a `_` prefix
+and are not available in Actor classes, so can be accessed only from modules and extensions.
+
+You should use them to write your own actions using module internals.
+
+{% highlight php %}
+
+getModule('WebDriver')->_findElements('#result');
+ $this->assertNotEmpty($elements);
+ $table = reset($elements);
+ $this->assertEquals('table', $table->getTagName());
+ $results = $table->findElements('tr');
+ // asserting that table contains exactly $num rows
+ $this->assertEquals($num, count($results));
+}
+
+{% endhighlight %}
+
+In this example we use the API of the
facebook/php-webdriver library,
+a Selenium WebDriver client the module is build on.
+You can also access the `webDriver` property of a module to get access to the `Facebook\WebDriver\RemoteWebDriver` instance
+for direct Selenium interaction.
+
+### Extending a Module
+
+If accessing modules doesn't provide enough flexibility, you can extend a module inside a Helper class:
+
+{% highlight php %}
+
+pause();
+ }
+}
+
+{% endhighlight %}
+
+### Hooks
+
+Each module can handle events from the running test. A module can be executed before the test starts,
+or after the test is finished. This can be useful for bootstrap/cleanup actions.
+You can also define special behavior for when the test fails. This may help you in debugging the issue.
+For example, the PhpBrowser module saves the current webpage to the `tests/_output` directory when a test fails.
+
+All hooks are defined in [Codeception\Module](https://codeception.com/docs/reference/Module) and are listed here. You are free to redefine them in your module.
+
+{% highlight php %}
+
+debugSection('Request', $params);
+$this->client->request($method, $uri, $params);
+$this->debug('Response Code: ' . $this->client->getStatusCode());
+
+{% endhighlight %}
+
+This test, running with the PhpBrowser module in debug mode, will print something like this:
+
+{% highlight bash %}
+
+I click "All pages"
+* Request (GET) http://localhost/pages {}
+* Response code: 200
+
+{% endhighlight %}
+
+## Configuration
+
+Modules and Helpers can be configured from the suite configuration file, or globally from `codeception.yml`.
+
+Mandatory parameters should be defined in the `$requiredFields` property of the class.
+Here is how it is done in the Db module:
+
+{% highlight php %}
+
+ '127.0.0.1', 'port' => '4444'];
+ // ...
+}
+
+{% endhighlight %}
+
+The host and port parameter can be redefined in the suite configuration.
+Values are set in the `modules:config` section of the configuration file.
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - WebDriver:
+ url: 'http://mysite.com/'
+ browser: 'firefox'
+ - Db:
+ cleanup: false
+ repopulate: false
+
+{% endhighlight %}
+
+Optional and mandatory parameters can be accessed through the `$config` property.
+Use `$this->config['parameter']` to get its value.
+
+### Dynamic Configuration With Parameters
+
+Modules can be dynamically configured from environment variables.
+Parameter storage should be specified in the global `codeception.yml` configuration inside the `params` section.
+Parameters can be loaded from environment vars, from yaml (Symfony format), .env (Laravel format), ini, or php files.
+
+Use the `params` section of the global configuration file `codeception.yml` to specify how to load them.
+You can specify several sources for parameters to be loaded from.
+
+Example: load parameters from the environment:
+
+{% highlight yaml %}
+
+params:
+ - env # load params from environment vars
+
+{% endhighlight %}
+
+Example: load parameters from YAML file (Symfony):
+
+{% highlight yaml %}
+
+params:
+ - app/config/parameters.yml
+
+{% endhighlight %}
+
+Example: load parameters from php file (Yii)
+
+{% highlight yaml %}
+
+params:
+ - config/params.php
+
+{% endhighlight %}
+
+Example: load parameters from .env files (Laravel):
+
+{% highlight yaml %}
+
+params:
+ - .env
+ - .env.testing
+
+{% endhighlight %}
+
+Once loaded, parameter variables can be used as module configuration values.
+Use a variable name wrapped with `%` as a placeholder and it will be replaced by its value.
+
+Let's say we want to specify credentials for a cloud testing service. We have loaded `SAUCE_USER`
+and `SAUCE_KEY` variables from environment, and now we are passing their values into config of `WebDriver`:
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - WebDriver:
+ url: http://mysite.com
+ host: '%SAUCE_USER%:%SAUCE_KEY%@ondemand.saucelabs.com'
+
+{% endhighlight %}
+
+Parameters are also useful to provide connection credentials for the `Db` module (taken from Laravel's .env files):
+
+{% highlight yaml %}
+
+modules:
+ enabled:
+ - Db:
+ dsn: "mysql:host=%DB_HOST%;dbname=%DB_DATABASE%"
+ user: "%DB_USERNAME%"
+ password: "%DB_PASSWORD%"
+
+{% endhighlight %}
+
+### Runtime Configuration
+
+If you want to reconfigure a module at runtime, you need to call a [helper](#Helpers) that uses the `_reconfigure` method of the module.
+
+In this example we change the root URL for PhpBrowser, so that `amOnPage('/')` will open `/admin/`.
+
+{% highlight php %}
+
+getModule('PhpBrowser')->_reconfigure(['url' => 'http://localhost/admin']);
+
+{% endhighlight %}
+
+Usually, these configuration changes are effective immediately. However, in WebDriver configuration changes can't be applied that easily.
+For instance, if you change the browser you need to close the current browser session and start a new one.
+For that, WebDriver module provides a `_restart` method which takes a config array and restarts the browser:
+
+{% highlight php %}
+
+getModule('WebDriver')->_restart(['browser' => 'chrome']);
+// or just restart browser
+$this->getModule('WebDriver')->_restart();
+
+{% endhighlight %}
+
+> You cannot change static test configurations like `depends` at runtime.
+
+At the end of a test all configuration changes will be rolled back to the original configuration values.
+
+### Runtime Configuration of a Test
+
+Sometimes it is needed to set custom configuration for a specific test only.
+For [Cest](https://codeception.com/docs/07-AdvancedUsage#Cest-Classes) and [Test\Unit](https://codeception.com/docs/05-UnitTests)
+formats you can use `@prepare` annotation which can execute the code before other hooks are executed. This allows `@prepare`
+to change the module configuration in runtime. `@prepare` uses [dependency injection](https://codeception.com/docs/07-AdvancedUsage#Dependency-Injection)
+to automatically inject required modules into a method.
+
+To run a specific test only in Chrome browser, you can call `_reconfigure` from WebDriver module for a test itself using `@prepare`.
+
+{% highlight php %}
+
+_reconfigure(['browser' => 'chrome']);
+}
+
+{% endhighlight %}
+
+Prepare methods can invoke all methods of a module, as well as hidden API methods (starting with `_`). Use them to customize the module setup for a specific test.
+
+To change module configuration for a specific group of tests use [GroupObjects](https://codeception.com/docs/08-Customization#Group-Objects).
+
+## Conclusion
+
+Modules are the real power of Codeception. They are used to emulate multiple inheritances for Actor classes
+(UnitTester, FunctionalTester, AcceptanceTester, etc). Codeception provides modules to emulate web requests,
+access data, interact with popular PHP libraries, etc. If the bundled modules are not enough for you that's OK,
+you are free to write your own! Use Helpers (custom modules) for everything that Codeception can't do out of the box.
+Helpers also can be used to extend the functionality of the original modules.
+
+
+
diff --git a/docs/ParallelExecution.md b/docs/ParallelExecution.md
new file mode 100644
index 000000000..5f5ebb359
--- /dev/null
+++ b/docs/ParallelExecution.md
@@ -0,0 +1,292 @@
+---
+layout: doc
+title: Parallel Execution - Codeception Docs
+---
+
+
+# Parallel Execution
+
+When execution time of your tests is longer than a coffee break, it is a good reason to think about making your tests faster. If you have already tried to run them on SSD drive, and the execution time still upsets you, it might be a good idea to run your tests in parallel. However, PHP runs in a single-process and you can't parallelize tests natively similarly to how this works in Java or in NodeJS.
+
+Depending on the project size and requirements you can choose how the best to implement parallel testing for your case.
+In this guide we will overview possible options.
+
+## Sharding
+
+Minimal setup can be implemented by executing several independent CI jobs and running.
+Sharding in Codeception allows to combine stages 1 and 2 so tests could be split by groups on the fly.
+In this case a pipeline could be simplified to one stage with several jobs.
+
+
+
+Each job should have Codeception running a subset of tests set by `--shard` option:
+
+```
+# first job
+./venodor/bin/codecept run --shard 1/3
+
+# second job
+./venodor/bin/codecept run --shard 2/3
+
+# third job
+./venodor/bin/codecept run --shard 3/3
+```
+
+For each job you specify on how many groups tests should be split and the group that should be executed on this agent.
+I.e. `--shard` option takes 2 params: `--shard {currentGroup}/{numberOfGroups}`. So to split tests on 5 machines you need to create 5 jobs with Codeception running these shards: 1/5, 2/5, 3/5, 4/5, 5/5.
+
+Splitting test by shards is done automatically with zero-config. However, in this case you receive as many reports as jobs you have. To aggregate jobs store HTML, XML, and CodeCoverage results as artifacts and add an extra job in the end to merge them. Merging can be done with Robo-paracept toolset described below.
+
+
+To get an aggregated report without an extra stage and without managing artifacts use [Testomat.io](https://testomat.io). This is a SaaS platform that can receive test results from different parallel run and show them in the one interface.
+
+
+
+By running tests with Testomat.io reporter attached results will be sent to a centralized server. By default each execution will create its own report. To store results from different shards in one report set the Run title for them. You can use a common environment variable, like number of a build, to create the unique title which will be the same for all jobs. If build id is stored as $BUILDID variable, execution script for shard #3 can be following:
+
+```
+TESTOMATIO={apiKey} TESTOMATIO_TITLE="Build $BUILDID" ./vendor/bin/codecept run --shard 3/4
+```
+
+
+## Building Pipeline
+
+While sharding provides a simplified setup for testing the complete pipeline schema may look like this.
+
+
+
+* On the first stage, tests should be split into groups. The group file should be committed into the repository or passed to next stage as an artifact.
+* On the second stage tests are executed. XML, HTML, and CodeCoverage reports must be stored as artifacts.
+* On the third stage the results from previous jobs must be collected or aggregated.
+
+
+To get more control on how the jobs are split excuted and results aggregated you can use a task runner.
+
+Codeception provides a toolset for [Robo task runner](https://robo.li) called [robo-paracept](https://github.com/Codeception/robo-paracept) for splitting tests into groups and merging resulting JUnit XML reports.
+
+To sum up, we need to install:
+
+* [Robo](https://robo.li), a task runner.
+* [robo-paracept](https://github.com/Codeception/robo-paracept) - Codeception tasks for parallel execution.
+
+## Using Robo and Robo-paracept
+
+Execute this command in an empty folder to install Robo and Robo-paracept :
+{% highlight bash %}
+
+$ composer require codeception/robo-paracept --dev
+
+{% endhighlight %}
+
+### Setting up Robo
+
+Initializes basic RoboFile in the root of your project
+
+{% highlight bash %}
+robo init
+{% endhighlight %}
+
+Open `RoboFile.php` to edit it
+
+{% highlight php %}
+
+taskSplitTestFilesByGroups(5)
+ ->projectRoot('.')
+ ->testsFrom('tests/acceptance')
+ ->groupsTo('tests/_data/paracept_')
+ ->run();
+
+ /*
+ // Split your tests by single tests (alternatively)
+ $this->taskSplitTestsByGroups(5)
+ ->projectRoot('.')
+ ->testsFrom('tests/acceptance')
+ ->groupsTo('tests/_data/paracept_')
+ ->run();
+ */
+ }
+
+
+{% endhighlight %}
+
+But what if one group of your tests runs for 5 mins and other for 20mins. In this case, you can balance execution time by using [SplitTestsByTime](https://github.com/Codeception/robo-paracept#splittestsbytime) task. It will generate balanced groups taking the execution speed into account.
+
+> More splitting strategies are implemented within [Robo-paracept](https://github.com/Codeception/robo-paracept#tasks) package.
+
+Let's prepare group files:
+
+{% highlight bash %}
+$ robo parallel:split-tests
+
+ [Codeception\Task\SplitTestFilesByGroupsTask] Processing 33 files
+ [Codeception\Task\SplitTestFilesByGroupsTask] Writing tests/_data/paracept_1
+ [Codeception\Task\SplitTestFilesByGroupsTask] Writing tests/_data/paracept_2
+ [Codeception\Task\SplitTestFilesByGroupsTask] Writing tests/_data/paracept_3
+ [Codeception\Task\SplitTestFilesByGroupsTask] Writing tests/_data/paracept_4
+ [Codeception\Task\SplitTestFilesByGroupsTask] Writing tests/_data/paracept_5
+
+{% endhighlight %}
+
+Now we have group files. We should update `codeception.yml` to load generated group files. In our case we have groups: *paracept_1*, *paracept_2*, *paracept_3*, *paracept_4*, *paracept_5*.
+
+{% highlight yaml %}
+
+groups:
+ paracept_*: tests/_data/paracept_*
+
+{% endhighlight %}
+
+Let's try to execute tests from the second group:
+
+{% highlight bash %}
+
+$ php vendor/bin/codecept run acceptance -g paracept_2
+
+{% endhighlight %}
+
+#### Step 2: Running Tests
+
+At this point you should decide if tests are executed on the same job or use multiple jobs for them. We recommend using multiple jobs, as in this case the burden of parallelization goes to CI server. This makes a lot of sense as a single machine has limited resources. If you split tests into CI jobs, you are limited only to the number of agents (build servers) that the CI can provide. For cloud-based services like GitHub Actions, GitLab CI, CircleCI, etc, this number is unlimited.
+
+> Please refer to documentation of your CI platform to learn how to set up multiple jobs runnninng in parallel. Then proceed to merging of results.
+
+In some situations you may want to keep tests running on the same machine and scale it up with more resourses. This makes sense if you have heavy application setup for each test run and setting it up for each machine can waste a lot of resources.
+
+
+To execute tests in multiple processes Robo has `ParallelExec` task to spawn background processes.
+
+{% highlight php %}
+
+taskParallelExec();
+ for ($i = 1; $i <= 5; $i++) {
+ $parallel->process(
+ $this->taskCodecept() // use built-in Codecept task
+ ->suite('acceptance') // run acceptance tests
+ ->group("paracept_$i") // for all paracept_* groups
+ ->xml("tests/_log/result_$i.xml") // save XML results
+ );
+ }
+ return $parallel->run();
+}
+
+{% endhighlight %}
+
+After the `parallelRun` method is defined you can execute tests with
+
+{% highlight bash %}
+
+$ robo parallel:run
+
+{% endhighlight %}
+
+#### Step 3: Merge Results
+
+In case of `parallelExec` task we recommend to save results as JUnit XML, which can be merged and plugged into Continuous Integration server.
+
+{% highlight php %}
+taskMergeXmlReports();
+ for ($i=1; $i<=5; $i++) {
+ $merge->from("tests/_output/result_paracept_$i.xml");
+ }
+ $merge->into("tests/_output/result_paracept.xml")->run();
+ }
+{% endhighlight %}
+Now, we can execute :
+{% highlight bash %}
+
+$ robo parallel:merge-results
+
+{% endhighlight %}
+
+`result_paracept.xml` file will be generated. It can be processed and analyzed.
+
+If you prefer HTML reports, they can be generated in the same way:
+
+{% highlight php %}
+ public function parallelMergeResults()
+ {
+ $merge = $this->taskMergeHtmlReports();
+ for ($i=1; $i<=5; $i++) {
+ $merge->from("tests/_output/result_$i.html");
+ }
+ $merge->into("tests/_output/result.html")->run();
+ }
+
+{% endhighlight %}
+
+
+
+
diff --git a/docs/Reporting.md b/docs/Reporting.md
new file mode 100644
index 000000000..0e8a8cdad
--- /dev/null
+++ b/docs/Reporting.md
@@ -0,0 +1,137 @@
+---
+layout: doc
+title: Reporting - Codeception Docs
+---
+
+
+## Reporting
+
+Clear reports gives a picture of the current state of the system. Which tests are passed, which tests are failed, and if failed what was the reason. Reports may vary on the level of detail and by the technical information collected. Codeception provides as built-in reporters and customizable API to create your own reporter.
+
+## CLI
+
+The standard reporter you already is CLI reporter. It is great for writing and debugging tests as well, as checking the results on CI. On failure, CLI reporter prints a list of all failed tests, if test includes some valuable data like last send requests for REST module, it will also be printed under 'artifacts' section of a test.
+
+
+
+To launch CLI reporter in minimal mode, simply execute tests:
+
+```
+php vendor/bin/codecept run
+```
+
+To see step-by-step execution in a runtime use `--steps` flag:
+
+```
+php vendor/bin/codecept run --steps
+```
+
+To get additional information which may be handful for debugging tests use `--debug` flag.
+This flag is your best friend for writing new tests.
+
+```
+php vendor/bin/codecept run --debug
+```
+
+More CLI options are available:
+
+* Artifacts report can be disabled with `--no-artifacts` option.
+* To explicitly enable ANSI colors use `--colors`, and `--no-colors` to disable them.
+* Use `--silent` to get the minimal possible output
+
+Codeception will exit with exit code 1 if tests are failed.
+This is how CI can mark the job as failed.
+
+## HTML
+
+More information can be presented via HTML report.
+
+
+
+Run tests with `--html` flag to create html report
+
+```
+php vendor/bin/codecept run --html
+```
+
+HTML report is valuable to present for non-tech colleagues. If you create HTML reports on CI you need to store a report as artifact to display it after. Codeception generates a static HTML file so no additional web server is needed to show it.
+
+## Testomat.io
+
+While HTML report can be pretty good for a single test run, more advanced reporting can be enabled by using Testomat.io. Testomat.io is a SaaS service which can store and present reports, and could be used by developers, QAs and managers. It is a complete test management system, which allows you track the history of tests, detect flaky tests, and work on planning new tests.
+
+Testomat.io reports are easy to set up and without storing artifacts on CI system.
+
+
+
+> 😻 Testomat.io is free for small teams, so you can use its reporting features with Codeception.
+
+Testomat.io imports all tests into UI, so your managers, business analysts, and manual QAs can see all your unit, funcitonal, and acceptance tests listed in one place:
+
+
+
+To start, create a new project at Testomat.io and import all your Codeception tests into it. Install testomatio packages for reporting and importing Codeception tests:
+
+```
+composer require testomatio/list-tests --dev
+composer require testomatio/reporter --dev
+```
+
+Obtain API key from a newly created Testomat.io project and import tests:
+
+```
+TESTOMATIO={apiKey} php vendor/bin/list-tests tests
+```
+
+After tests imported you can get a complete report while executing them:
+
+```
+TESTOMATIO={apiKey} php vendor/bin/codecept run --ext "Testomatio\Reporter\Codeception"
+```
+
+Data from test runs will be sent to Testomat.io server and you will see tests statuses are reported in realtime.
+
+Testomat.io not only provides reports for test executions, it also collects historical data for tests, allows attaching tests to Jira issues, and provides useful analytics, and allows planning new tests.
+
+Check an [Example Project](https://github.com/testomatio/examples/tree/master/codeception) to try it.
+
+## Recorder
+
+By default Codeception saves the screenshot for a failed test for acceptance tests and show it in HTML report. However, can't be possible to understand cause of failure just by one screenshot. This is where Recorder extension is handy, it saves a screenshot after each step and shows them in a slideshow.
+
+
+
+Selenium WebDriver doesn't have a simple way to record a video of a test execution, so slideshow is the simplest solution you can use to debug your tests.
+
+To use Recorder enable it as an extension inside config file:
+
+```yml
+extensions:
+ enabled:
+ - Codeception\Extension\Recorder
+```
+More config options are available on [Extension page](https://codeception.com/extensions#Recorder).
+
+## XML
+
+JUnit XML is a reporting standard for testing frameworks. CI platforms like Jenkins can visualize JUnit reports.
+
+```
+php vendor/bin/codecept run --xml
+```
+
+## Allure
+
+
+
+[Allure](https://docs.qameta.io/allure/) is a popular open-source reporting tool. It can be paired with Codeception to get a detailed run report. Use [Allure extension](https://github.com/allure-framework/allure-codeception) to generate report which can be passed to Allure to display it.
+
+## Custom Reporter
+
+Custom reporter can be built as an [Extension](https://codeception.com/docs/08-Customization#Extension). Extension can listen to all test events and log data from them.
+Look into the basic reporting extensions like [DotReporter](https://codeception.com/extensions#DotReporter) or [Logger](https://codeception.com/extensions#Logger) to learn how to build your own.
+
+
+
+
+
diff --git a/docs/ReusingTestCode.md b/docs/ReusingTestCode.md
new file mode 100644
index 000000000..4d4ed1fc5
--- /dev/null
+++ b/docs/ReusingTestCode.md
@@ -0,0 +1,296 @@
+---
+layout: doc
+title: Reusing Test Code - Codeception Docs
+---
+
+
+# Reusing Test Code
+
+Codeception uses modularity to create a comfortable testing environment for every test suite you write.
+Modules allow you to choose the actions and assertions that can be performed in tests.
+
+## What are Actors
+
+All actions and assertions that can be performed by the Actor object in a class are defined in modules.
+It might look like Codeception limits you in testing, but that's not true. You can extend the testing suite
+with your own actions and assertions, by writing them into a custom module, called a Helper.
+We will get back to this later in this chapter, but for now let's look at the following test:
+
+{% highlight php %}
+
+amOnPage('/');
+$I->see('Hello');
+$I->seeInDatabase('users', ['id' => 1]);
+$I->seeFileFound('running.lock');
+
+{% endhighlight %}
+
+It can operate with different entities: the web page can be loaded with the PhpBrowser module,
+the database assertion uses the Db module, and the file state can be checked with the Filesystem module.
+
+Modules are attached to Actor classes in the suite config.
+For example, in `tests/acceptance.suite.yml` we should see:
+
+{% highlight yaml %}
+
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost
+ - Db
+ - Filesystem
+
+{% endhighlight %}
+
+The AcceptanceTester class has its methods defined in modules.
+Let's see what's inside the `AcceptanceTester` class, which is located inside the `tests/_support` directory:
+
+{% highlight php %}
+
+ Use actor classes to set common actions which can be used accross a suite.
+
+
+## PageObjects
+
+For acceptance and functional testing, we will not only need to have common actions being reused across different tests,
+we should have buttons, links and form fields being reused as well. For those cases we need to implement
+the [PageObject pattern](https://www.selenium.dev/documentation/en/guidelines_and_recommendations/page_object_models/),
+which is widely used by test automation engineers. The PageObject pattern represents a web page as a class
+and the DOM elements on that page as its properties, and some basic interactions as its methods.
+PageObjects are very important when you are developing a flexible architecture of your acceptance or functional tests.
+Do not hard-code complex CSS or XPath locators in your tests but rather move them into PageObject classes.
+
+Codeception can generate a PageObject class for you with command:
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:pageobject acceptance Login
+
+{% endhighlight %}
+
+> It is recommended to use page objects for acceptance testing only
+
+This will create a `Login` class in `tests/_support/Page/Acceptance`.
+The basic PageObject is nothing more than an empty class with a few stubs.
+
+It is expected that you will populate it with the UI locators of a page it represents. Locators can be added as public properties:
+
+{% highlight php %}
+
+tester = $I;
+ }
+
+ public function login($name, $password)
+ {
+ $I = $this->tester;
+
+ $I->amOnPage(self::$URL);
+ $I->fillField($this->usernameField, $name);
+ $I->fillField($this->passwordField, $password);
+ $I->click($this->loginButton);
+ }
+}
+
+{% endhighlight %}
+
+If you specify which object you need for a test, Codeception will try to create it using the dependency injection container.
+In the case of a PageObject you should declare a class as a parameter for a test method:
+
+{% highlight php %}
+
+login('bill evans', 'debby');
+ $I->amOnPage('/profile');
+ $I->see('Bill Evans Profile', 'h1');
+ }
+}
+
+{% endhighlight %}
+
+The dependency injection container can construct any object that requires any known class type.
+For instance, `Page\Login` required `AcceptanceTester`, and so it was injected into `Page\Login` constructor,
+and PageObject was created and passed into method arguments. You should explicitly specify
+the types of required objects for Codeception to know what objects should be created for a test.
+Dependency Injection will be described in the next chapter.
+
+## StepObjects
+
+StepObjects are great if you need some common functionality for a group of tests.
+Let's say you are going to test an admin area of a site. You probably won't need the same actions from the admin area
+while testing the front end, so it's a good idea to move these admin-specific tests into their own class.
+We call such a classes StepObjects.
+
+Lets create an Admin StepObject with the generator:
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:stepobject acceptance Admin
+
+{% endhighlight %}
+
+You can supply optional action names. Enter one at a time, followed by a newline.
+End with an empty line to continue to StepObject creation.
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:stepobject acceptance Admin
+Add action to StepObject class (ENTER to exit): loginAsAdmin
+Add action to StepObject class (ENTER to exit):
+StepObject was created in /tests/acceptance/_support/Step/Acceptance/Admin.php
+
+{% endhighlight %}
+
+This will generate a class in `/tests/_support/Step/Acceptance/Admin.php` similar to this:
+
+{% highlight php %}
+
+amOnPage('/admin');
+ $I->fillField('username', 'admin');
+ $I->fillField('password', '123456');
+ $I->click('Login');
+ }
+}
+
+{% endhighlight %}
+
+
+StepObject can be instantiated automatically when used inside the Cest format:
+
+{% highlight php %}
+
+loginAsAdmin();
+ $I->amOnPage('/admin/profile');
+ $I->see('Admin Profile', 'h1');
+ }
+}
+
+{% endhighlight %}
+
+If you have a complex interaction scenario, you may use several step objects in one test.
+If you feel like adding too many actions into your Actor class
+(which is AcceptanceTester in this case) consider moving some of them into separate StepObjects.
+
+> Use StepObjects when you have multiple areas of applications or multiple roles.
+
+
+## Conclusion
+
+There are lots of ways to create reusable and readable tests. Group common actions together
+and move them to an Actor class or StepObjects. Move CSS and XPath locators into PageObjects.
+Write your custom actions and assertions in Helpers.
+Scenario-driven tests should not contain anything more complex than `$I->doSomething` commands.
+Following this approach will allow you to keep your tests clean, readable, stable and make them easy to maintain.
+
+
+
diff --git a/docs/UnitTests.md b/docs/UnitTests.md
new file mode 100644
index 000000000..7cb34457a
--- /dev/null
+++ b/docs/UnitTests.md
@@ -0,0 +1,541 @@
+---
+layout: doc
+title: Unit Tests - Codeception Docs
+---
+
+
+# Unit & Integration Tests
+
+Codeception uses PHPUnit as a backend for running its tests. Thus, any PHPUnit test can be added to a Codeception test suite
+and then executed. If you ever wrote a PHPUnit test then do it just as you did before.
+Codeception adds some nice helpers to simplify common tasks.
+
+## Creating a Test
+
+Create a test using `generate:test` command with a suite and test names as parameters:
+
+{% highlight bash %}
+
+php vendor/bin/codecept generate:test unit Example
+
+{% endhighlight %}
+
+It creates a new `ExampleTest` file located in the `tests/unit` directory.
+
+As always, you can run the newly created test with this command:
+
+{% highlight bash %}
+
+php vendor/bin/codecept run unit ExampleTest
+
+{% endhighlight %}
+
+Or simply run the whole set of unit tests with:
+
+{% highlight bash %}
+
+php vendor/bin/codecept run unit
+
+{% endhighlight %}
+
+A test created by the `generate:test` command will look like this:
+
+{% highlight php %}
+
+setName(null);
+ $this->assertFalse($user->validate(['username']));
+
+ $user->setName('toolooooongnaaaaaaameeee');
+ $this->assertFalse($user->validate(['username']));
+
+ $user->setName('davert');
+ $this->assertTrue($user->validate(['username']));
+ }
+}
+
+{% endhighlight %}
+
+### Assertions
+
+There are pretty many assertions you can use inside tests. The most common are:
+
+* `$this->assertEquals()`
+* `$this->assertContains()`
+* `$this->assertFalse()`
+* `$this->assertTrue()`
+* `$this->assertNull()`
+* `$this->assertEmpty()`
+
+Assertion methods come from PHPUnit. [See the complete reference at phpunit.de](https://phpunit.de/manual/current/en/appendixes.assertions.html).
+
+### Test Doubles
+
+Codeception provides [Codeception\Stub library](https://github.com/Codeception/Stub) for building mocks and stubs for tests.
+Under the hood it used PHPUnit's mock builder but with much simplified API.
+
+Alternatively, [Mockery](https://github.com/Codeception/MockeryModule) can be used inside Codeception.
+
+#### Stubs
+
+Stubs can be created with a static methods of `Codeception\Stub`.
+
+{% highlight php %}
+
+ 'john']);
+$name = $user->getName(); // 'john'
+
+{% endhighlight %}
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+Inside unit tests (`Codeception\Test\Unit`) it is recommended to use alternative API:
+
+{% highlight php %}
+
+make(UserRepository::class, ['find' => new User]);
+$userRepository->find(1); // => User
+
+// create a dummy
+$userRepository = $this->makeEmpty(UserRepository::class);
+
+// create a stub with all methods replaced except one
+$user = $this->makeEmptyExcept(User::class, 'validate');
+$user->validate($data);
+
+// create a stub by calling constructor and replacing a method
+$user = $this->construct(User::class, ['name' => 'davert'], ['save' => false]);
+
+// create a stub by calling constructor with empty methods
+$user = $this->constructEmpty(User::class, ['name' => 'davert']);
+
+// create a stub by calling constructor with empty methods
+$user = $this->constructEmptyExcept(User::class, 'getName', ['name' => 'davert']);
+$user->getName(); // => davert
+$user->setName('jane'); // => this method is empty
+
+{% endhighlight %}
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+Stubs can also be created using static methods from `Codeception\Stub` class.
+In this
+
+{% highlight php %}
+
+ new User]);
+
+{% endhighlight %}
+
+See a reference for [static Stub API](https://codeception.com/docs/reference/Stub)
+
+#### Mocks
+
+To declare expectations for mocks use `Codeception\Stub\Expected` class:
+
+{% highlight php %}
+
+getName() should never be called
+$user = $this->make('User', [
+ 'getName' => Expected::never(),
+ 'someMethod' => function() {}
+]);
+$user->someMethod();
+
+// create a mock where $user->getName() should be called at least once
+$user = $this->make('User', [
+ 'getName' => Expected::atLeastOnce('Davert')
+ ]
+);
+$user->getName();
+$userName = $user->getName();
+$this->assertEquals('Davert', $userName);
+
+{% endhighlight %}
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+## Integration Tests
+
+Unlike unit tests integration tests doesn't require the code to be executed in isolation.
+That allows us to use database and other components inside a tests.
+To improve the testing experience modules can be used as in functional testing.
+
+### Using Modules
+
+As in scenario-driven functional or acceptance tests you can access Actor class methods.
+If you write integration tests, it may be useful to include the `Db` module for database testing.
+
+{% highlight yaml %}
+
+# Codeception Test Suite Configuration
+
+# suite for unit (internal) tests.
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Db
+ - \Helper\Unit
+
+{% endhighlight %}
+
+To access UnitTester methods you can use the `UnitTester` property in a test.
+
+### Testing Database
+
+Let's see how you can do some database testing:
+
+{% highlight php %}
+
+setName('Miles');
+ $user->setSurname('Davis');
+ $user->save();
+ $this->assertEquals('Miles Davis', $user->getFullName());
+ $this->tester->seeInDatabase('users', ['name' => 'Miles', 'surname' => 'Davis']);
+}
+
+{% endhighlight %}
+
+To enable the database functionality in unit tests, make sure the `Db` module is included
+in the `unit.suite.yml` configuration file.
+The database will be cleaned and populated after each test, the same way it happens for acceptance and functional tests.
+If that's not your required behavior, change the settings of the `Db` module for the current suite. See [Db Module](https://codeception.com/docs/modules/Db)
+
+### Interacting with the Framework
+
+You should probably not access your database directly if your project already uses ORM for database interactions.
+Why not use ORM directly inside your tests? Let's try to write a test using Laravel's ORM Eloquent.
+For this we need to configure the Laravel5 module. We won't need its web interaction methods like `amOnPage` or `see`,
+so let's enable only the ORM part of it:
+
+{% highlight yaml %}
+
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Laravel5:
+ part: ORM
+ - \Helper\Unit
+
+{% endhighlight %}
+
+We included the Laravel5 module the same way we did for functional testing.
+Let's see how we can use it for integration tests:
+
+{% highlight php %}
+
+tester->haveRecord('users', ['name' => 'miles']);
+ // access model
+ $user = User::find($id);
+ $user->setName('bill');
+ $user->save();
+ $this->assertEquals('bill', $user->getName());
+ // verify data was saved using framework methods
+ $this->tester->seeRecord('users', ['name' => 'bill']);
+ $this->tester->dontSeeRecord('users', ['name' => 'miles']);
+}
+
+{% endhighlight %}
+
+A very similar approach can be used for all frameworks that have an ORM implementing the ActiveRecord pattern.
+In Yii2 and Phalcon, the methods `haveRecord`, `seeRecord`, `dontSeeRecord` work in the same way.
+They also should be included by specifying `part: ORM` in order to not use the functional testing actions.
+
+If you are using Symfony with Doctrine, you don't need to enable Symfony itself but just Doctrine2:
+
+{% highlight yaml %}
+
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Doctrine2:
+ depends: Symfony
+ - \Helper\Unit
+
+{% endhighlight %}
+
+In this case you can use the methods from the Doctrine2 module, while Doctrine itself uses the Symfony module
+to establish connections to the database. In this case a test might look like:
+
+{% highlight php %}
+
+tester->haveInRepository(User::class, ['name' => 'miles']);
+ // get entity manager by accessing module
+ $em = $this->getModule('Doctrine2')->em;
+ // get real user
+ $user = $em->find(User::class, $id);
+ $user->setName('bill');
+ $em->persist($user);
+ $em->flush();
+ $this->assertEquals('bill', $user->getName());
+ // verify data was saved using framework methods
+ $this->tester->seeInRepository(User::class, ['name' => 'bill']);
+ $this->tester->dontSeeInRepository(User::class, ['name' => 'miles']);
+}
+
+{% endhighlight %}
+
+In both examples you should not be worried about the data persistence between tests.
+The Doctrine2 and Laravel5 modules will clean up the created data at the end of a test.
+This is done by wrapping each test in a transaction and rolling it back afterwards.
+
+### Accessing Module
+
+Codeception allows you to access the properties and methods of all modules defined for this suite.
+Unlike using the UnitTester class for this purpose, using a module directly grants you access
+to all public properties of that module.
+
+We have already demonstrated this in a previous example where we accessed the Entity Manager from a Doctrine2 module:
+
+{% highlight php %}
+
+getModule('Doctrine2')->em;
+
+{% endhighlight %}
+
+If you use the `Symfony` module, here is how you can access the Symfony container:
+
+{% highlight php %}
+
+getModule('Symfony')->container;
+
+{% endhighlight %}
+
+The same can be done for all public properties of an enabled module. Accessible properties are listed in the module reference.
+
+### Scenario Driven Testing
+
+[Cest format](https://codeception.com/docs/07-AdvancedUsage#Cest-Classes) can also be used for integration testing.
+In some cases it makes tests cleaner as it simplifies module access by using common `$I->` syntax:
+
+{% highlight php %}
+
+have(Build::class, ['project_id' => $this->project->id]);
+ $I->assertEquals(1, $build->sequence);
+ $build = $I->have(Build::class, ['project_id' => $this->project->id]);
+ $I->assertEquals(2, $build->sequence);
+ $this->project->refresh();
+ $I->assertEquals(3, $this->project->build_sequence);
+}
+
+{% endhighlight %}
+This format can be recommended for testing domain and database interactions.
+
+In Cest format you don't have native support for test doubles so it's recommended
+to include a trait `\Codeception\Test\Feature\Stub` to enable mocks inside a test.
+Alternatively, install and enable [Mockery module](https://github.com/Codeception/MockeryModule).
+
+## Advanced Tools
+
+### Specify
+
+When writing tests you should prepare them for constant changes in your application.
+Tests should be easy to read and maintain. If a specification of your application is changed,
+your tests should be updated as well. If you don't have a convention inside your team for documenting tests,
+you will have issues figuring out what tests will be affected by the introduction of a new feature.
+
+That's why it's pretty important not just to cover your application with unit tests, but make unit tests self-explanatory.
+We do this for scenario-driven acceptance and functional tests, and we should do this for unit and integration tests as well.
+
+For this case we have a stand-alone project [Specify](https://github.com/Codeception/Specify)
+(which is included in the phar package) for writing specifications inside unit tests:
+
+{% highlight php %}
+
+user = User::create();
+
+ $this->specify("username is required", function() {
+ $this->user->username = null;
+ $this->assertFalse($this->user->validate(['username']));
+ });
+
+ $this->specify("username is too long", function() {
+ $this->user->username = 'toolooooongnaaaaaaameeee';
+ $this->assertFalse($this->user->validate(['username']));
+ });
+
+ $this->specify("username is ok", function() {
+ $this->user->username = 'davert';
+ $this->assertTrue($this->user->validate(['username']));
+ });
+ }
+}
+
+{% endhighlight %}
+
+By using `specify` codeblocks, you can describe any piece of a test.
+This makes tests much cleaner and comprehensible for everyone in your team.
+
+Code inside `specify` blocks is isolated. In the example above, any changes to `$this->user`
+will not be reflected in other code blocks as it is marked with `@specify` annotation.
+
+Also, you may add [Codeception\Verify](https://github.com/Codeception/Verify) for BDD-style assertions.
+This tiny library adds more readable assertions, which is quite nice, if you are always confused
+about which argument in `assert` calls is expected and which one is actual:
+
+{% highlight php %}
+
+getName())->equals('john');
+
+{% endhighlight %}
+
+### Domain Assertions
+
+The more complicated your domain is the more explicit your tests should be. With [DomainAssert](https://github.com/Codeception/DomainAssert)
+library you can easily create custom assertion methods for unit and integration tests.
+
+It allows to reuse business rules inside assertion methods:
+
+{% highlight php %}
+
+assertUserIsValid($user);
+$this->assertUserIsAdmin($user);
+
+// use combined explicit assertion
+// to tell what you expect to check
+$this->assertUserCanPostToBlog($user, $blog);
+// instead of just calling a bunch of assertions
+$this->assertNotNull($user);
+$this->assertNotNull($blog);
+$this->assertContain($user, $blog->getOwners());
+
+{% endhighlight %}
+
+With custom assertion methods you can improve readability of your tests and keep them focused around the specification.
+
+### AspectMock
+
+[AspectMock](https://github.com/Codeception/AspectMock) is an advanced mocking framework which allows you to replace any methods of any class in a test.
+Static methods, class methods, date and time functions can be easily replaced with AspectMock.
+For instance, you can test singletons!
+
+{% highlight php %}
+
+assertInstanceOf('MySingleton', $class);
+ test::double('MySingleton', ['getInstance' => new DOMDocument]);
+ $this->assertInstanceOf('DOMDocument', $class);
+}
+
+{% endhighlight %}
+
+* [AspectMock on GitHub](https://github.com/Codeception/AspectMock)
+* [AspectMock in Action](https://codeception.com/07-31-2013/nothing-is-untestable-aspect-mock.html)
+* [How it Works](https://codeception.com/09-13-2013/understanding-aspectmock.html)
+
+## Error Reporting
+
+By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
+In unit tests you might want to change this level depending on your framework's error policy.
+The error reporting level can be set in the suite configuration file:
+
+{% highlight yaml %}
+
+actor: UnitTester
+...
+error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
+
+{% endhighlight %}
+
+`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
+
+## Conclusion
+
+PHPUnit tests are first-class citizens in test suites. Whenever you need to write and execute unit tests,
+you don't need to install PHPUnit separately, but use Codeception directly to execute them.
+Some nice features can be added to common unit tests by integrating Codeception modules.
+For most unit and integration testing, PHPUnit tests are enough. They run fast, and are easy to maintain.
+
+
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index d60a35ddf..000000000
--- a/docs/index.html
+++ /dev/null
@@ -1,8 +0,0 @@
----
-layout: doc
-title: Codeception Documentation
----
-
-
Codeception Documentation Guides
-
-
IntroductionGetting StartedAcceptance TestsFunctional TestsUnit TestsModules And HelpersReusing Test CodeAdvanced UsageBDDCustomizationDataAPI TestingCodecoverageContinuous IntegrationParallel Execution
\ No newline at end of file
diff --git a/docs/reference/ShellAutocomplete.md b/docs/reference/ShellAutocomplete.md
new file mode 100644
index 000000000..e3900353f
--- /dev/null
+++ b/docs/reference/ShellAutocomplete.md
@@ -0,0 +1,26 @@
+## Shell auto-completion
+
+For bash and zsh shells, you can use auto-completion for your Codeception projects by executing the following in your shell (or add it to your .bashrc/.zshrc):
+
+```
+# BASH ~4.x, ZSH
+source <([codecept location] _completion --generate-hook --program codecept --use-vendor-bin)
+# BASH ~3.x, ZSH
+[codecept location] _completion --generate-hook --program codecept --use-vendor-bin | source /dev/stdin
+
+# BASH (any version)
+eval $([codecept location] _completion --generate-hook --program codecept --use-vendor-bin)
+
+```
+
+By using the above code in your shell, Codeception will try to autocomplete the following:
+
+* Commands
+* Suites
+* Test paths
+
+Usage of `-use-vendor-bin` is optional. This option will work for most Codeception projects, where Codeception is located in your `vendor/bin` folder.
+But in case you are using a global Codeception installation for example, you wouldn't use this option.
+
+Note that with the `-use-vendor-bin` option, your commands will be completed using the Codeception binary located in your project's root.
+Without the option, it will use whatever Codeception binary you originally used to generate the completion script ('codecept location' in the above examples)
diff --git a/guides/01-Introduction.md b/guides/01-Introduction.md
new file mode 100644
index 000000000..b9b8bf10e
--- /dev/null
+++ b/guides/01-Introduction.md
@@ -0,0 +1,116 @@
+# Introduction
+
+The idea behind testing is not new. You can't sleep well if you are not confident
+that your latest commit didn't take down the entire application.
+Having your application covered with tests gives you more trust in the stability of your application. That's all.
+
+In most cases tests don't guarantee that the application works 100% as it is supposed to.
+You can't predict all possible scenarios and exceptional situations for complex apps,
+but with tests you can cover the most important parts of your app and at least be sure they work as predicted.
+
+There are plenty of ways to test your application.
+The most popular paradigm is [Unit Testing](https://en.wikipedia.org/wiki/Unit_testing).
+For web applications, testing just the controller and/or the model doesn't prove that your application is working.
+To test the behavior of your application as a whole, you should write functional or acceptance tests.
+
+Codeception supports all three testing types.
+Out of the box you have tools for writing unit, functional, and acceptance tests in a unified framework.
+
+| | Unit Tests | Functional Tests | Acceptance Tests
+| --- | --- | --- | --- |
+| Scope of the test | Single PHP class | PHP Framework (Routing, Controllers, etc.) | Page in browser (Chrome, Firefox, or [PhpBrowser](https://codeception.com/docs/03-AcceptanceTests#PhpBrowser)) |
+| Testing computer needs access to project's PHP files | Yes | Yes | No |
+| Webserver required | No | No | Yes |
+| JavaScript | No | No | Yes |
+| Additional software required | None | None | Selenium for browser testing |
+| Speed | Fast | Fast | Slow |
+| Configuration file | `unit.suite.yml` | `functional.suite.yml` | `acceptance.suite.yml` |
+
+One of the main advantages of Codeception is that you don't have to decide on just *one* type of testing. You should have all three!
+And chances are, that you will (sooner or later) need all three. That's why Codeception consists of three so-called "suites":
+A "unit suite" for all unit tests, a "functional suite" for all functional tests, and an "acceptance suite" for all acceptance tests.
+
+Let's review those three testing types in reverse order.
+
+### Acceptance Tests
+
+How does your client, manager, tester, or any other non-technical person know your website is working? By opening the browser, accessing the site, clicking on links, filling in the forms, and actually seeing the content on a web page. They have no idea of the programming language, framework, database, web-server,
+or why the application did (or did not) behave as expected.
+
+This is what acceptance tests are doing. They cover scenarios from a user's perspective.
+With acceptance tests, you can be confident that users, following all the defined scenarios, won't get errors.
+
+> **Any website** can be covered with acceptance tests, even if you use a very exotic CMS or framework.
+
+#### Sample acceptance test
+
+```php
+$I->amOnPage('/');
+$I->click('Sign Up');
+$I->submitForm('#signup', [
+ 'username' => 'MilesDavis',
+ 'email' => 'miles@davis.com'
+]);
+$I->see('Thank you for Signing Up!');
+```
+
+### Functional Tests
+
+What if you could check our application without running it on a server?
+That way you could see detailed exceptions on errors, have our tests run faster, and check the database against predictable and expected results. That's what functional tests are for.
+
+For functional tests, you emulate a web request (`$_GET` and `$_POST` variables) which returns the HTML response. Inside a test, you can make assertions about the response, and you can check if the data was successfully stored in the database.
+
+For functional tests, your application needs to be structured in order to run in a test environment. Codeception provides connectors to all popular PHP frameworks.
+
+#### Sample functional test
+
+```php
+$I->amOnPage('/');
+$I->click('Sign Up');
+$I->submitForm('#signup', ['username' => 'MilesDavis', 'email' => 'miles@davis.com']);
+$I->see('Thank you for Signing Up!');
+$I->seeEmailSent('miles@davis.com', 'Thank you for registration');
+$I->seeInDatabase('users', ['email' => 'miles@davis.com']);
+```
+
+> This looks very similar to acceptance tests. The behavior is the same, however, the test is executed inside PHP without launching a browser.
+
+### Unit Tests
+
+Testing pieces of code before coupling them together is highly important as well. This way,
+you can be sure that some deeply hidden feature still works, even if it was not covered by functional or acceptance tests.
+This also shows care in producing stable and testable code.
+
+Codeception is created on top of [PHPUnit](https://www.phpunit.de/). If you have experience writing unit tests with PHPUnit
+you can continue doing so. Codeception has no problem executing standard PHPUnit tests,
+but, additionally, Codeception provides some well-built tools to make your unit tests simpler and cleaner.
+
+Requirements and code can change rapidly,
+and unit tests should be updated every time to fit the requirements.
+The better you understand the testing scenario, the faster you can update it for new behavior.
+
+#### Sample integration test
+
+```php
+public function testSavingUser()
+{
+ $user = new User();
+ $user->setName('Miles');
+ $user->setSurname('Davis');
+ $user->save();
+ $this->assertEquals('Miles Davis', $user->getFullName());
+ $this->tester->seeInDatabase('users', [
+ 'name' => 'Miles',
+ 'surname' => 'Davis'
+ ]);
+}
+```
+
+## Conclusion
+
+The Codeception framework was developed to actually make testing fun.
+It allows writing unit, functional, integration, and acceptance tests in a single, coherent style.
+
+All Codeception tests are written in a descriptive manner.
+Just by looking at the test body, you can clearly understand what is being tested and how it is performed.
diff --git a/guides/02-GettingStarted.md b/guides/02-GettingStarted.md
new file mode 100644
index 000000000..4bc60f02f
--- /dev/null
+++ b/guides/02-GettingStarted.md
@@ -0,0 +1,360 @@
+# Getting Started
+
+Let's take a look at Codeception's architecture. We'll assume that you have already [installed](https://codeception.com/install) it
+and bootstrapped your first test suites. Codeception has generated three of them: unit, functional, and acceptance.
+They are well described in the [previous chapter](https://codeception.com/docs/01-Introduction). Inside your __/tests__ folder you will have three `.yml` config files and three directories
+with names corresponding to these suites: `Unit`, `Functional`, `Acceptance`. Suites are independent groups of tests with a common purpose.
+
+## The Codeception Syntax
+
+Codeception follows simple naming rules to make it easy to remember (as well as easy to understand) its method names.
+
+* **Actions** start with a plain english verb, like "click" or "fill". Examples:
+
+```php
+$I->click('Login');
+$I->fillField('#input-username', 'John Dough');
+$I->pressKey('#input-remarks', 'foo');
+```
+
+* **Assertions** always start with "see" or "dontSee". Examples:
+
+```php
+$I->see('Welcome');
+$I->seeInTitle('My Company');
+$I->seeElement('nav');
+$I->dontSeeElement('#error-message');
+$I->dontSeeInPageSource('
');
+```
+
+* **Grabbers** take information. The return value of those are meant to be saved as variables and used later. Example:
+
+```php
+$method = $I->grabAttributeFrom('#login-form', 'method');
+$I->assertEquals('post', $method);
+```
+
+
+## Actors
+
+One of the main concepts of Codeception is representation of tests as actions of a person. We have a UnitTester, who executes functions and tests the code. We also have a FunctionalTester, a qualified tester,
+who tests the application as a whole, with knowledge of its internals. Lastly we have an AcceptanceTester, a user who works with our application
+through an interface that we provide.
+
+Methods of actor classes are generally taken from [Codeception Modules](https://codeception.com/docs/06-ModulesAndHelpers). Each module provides predefined actions for different testing purposes, and they can be combined to fit the testing environment.
+Codeception tries to solve 90% of possible testing issues in its modules, so you don't have to reinvent the wheel.
+We think that you can spend more time on writing tests and less on writing support code to make those tests run.
+By default, AcceptanceTester relies on PhpBrowser module, which is set in the `tests/acceptance.suite.yml` configuration file:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost/myapp/
+ - \Helper\Acceptance
+```
+
+
+In this configuration file you can enable/disable and reconfigure modules for your needs.
+When you change the configuration, the actor classes are rebuilt automatically. If the actor classes are not created or updated as you expect,
+try to generate them manually with the `build` command:
+
+```bash
+php vendor/bin/codecept build
+```
+
+
+## Writing a Sample Test
+
+Codeception has its own testing format called Cest (Codecept + Test).
+To start writing a test we need to create a new Cest file. We can do that by running the following command:
+
+```bash
+php vendor/bin/codecept generate:cest Acceptance Signin
+```
+
+
+This will generate `SigninCest.php` file inside `tests/Acceptance` directory. Let's open it:
+
+```php
+amOnPage('/login');
+ $I->fillField('Username','davert');
+ $I->fillField('Password','qwerty');
+ $I->click('Login');
+ $I->see('Hello, davert');
+ }
+}
+```
+
+
+This scenario can probably be read by non-technical people. If you just remove all special chars like braces, arrows and `$`,
+this test transforms into plain English text:
+
+```yaml
+I amOnPage '/login'
+I fillField 'Username','davert'
+I fillField 'Password','qwerty'
+I click 'Login'
+I see 'Hello, davert'
+```
+
+
+Codeception generates this text representation from PHP code by executing:
+
+```bash
+php vendor/bin/codecept generate:scenarios
+```
+
+
+These generated scenarios will be stored in your `_data` directory in text files.
+
+Before we execute this test, we should make sure that the website is running on a local web server.
+Let's open the `tests/acceptance.suite.yml` file and replace the URL with the URL of your web application:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: 'http://myappurl.local'
+ - \Helper\Acceptance
+```
+
+
+After configuring the URL we can run this test with the `run` command:
+
+```bash
+php vendor/bin/codecept run
+```
+
+
+This is the output we should see:
+
+```bash
+Acceptance Tests (1) -------------------------------
+✔ SigninCest: sign in successfully
+----------------------------------------------------
+
+Time: 1 second, Memory: 21.00Mb
+
+OK (1 test, 1 assertions)
+```
+
+
+Let's get some detailed output:
+
+```
+php vendor/bin/codecept run acceptance --steps
+```
+
+
+We should see a step-by-step report on the performed actions:
+
+```bash
+Acceptance Tests (1) -------------------------------
+SigninCest: Login to website
+Signature: SigninCest.php:signInSuccessfully
+Test: tests/acceptance/SigninCest.php:signInSuccessfully
+Scenario --
+ I am on page "/login"
+ I fill field "Username" "davert"
+ I fill field "Password" "qwerty"
+ I click "Login"
+ I see "Hello, davert"
+ OK
+----------------------------------------------------
+
+Time: 0 seconds, Memory: 21.00Mb
+
+OK (1 test, 1 assertions)
+```
+
+
+This simple test can be extended to a complete scenario of site usage, therefore,
+by emulating the user's actions, you can test any of your websites.
+
+To run more tests create a public method for each of them. Include `AcceptanceTester` object as `$I` as a method parameter and use the same `$I->` API you've seen before.
+If your tests share common setup actions put them into `_before` method.
+
+For instance, to test CRUD we want 4 methods to be implemented and all next tests should start at `/task` page:
+
+```php
+amOnPage('/task');
+ }
+
+ function createTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function viewTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function updateTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+
+ function deleteTask(AcceptanceTester $I)
+ {
+ // todo: write test
+ }
+}
+```
+
+
+Learn more about the [Cest format](https://codeception.com/docs/07-AdvancedUsage#Cest-Classes) in the Advanced Testing section.
+
+## BDD
+
+Codeception allows execution of user stories in Gherkin format in a similar manner as is done in Cucumber or Behat.
+Please refer to [the BDD chapter](https://codeception.com/docs/07-BDD) to learn more.
+
+## Configuration
+
+Codeception has a global configuration in `codeception.yml` and a config for each suite. We also support `.dist` configuration files.
+If you have several developers in a project, put shared settings into `codeception.dist.yml` and personal settings into `codeception.yml`.
+The same goes for suite configs. For example, the `unit.suite.yml` will be merged with `unit.suite.dist.yml`.
+
+## Running Tests
+
+Tests can be started with the `run` command:
+
+```bash
+php vendor/bin/codecept run
+```
+
+
+With the first argument you can run all tests from one suite:
+
+```bash
+php vendor/bin/codecept run acceptance
+```
+
+
+To limit tests run to a single class, add a second argument. Provide a local path to the test class, from the suite directory:
+
+```bash
+php vendor/bin/codecept run acceptance SigninCest.php
+```
+
+
+Alternatively you can provide the full path to test file:
+
+```bash
+php vendor/bin/codecept run tests/acceptance/SigninCest.php
+```
+
+
+You can further filter which tests are run by appending a method name to the class, separated by a colon (for Cest or Test formats):
+
+```bash
+php vendor/bin/codecept run tests/acceptance/SigninCest.php:^anonymousLogin$
+```
+
+
+You can provide a directory path as well. This will execute all acceptance tests from the `backend` dir:
+
+```bash
+php vendor/bin/codecept run tests/acceptance/backend
+```
+
+
+Using regular expressions, you can even run many different test methods from the same directory or class.
+For example, this will execute all acceptance tests from the `backend` dir beginning with the word "login":
+
+```bash
+php vendor/bin/codecept run tests/acceptance/backend:^login
+```
+
+
+To execute a group of tests that are not stored in the same directory, you can organize them in [groups](https://codeception.com/docs/07-AdvancedUsage#Groups).
+
+### Reports
+
+To generate JUnit XML output, you can provide the `--xml` option, and `--html` for HTML report.
+
+```bash
+php vendor/bin/codecept run --steps --xml --html
+```
+
+
+This command will run all tests for all suites, displaying the steps, and building HTML and XML reports. Reports will be stored in the `tests/_output/` directory.
+
+Learn more about [available reports](/docs/Reporting).
+
+## Debugging
+
+To receive detailed output, tests can be executed with the `--debug` option.
+
+Learn more about [debugging](/docs/Debugging).
+
+### Generators
+
+There are plenty of useful Codeception commands:
+
+* `generate:cest` *suite* *filename* - Generates a sample Cest test
+* `generate:test` *suite* *filename* - Generates a sample PHPUnit Test with Codeception hooks
+* `generate:feature` *suite* *filename* - Generates Gherkin feature file
+* `generate:suite` *suite* *actor* - Generates a new suite with the given Actor class name
+* `generate:scenarios` *suite* - Generates text files containing scenarios from tests
+* `generate:helper` *filename* - Generates a sample Helper File
+* `generate:pageobject` *suite* *filename* - Generates a sample Page object
+* `generate:stepobject` *suite* *filename* - Generates a sample Step object
+* `generate:environment` *env* - Generates a sample Environment configuration
+* `generate:groupobject` *group* - Generates a sample Group Extension
+
+## Conclusion
+
+We have taken a look into the Codeception structure. Most of the things you need were already generated by the `bootstrap` command.
+After you have reviewed the basic concepts and configurations, you can start writing your first scenario.
diff --git a/guides/03-AcceptanceTests.md b/guides/03-AcceptanceTests.md
new file mode 100644
index 000000000..b31eaca5d
--- /dev/null
+++ b/guides/03-AcceptanceTests.md
@@ -0,0 +1,765 @@
+# Acceptance Testing
+
+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.
+
+## Sample Scenario
+
+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:
+
+```php
+$I->amOnPage('/login');
+$I->fillField('username', 'davert');
+$I->fillField('password', 'qwerty');
+$I->click('LOGIN');
+$I->see('Welcome, Davert!');
+```
+
+**This scenario can be performed either by PhpBrowser or by a real browser through WebDriver**.
+
+| | PhpBrowser | WebDriver |
+| --- | --- | --- |
+| Browser Engine | Guzzle + Symfony BrowserKit | Chrome or Firefox |
+| JavaScript | No | Yes |
+| `see`/`seeElement` checks if… | …text is present in the HTML source | …text is actually visible to the user |
+| Access to HTTP response headers and status codes | Yes | No |
+| System requirements | PHP with [ext-curl](https://php.net/manual/book.curl.php) | Chrome or Firefox; optionally with Selenium Standalone Server |
+| Speed | Fast | Slow |
+
+We will start writing our first acceptance tests with PhpBrowser.
+
+## 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](https://guzzlephp.org) and [Symfony BrowserKit](https://symfony.com/doc/current/components/browser_kit.html) 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:
+
+```yaml
+# acceptance.suite.yml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://www.example.com/
+ - \Helper\Acceptance
+```
+
+We should start by creating a test with the next command:
+
+```
+php vendor/bin/codecept g:cest acceptance Signin
+```
+
+It will be placed into `tests/acceptance` directory.
+
+```php
+class SigninCest
+{
+ public function tryToTest(AcceptanceTester $I)
+ {
+ }
+}
+```
+
+The `$I` object is used to write all interactions.
+The methods of the `$I` object are taken from the [PhpBrowser Module](https://codeception.com/docs/modules/PhpBrowser). We will briefly describe them here:
+
+```php
+$I->amOnPage('/login');
+```
+
+We will assume that all actions starting with `am` and `have` describe the initial environment.
+The `amOnPage` action sets the starting point of a test to the `/login` page.
+
+With the `PhpBrowser` you can click the links and fill in the forms. That will probably be the majority of your actions.
+
+#### Click
+
+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.
+
+```php
+$I->click('Log in');
+// CSS selector applied
+$I->click('#login a');
+// XPath
+$I->click('//a[@id=login]');
+// Using context as second argument
+$I->click('Login', '.nav');
+```
+
+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:
+
+* id
+* name
+* css
+* xpath
+* link
+* class
+
+```php
+// By specifying locator type
+$I->click(['link' => 'Login']);
+$I->click(['class' => 'btn']);
+```
+
+There is a special class [`Codeception\Util\Locator`](https://codeception.com/docs/reference/Locator)
+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:
+
+```php
+$I->click('Edit' , \Codeception\Util\Locator::elementAt('//table/tr', -1));
+```
+
+#### Forms
+
+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:
+
+```html
+
+```
+
+From a user's perspective, a form consists of fields which should be filled in, and then a submit button clicked:
+
+```php
+// we are using label to match user_name field
+$I->fillField('Name', 'Miles');
+// we can use input name or id
+$I->fillField('user[email]','miles@davis.com');
+$I->selectOption('Gender','Male');
+$I->click('Update');
+```
+
+To match fields by their labels, you should write a `for` attribute in the `label` tag.
+
+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:
+
+```php
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm'
+)));
+```
+
+The `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
+or that fields have unclean names or badly written IDs, or the form is sent by a JavaScript call.
+
+By default, `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:
+
+```php
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm'
+)), 'submitButton');
+// this would have the same effect, but the value has to be explicitly specified
+$I->submitForm('#update_form', array('user' => array(
+ 'name' => 'Miles',
+ 'email' => 'Davis',
+ 'gender' => 'm',
+ 'submitButton' => 'Update'
+)));
+```
+
+##### 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.
+
+```php
+use \Codeception\Step\Argument\PasswordArgument;
+
+$I->amOnPage('/form/password_argument');
+$I->fillField('password', new PasswordArgument('thisissecret'));
+```
+
+`thisissecret` will be filled into a form but it won't be shown in output and logs.
+
+#### Assertions
+
+In the `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 `see()`:
+
+```php
+// We check that 'Thank you, Miles' is on the page.
+$I->see('Thank you, Miles');
+// We check that 'Thank you, Miles' is inside an element with 'notice' class.
+$I->see('Thank you, Miles', '.notice');
+// Or using XPath locators
+$I->see('Thank you, Miles', "//table/tr[2]");
+// We check this message is *not* on the page.
+$I->dontSee('Form is filled incorrectly');
+```
+
+You can check that a specific HTML element exists (or doesn't) on a page:
+
+```php
+$I->seeElement('.notice');
+$I->dontSeeElement('.error');
+```
+
+We also have other useful commands to perform checks. Please note that they all start with the `see` prefix:
+
+```php
+$I->seeInCurrentUrl('/user/miles');
+$I->seeCheckboxIsChecked('#agree');
+$I->seeInField('user[name]', 'Miles');
+$I->seeLink('Login');
+```
+
+#### Conditional Assertions
+
+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.
+Each `see` method has a corresponding `canSee` method, and `dontSee` has a `cantSee` method:
+
+```php
+$I->canSeeInCurrentUrl('/user/miles');
+$I->canSeeCheckboxIsChecked('#agree');
+$I->cantSeeInField('user[name]', 'Miles');
+```
+
+Each failed assertion will be shown in the test results, but it won't stop the test.
+
+Conditional assertions are disabled in bootstrap setup. To enable them you should add corresponding step decorators to suite config:
+
+> If you started project as `codecept init acceptance` they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\ConditionalAssertion
+```
+
+Then rebuild actors with `codecept build` command.
+
+#### Comments
+
+Within a long scenario, you should describe what actions you are going to perform and what results should be achieved.
+Comment methods like `amGoingTo`, `expect`, `expectTo` help you in making tests more descriptive:
+
+```php
+$I->amGoingTo('submit user form with invalid values');
+$I->fillField('user[email]', 'miles');
+$I->click('Update');
+$I->expect('the form is not submitted');
+$I->see('Form is filled incorrectly');
+```
+
+#### Grabbers
+
+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:
+
+```php
+$I->fillField('email', 'miles@davis.com');
+$I->click('Generate Password');
+$password = $I->grabTextFrom('#password');
+$I->click('Login');
+$I->fillField('email', 'miles@davis.com');
+$I->fillField('password', $password);
+$I->click('Log in!');
+```
+
+Grabbers allow you to get a single value from the current page with commands:
+
+```php
+$token = $I->grabTextFrom('.token');
+$password = $I->grabTextFrom("descendant::input/descendant::*[@id = 'password']");
+$api_key = $I->grabValueFrom('input[name=api]');
+```
+
+#### Cookies, URLs, Title, etc
+
+Actions for cookies:
+
+```php
+$I->setCookie('auth', '123345');
+$I->grabCookie('auth');
+$I->seeCookie('auth');
+```
+
+Actions for checking the page title:
+
+```php
+$I->seeInTitle('Login');
+$I->dontSeeInTitle('Register');
+```
+
+Actions for URLs:
+
+```php
+$I->seeCurrentUrlEquals('/login');
+$I->seeCurrentUrlMatches('~^/users/(\d+)~');
+$I->seeInCurrentUrl('user/1');
+$user_id = $I->grabFromCurrentUrl('~^/user/(\d+)/~');
+```
+
+## WebDriver
+
+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](https://www.w3.org/TR/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 [php-webdriver/php-webdriver](https://github.com/php-webdriver/php-webdriver) as a PHP implementation of the 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.
+
+### Local Setup
+
+### Selenium Server
+
+[Selenium](https://www.selenium.dev) is required to launch and control browsers from Codeception.
+Selenium Server is required to be installed and started before running tests.
+
+The fastest way of getting Selenium is using [selenium-standalone](https://www.npmjs.com/package/selenium-standalone) NodeJS Package.
+It automatically installs Selenium and all required dependencies and starts server. It requires **NodeJS and Java** to be installed.
+
+```
+npm install selenium-standalone -g
+selenium-standalone install
+```
+
+Launch this command in a separate terminal:
+
+```
+selenium-standalone start
+```
+
+
+
+Now, you are ready to run WebDriver tests using Codeception.
+
+> Alternatively, Selenium Server can be installed manually. [Download it](https://www.selenium.dev/downloads/) from the official site and launch a server with Java: `java -jar selenium-server-....jar`. In this case ChromeDriver and GeckoDriver must be installed separately.
+
+* For more information refer to [Installation Instructions](https://codeception.com/docs/modules/WebDriver#Selenium)
+* Enable [RunProcess](https://codeception.com/extensions#RunProcess) extension to start/stop Selenium automatically *(optional)*.
+
+
+### Configuration
+
+To execute a test in a browser you need to change the suite configuration to use **WebDriver** module.
+
+Modify your `acceptance.suite.yml` file:
+
+```yaml
+actor: AcceptanceTester
+modules:
+ enabled:
+ - WebDriver:
+ url: {{your site URL}}
+ browser: chrome
+ - \Helper\Acceptance
+```
+
+See [WebDriver Module](https://codeception.com/docs/modules/WebDriver) 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:
+
+```php
+$I->seeElement('#modal');
+```
+
+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:
+
+#### Wait
+
+While testing web application, you may need to wait for JavaScript events to occur. Due to its asynchronous nature,
+complex JavaScript interactions are hard to test. That's why you may need to use waiters, actions with `wait` prefix.
+They can be used to specify what event you expect to occur on a page, before continuing the test.
+
+For example:
+
+```php
+$I->waitForElement('#agree_button', 30); // secs
+$I->click('#agree_button');
+```
+
+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](https://codeception.com/docs/modules/WebDriver#waitForText),
+[waitForElementVisible](https://codeception.com/docs/modules/WebDriver#waitForElementVisible) and others.
+
+If you don't know what exact element you need to wait for, you can simply pause execution with using `$I->wait()`
+
+```php
+$I->wait(3); // wait for 3 secs
+```
+
+#### SmartWait
+
+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](https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits) 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:
+
+```yaml
+wait: 5
+```
+
+With this config we have the following test:
+
+```php
+// we use wait: 5 instead of
+// $I->waitForElement(['css' => '#click-me'], 5);
+// to wait for element on page
+$I->click(['css' => '#click-me']);
+```
+
+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:
+
+```php
+$I->click('Login'); // DISABLED, not a specific locator
+$I->fillField('user', 'davert'); // DISABLED, not a specific locator
+$I->fillField(['name' => 'password'], '123456'); // ENABLED, strict locator
+$I->click('#login'); // ENABLED, locator is CSS ID
+$I->see('Hello, Davert'); // DISABLED, Not a locator
+$I->seeElement('#userbar'); // ENABLED
+$I->dontSeeElement('#login'); // DISABLED, can't wait for element to hide
+$I->seeNumberOfElements(['css' => 'button.link'], 5); // DISABLED, can wait only for one element
+```
+
+#### Retry
+
+When it's hard to define condition to wait for, we can retry a command few times until it succeeds.
+For instance, if you try to click while it's animating you can try to do it few times until it freezes.
+Each action and assertion have an alias prefixed with `retry` which allows to retry a flaky command.
+
+```php
+$I->retryClick('flaky element');
+$I->retrySee('Something changed');
+```
+
+Retry can be configured via `$I->retry()` command, where you can set number of retries and initial interval:
+interval will be doubled on each unsuccessful execution.
+
+```php
+// Retry up to 6 sec: 4 times, for 400ms initial interval => 400ms + 800ms + 1600ms + 3200ms = 6000ms
+$I->retry(4, 400);
+```
+
+`$I->retry` takes 2 parameters:
+* number of retries (1 by default)
+* initial interval (200ms by default)
+
+Retries are disabled by default. To enable them you should add retry step decorators to suite config:
+
+> If you started project as `codecept init acceptance` they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\Retry
+```
+
+Then add `\Codeception\Lib\Actor\Shared\Retry` trait into `AcceptanceTester` class:
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ use _generated\AcceptanceTesterActions;
+
+ use \Codeception\Lib\Actor\Shared\Retry;
+}
+```
+
+Run `codecept build` to recreate actions. New `retry*` actions are available for tests.
+Keep in mind, that you can change retry policy dynamically for each test.
+
+#### Wait and Act
+
+To combine `waitForElement` with actions inside that element you can use the [performOn](https://codeception.com/docs/modules/WebDriver#performOn) method.
+Let's see how you can perform some actions inside an HTML popup:
+
+```php
+$I->performOn('.confirm', \Codeception\Util\ActionSequence::build()
+ ->see('Warning')
+ ->see('Are you sure you want to delete this?')
+ ->click('Yes')
+);
+```
+Alternatively, this can be executed using a callback, in this case the `WebDriver` instance is passed as argument
+
+```php
+$I->performOn('.confirm', function(\Codeception\Module\WebDriver $I) {
+ $I->see('Warning');
+ $I->see('Are you sure you want to delete this?');
+ $I->click('Yes');
+});
+```
+
+For more options see [`performOn()` reference](https://codeception.com/docs/modules/WebDriver#performOn).
+
+#### A/B Testing
+
+When a web site acts unpredictably you may need to react on that change.
+This happens if site configured for A/B testing, or shows different popups, based on environment.
+
+Since Codeception 3.0 you can have some actions to fail silently, if they are errored.
+Let's say, you open a page and some times there is a popup which should be closed.
+We may try to hit the "close" button but if this action fails (no popup on page) we just continue the test.
+
+This is how it can be implemented:
+
+```php
+$I->amOnPage('/');
+$I->tryToClick('x', '.alert');
+// continue execution
+```
+
+You can also use `tryTo` as condition for your tests:
+
+```php
+if ($I->tryToSeeElement('.alert')) {
+ $I->waitForText('Do you accept cookies?');
+ $I->click('Yes');
+}
+```
+
+A/B testing is disabled by default. To enable it you should add corresponding step decorators to suite config:
+
+> If you started project as `codecept init acceptance` in Codeception >= 3.0 they should be already enabled in config
+
+```yaml
+# in acceptance.suite.yml
+# or in codeception.yml inside suites section
+step_decorators:
+ - \Codeception\Step\TryTo
+```
+
+Then rebuild actors with `codecept build` command.
+
+### 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**:
+
+```php
+$I->amOnPage('/messages');
+$nick = $I->haveFriend('nick');
+$nick->does(function(AcceptanceTester $I) {
+ $I->amOnPage('/messages/new');
+ $I->fillField('body', 'Hello all!');
+ $I->click('Send');
+ $I->see('Hello all!', '.message');
+});
+$I->wait(3);
+$I->see('Hello all!', '.message');
+```
+
+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 `leave()`.
+You can also specify roles for a friend:
+
+```php
+$nickAdmin = $I->haveFriend('nickAdmin', adminStep::class);
+$nickAdmin->does(function(adminStep $I) {
+ // Admin does ...
+});
+$nickAdmin->leave();
+```
+
+Multi session testing is disabled by default. To enable it, add `\Codeception\Lib\Actor\Shared\Friend` into `AcceptanceTester`.
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ use _generated\AcceptanceTesterActions;
+
+ use \Codeception\Lib\Actor\Shared\Friend;
+}
+```
+
+### Cloud Testing
+
+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](https://saucelabs.com), [BrowserStack](https://www.browserstack.com/)
+and [others](https://codeception.com/docs/modules/WebDriver#Cloud-Testing) 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](https://codeception.com/docs/modules/WebDriver#Cloud-Testing) to:
+
+* specify the host to connect to (depends on the cloud provider)
+* authentication details (to use your account)
+* browser
+* OS
+
+We recommend using [params](https://codeception.com/docs/06-ModulesAndHelpers#Dynamic-Configuration-With-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.
+
+### Debugging
+
+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 `codecept_debug` function:
+
+```php
+codecept_debug($I->grabTextFrom('#name'));
+```
+
+On each failure, the snapshot of the last shown page will be stored in the `tests/_output` directory.
+PhpBrowser will store the HTML code and WebDriver will save a screenshot of the page.
+
+Additional debugging features by Codeception:
+
+* [Interactive Pause](https://codeception.com/docs/02-GettingStarted#Interactive-Pause) is a REPL that allows to type and check commands for instant feedback.
+* [Recorder Extension](https://codeception.com/addons#CodeceptionExtensionRecorder) allows to record tests step-by-steps and show them in slideshow
+
+### Common Cases
+
+Let's see how common problems of acceptance testing can be solved with Codeception.
+
+#### Login
+
+It is recommended to put widely used actions inside an Actor class. A good example is the `login` action
+which would probably be actively involved in acceptance or functional testing:
+
+```php
+class AcceptanceTester extends \Codeception\Actor
+{
+ // do not ever remove this line!
+ use _generated\AcceptanceTesterActions;
+
+ public function login($name, $password)
+ {
+ $I = $this;
+ $I->amOnPage('/login');
+ $I->submitForm('#loginForm', [
+ 'login' => $name,
+ 'password' => $password
+ ]);
+ $I->see($name, '.navbar');
+ }
+}
+```
+
+Now you can use the `login` method inside your tests:
+
+```php
+// $I is AcceptanceTester
+$I->login('miles', '123456');
+```
+
+However, implementing all actions for reuse in a single actor class may lead to
+breaking the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle).
+
+#### Single Login
+
+If you need to authorize a user for each test, you can do so by submitting the login form at the beginning of every test.
+Running those steps takes time, and in the case of Selenium tests (which are slow by themselves)
+that time loss can become significant.
+
+Codeception allows you to share cookies between tests, so a test user can stay logged in for other tests.
+
+Let's improve the code of our `login` method, executing the form submission only once
+and restoring the session from cookies for each subsequent login function call:
+
+```php
+public function login($name, $password)
+ {
+ $I = $this;
+ // if snapshot exists - skipping login
+ if ($I->loadSessionSnapshot('login')) {
+ return;
+ }
+ // logging in
+ $I->amOnPage('/login');
+ $I->submitForm('#loginForm', [
+ 'login' => $name,
+ 'password' => $password
+ ]);
+ $I->see($name, '.navbar');
+ // saving snapshot
+ $I->saveSessionSnapshot('login');
+ }
+```
+
+Note that session restoration only works for `WebDriver` modules
+(modules implementing `Codeception\Lib\Interfaces\SessionSnapshot`).
+
+
+### 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](https://codeception.com/docs/06-ModulesAndHelpers#Helpers).
+
+WebDriver module provides advanced methods for the browser session, however, they can only be used from Helpers.
+
+* [_initializeSession](https://codeception.com/docs/modules/WebDriver#_initializeSession) - starts a new browser session
+* [_closeSession](https://codeception.com/docs/modules/WebDriver#_closeSession) - stops the browser session
+* [_restart](https://codeception.com/docs/modules/WebDriver#_restart) - updates configuration and restarts browser
+* [_capabilities](https://codeception.com/docs/modules/WebDriver#_capabilities) - set [desired capabilities](https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities) programmatically.
+
+Those methods can be used to create custom commands like `$I->startBrowser()` or used in [before/after](https://codeception.com/docs/06-ModulesAndHelpers#Hooks) hooks.
+
+## Conclusion
+
+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](https://codeception.com/docs/modules/Db).
diff --git a/guides/04-FunctionalTests.md b/guides/04-FunctionalTests.md
new file mode 100644
index 000000000..ea7e72495
--- /dev/null
+++ b/guides/04-FunctionalTests.md
@@ -0,0 +1,232 @@
+# Functional Tests
+
+Now that we've written some acceptance tests, functional tests are almost the same, with one major difference:
+Functional tests don't require a web server.
+
+Under the hood, Codeception uses Symfony's [BrowserKit](https://symfony.com/doc/current/components/browser_kit.html)
+to "send" requests to your app. So there's no real HTTP request made, but rather a BrowserKit
+[Request object](https://github.com/symfony/browser-kit/blob/master/Request.php) with the required properties is
+passed to your framework's (front-)controller.
+
+As a first step, you need to enable Codeception's module for your framework in `Functional.suite.yml` (see below).
+
+All of Codeception's framework modules share the same interface, and thus your tests are not bound to any one of them.
+This is a sample functional test:
+
+```php
+amOnPage('/');
+ $I->click('Login');
+ $I->fillField('Username', 'Miles');
+ $I->fillField('Password', 'Davis');
+ $I->click('Enter');
+ $I->see('Hello, Miles', 'h1');
+ // $I->seeEmailIsSent(); // only for Symfony
+ }
+}
+```
+
+As you see, the syntax is the same for functional and acceptance tests.
+
+## Limitations
+
+Functional tests are usually much faster than acceptance tests. But functional tests are less stable as they run Codeception
+and the application in one environment. If your application was not designed to run in long lived processes (e.g.
+if you use the `exit` operator or global variables), then functional tests are probably not for you.
+
+### Headers, Cookies, Sessions
+
+One of the common issues with functional tests is the use of PHP functions that deal with headers, sessions and cookies.
+As you may already know, the `header` function triggers an error if it is executed after PHP has already output something.
+In functional tests we run the application multiple times, thus we will get lots of irrelevant errors in the result.
+
+### External URLs
+
+Functional tests cannot access external URLs, just URLs within your project. You can use PhpBrowser to open external URLs.
+
+### Shared Memory
+
+In functional testing, unlike running the application the traditional way, the PHP application does not stop
+after it has finished processing a request. Since all requests are run in one memory container, they are not isolated.
+So **if you see that your tests are mysteriously failing when they shouldn't - try to execute a single test.**
+This will show if the tests were failing because they weren't isolated during the run.
+Keep your memory clean, avoid memory leaks and clean global and static variables.
+
+## Enabling Framework Modules
+
+You have a functional testing suite in the `tests/functional` directory.
+To start, you need to include one of the framework modules in the suite configuration file: `tests/Functional.suite.yml`.
+
+### Symfony
+
+To perform Symfony integration you just need to include the Symfony module into your test suite. If you also use Doctrine2,
+don't forget to include it too. To make the Doctrine2 module connect using the `doctrine` service from Symfony,
+you should specify the Symfony module as a dependency for Doctrine2:
+
+```yaml
+# Functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Symfony
+ - Doctrine2:
+ depends: Symfony # connect to Symfony
+```
+
+By default this module will search for AppKernel in the `app` directory.
+
+The module uses the Symfony Profiler to provide additional information and assertions.
+
+[See the full reference](https://codeception.com/docs/modules/Symfony)
+
+### Laravel
+
+The [Laravel](https://codeception.com/docs/modules/Laravel) module is included and requires no configuration:
+
+```yaml
+# Functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Laravel
+```
+
+### Yii2
+
+Yii2 tests are included in [Basic](https://github.com/yiisoft/yii2-app-basic)
+and [Advanced](https://github.com/yiisoft/yii2-app-advanced) application templates. Follow the Yii2 guides to start.
+
+### Laminas
+
+[Laminas](https://codeception.com/docs/modules/Laminas) tests can be executed with enabling a corresponding module.
+
+```yaml
+# Functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Laminas
+```
+
+> See module reference to more configuration options
+
+### Phalcon 5
+
+The `Phalcon5` module requires creating a bootstrap file which returns an instance of `\Phalcon\Mvc\Application`.
+To start writing functional tests with Phalcon support you should enable the `Phalcon5` module
+and provide the path to this bootstrap file:
+
+```yaml
+# Functional.suite.yml
+
+actor: FunctionalTester
+modules:
+ enabled:
+ - Phalcon5:
+ bootstrap: 'app/config/bootstrap.php'
+ cleanup: true
+ savepoints: true
+```
+
+[See the full reference](https://codeception.com/docs/modules/Phalcon4)
+
+## Writing Functional Tests
+
+Functional tests are written in the same manner as [Acceptance Tests](https://codeception.com/docs/03-AcceptanceTests)
+with the `PhpBrowser` module enabled. All framework modules and the `PhpBrowser` module share the same methods
+and the same engine.
+
+Therefore we can open a web page with `amOnPage` method:
+
+```php
+$I->amOnPage('/login');
+```
+
+We can click links to open web pages:
+
+```php
+$I->click('Logout');
+// click link inside .nav element
+$I->click('Logout', '.nav');
+// click by CSS
+$I->click('a.logout');
+// click with strict locator
+$I->click(['class' => 'logout']);
+```
+
+We can submit forms as well:
+
+```php
+$I->submitForm('form#login', ['name' => 'john', 'password' => '123456']);
+// alternatively
+$I->fillField('#login input[name=name]', 'john');
+$I->fillField('#login input[name=password]', '123456');
+$I->click('Submit', '#login');
+```
+
+And do assertions:
+
+```php
+$I->see('Welcome, john');
+$I->see('Logged in successfully', '.notice');
+$I->seeCurrentUrlEquals('/profile/john');
+```
+
+Framework modules also contain additional methods to access framework internals. For instance, Laravel, Phalcon,
+and Yii2 modules have a `seeRecord` method which uses the ActiveRecord layer to check that a record exists in the database.
+
+Take a look at the complete reference for the module you are using. Most of its methods are common to all modules
+but some of them are unique.
+
+You can also access framework globals inside a test or access the dependency injection container
+inside the `Helper\Functional` class:
+
+```php
+getModule('Symfony')->grabServiceFromContainer('myservice');
+ $service->doSomething();
+ }
+}
+```
+
+Also check all available *Public Properties* of the used modules to get full access to their data.
+
+## Error Reporting
+
+By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
+In functional tests you might want to change this level depending on your framework's error policy.
+The error reporting level can be set in the suite configuration file:
+
+```yaml
+actor: FunctionalTester
+...
+error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
+```
+
+`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
+
+## Conclusion
+
+Functional tests are great if you are using powerful frameworks. By using functional tests you can access
+and manipulate their internal state. This makes your tests shorter and faster. In other cases,
+if you don't use frameworks there is no practical reason to write functional tests.
+If you are using a framework other than the ones listed here, create a module for it and share it with the community.
diff --git a/guides/05-UnitTests.md b/guides/05-UnitTests.md
new file mode 100644
index 000000000..dfdafb04c
--- /dev/null
+++ b/guides/05-UnitTests.md
@@ -0,0 +1,501 @@
+# Unit & Integration Tests
+
+Codeception uses PHPUnit as a backend for running its tests. Thus, any PHPUnit test can be added to a Codeception test suite
+and then executed. If you ever wrote a PHPUnit test then do it just as you did before.
+Codeception adds some nice helpers to simplify common tasks.
+
+## Creating a Test
+
+Create a test using `generate:test` command with a suite and test names as parameters:
+
+```bash
+php vendor/bin/codecept generate:test unit Example
+```
+
+It creates a new `ExampleTest` file located in the `tests/unit` directory.
+
+As always, you can run the newly created test with this command:
+
+```bash
+php vendor/bin/codecept run unit ExampleTest
+```
+
+Or simply run the whole set of unit tests with:
+
+```bash
+php vendor/bin/codecept run unit
+```
+
+A test created by the `generate:test` command will look like this:
+
+```php
+setName(null);
+ $this->assertFalse($user->validate(['username']));
+
+ $user->setName('toolooooongnaaaaaaameeee');
+ $this->assertFalse($user->validate(['username']));
+
+ $user->setName('davert');
+ $this->assertTrue($user->validate(['username']));
+ }
+}
+```
+
+### Assertions
+
+There are pretty many assertions you can use inside tests. The most common are:
+
+* `$this->assertEquals()`
+* `$this->assertContains()`
+* `$this->assertFalse()`
+* `$this->assertTrue()`
+* `$this->assertNull()`
+* `$this->assertEmpty()`
+
+Assertion methods come from PHPUnit. [See the complete reference at phpunit.de](https://phpunit.de/manual/current/en/appendixes.assertions.html).
+
+
+### Fluent Assertions
+
+You may add [Codeception\Verify](https://github.com/Codeception/Verify) for BDD-style assertions.
+This tiny library adds more readable assertions, which is quite nice, if you are always confused
+about which argument in `assert` calls is expected and which one is actual:
+
+```php
+// simple assertions
+verify($user)->notNull();
+verify($user->getName())->equals('john');
+
+// greater / less
+verify($user->getRate())
+ ->greaterThan(5)
+ ->lessThan(10)
+ ->equals(7, 'first user rate is 7');
+
+// array assertions
+Verify::Array($user->getRoles())
+ ->contains('admin', 'first user is admin')
+ ->notContains('banned', 'first user is not banned');
+```
+
+### Test Doubles
+
+Codeception provides [Codeception\Stub library](https://github.com/Codeception/Stub) for building mocks and stubs for tests.
+Under the hood it used PHPUnit's mock builder but with much simplified API.
+
+Alternatively, [Mockery](https://github.com/Codeception/MockeryModule) can be used inside Codeception.
+
+#### Stubs
+
+Stubs can be created with a static methods of `Codeception\Stub`.
+
+```php
+$user = \Codeception\Stub::make('User', ['getName' => 'john']);
+$name = $user->getName(); // 'john'
+```
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+Inside unit tests (`Codeception\Test\Unit`) it is recommended to use alternative API:
+
+```php
+// create a stub with find method replaced
+$userRepository = $this->make(UserRepository::class, ['find' => new User]);
+$userRepository->find(1); // => User
+
+// create a dummy
+$userRepository = $this->makeEmpty(UserRepository::class);
+
+// create a stub with all methods replaced except one
+$user = $this->makeEmptyExcept(User::class, 'validate');
+$user->validate($data);
+
+// create a stub by calling constructor and replacing a method
+$user = $this->construct(User::class, ['name' => 'davert'], ['save' => false]);
+
+// create a stub by calling constructor with empty methods
+$user = $this->constructEmpty(User::class, ['name' => 'davert']);
+
+// create a stub by calling constructor with empty methods
+$user = $this->constructEmptyExcept(User::class, 'getName', ['name' => 'davert']);
+$user->getName(); // => davert
+$user->setName('jane'); // => this method is empty
+```
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+Stubs can also be created using static methods from `Codeception\Stub` class.
+In this
+
+```php
+\Codeception\Stub::make(UserRepository::class, ['find' => new User]);
+```
+
+See a reference for [static Stub API](https://codeception.com/docs/reference/Stub)
+
+#### Mocks
+
+To declare expectations for mocks use `Codeception\Stub\Expected` class:
+
+```php
+// create a mock where $user->getName() should never be called
+$user = $this->make('User', [
+ 'getName' => Expected::never(),
+ 'someMethod' => function() {}
+]);
+$user->someMethod();
+
+// create a mock where $user->getName() should be called at least once
+$user = $this->make('User', [
+ 'getName' => Expected::atLeastOnce('Davert')
+ ]
+);
+$user->getName();
+$userName = $user->getName();
+$this->assertEquals('Davert', $userName);
+```
+
+[See complete reference](https://codeception.com/docs/reference/Mock)
+
+## Integration Tests
+
+Unlike unit tests integration tests doesn't require the code to be executed in isolation.
+That allows us to use database and other components inside a tests.
+To improve the testing experience modules can be used as in functional testing.
+
+### Using Modules
+
+As in scenario-driven functional or acceptance tests you can access Actor class methods.
+If you write integration tests, it may be useful to include the `Db` module for database testing.
+
+```yaml
+# Codeception Test Suite Configuration
+
+# suite for unit (internal) tests.
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Db
+```
+
+To access UnitTester methods you can use the `UnitTester` property in a test.
+
+### Testing Database
+
+Let's see how you can do some database testing:
+
+```php
+setName('Miles');
+ $user->setSurname('Davis');
+ $user->save();
+ $this->assertEquals('Miles Davis', $user->getFullName());
+ $this->tester->seeInDatabase('users', ['name' => 'Miles', 'surname' => 'Davis']);
+}
+```
+
+To enable the database functionality in unit tests, make sure the `Db` module is included
+in the `unit.suite.yml` configuration file.
+The database will be cleaned and populated after each test, the same way it happens for acceptance and functional tests.
+If that's not your required behavior, change the settings of the `Db` module for the current suite. See [Db Module](https://codeception.com/docs/modules/Db)
+
+### Interacting with the Framework
+
+You should probably not access your database directly if your project already uses ORM for database interactions.
+Why not use ORM directly inside your tests? Let's try to write a test using Laravel's ORM Eloquent.
+For this we need to configure the Laravel module. We won't need its web interaction methods like `amOnPage` or `see`,
+so let's enable only the ORM part of it:
+
+```yaml
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Laravel:
+ part: ORM
+```
+
+We included the Laravel module the same way we did for functional testing.
+Let's see how we can use it for integration tests:
+
+```php
+tester->haveRecord('users', ['name' => 'miles']);
+ // access model
+ $user = User::find($id);
+ $user->setName('bill');
+ $user->save();
+ $this->assertEquals('bill', $user->getName());
+ // verify data was saved using framework methods
+ $this->tester->seeRecord('users', ['name' => 'bill']);
+ $this->tester->dontSeeRecord('users', ['name' => 'miles']);
+}
+```
+
+A very similar approach can be used for all frameworks that have an ORM implementing the ActiveRecord pattern.
+In Yii2 and Phalcon, the methods `haveRecord`, `seeRecord`, `dontSeeRecord` work in the same way.
+They also should be included by specifying `part: ORM` in order to not use the functional testing actions.
+
+If you are using Symfony with Doctrine, you don't need to enable Symfony itself but just Doctrine2:
+
+```yaml
+actor: UnitTester
+modules:
+ enabled:
+ - Asserts
+ - Doctrine2:
+ depends: Symfony
+ - \Helper\Unit
+```
+
+In this case you can use the methods from the Doctrine2 module, while Doctrine itself uses the Symfony module
+to establish connections to the database. In this case a test might look like:
+
+```php
+tester->haveInRepository(User::class, ['name' => 'miles']);
+ // get entity manager by accessing module
+ $em = $this->getModule('Doctrine2')->em;
+ // get real user
+ $user = $em->find(User::class, $id);
+ $user->setName('bill');
+ $em->persist($user);
+ $em->flush();
+ $this->assertEquals('bill', $user->getName());
+ // verify data was saved using framework methods
+ $this->tester->seeInRepository(User::class, ['name' => 'bill']);
+ $this->tester->dontSeeInRepository(User::class, ['name' => 'miles']);
+}
+```
+
+In both examples you should not be worried about the data persistence between tests.
+The Doctrine2 and Laravel modules will clean up the created data at the end of a test.
+This is done by wrapping each test in a transaction and rolling it back afterwards.
+
+### Accessing Module
+
+Codeception allows you to access the properties and methods of all modules defined for this suite.
+Unlike using the UnitTester class for this purpose, using a module directly grants you access
+to all public properties of that module.
+
+We have already demonstrated this in a previous example where we accessed the Entity Manager from a Doctrine2 module:
+
+```php
+getModule('Doctrine2')->em;
+```
+
+If you use the `Symfony` module, here is how you can access the Symfony container:
+
+```php
+/** @var Symfony\Component\DependencyInjection\Container */
+$container = $this->getModule('Symfony')->container;
+```
+
+The same can be done for all public properties of an enabled module. Accessible properties are listed in the module reference.
+
+### Scenario Driven Testing
+
+[Cest format](https://codeception.com/docs/07-AdvancedUsage#Cest-Classes) can also be used for integration testing.
+In some cases it makes tests cleaner as it simplifies module access by using common `$I->` syntax:
+
+```php
+public function buildShouldHaveSequence(UnitTester $I)
+{
+ $build = $I->have(Build::class, ['project_id' => $this->project->id]);
+ $I->assertEquals(1, $build->sequence);
+ $build = $I->have(Build::class, ['project_id' => $this->project->id]);
+ $I->assertEquals(2, $build->sequence);
+ $this->project->refresh();
+ $I->assertEquals(3, $this->project->build_sequence);
+}
+```
+This format can be recommended for testing domain and database interactions.
+
+In Cest format you don't have native support for test doubles so it's recommended
+to include a trait `\Codeception\Test\Feature\Stub` to enable mocks inside a test.
+Alternatively, install and enable [Mockery module](https://github.com/Codeception/MockeryModule).
+
+## Advanced Tools
+
+### Specify
+
+When writing tests you should prepare them for constant changes in your application.
+Tests should be easy to read and maintain. If a specification of your application is changed,
+your tests should be updated as well. If you don't have a convention inside your team for documenting tests,
+you will have issues figuring out what tests will be affected by the introduction of a new feature.
+
+That's why it's pretty important not just to cover your application with unit tests, but make unit tests self-explanatory.
+We do this for scenario-driven acceptance and functional tests, and we should do this for unit and integration tests as well.
+
+For this case we have a stand-alone project [Specify](https://github.com/Codeception/Specify)
+(which is included in the phar package) for writing specifications inside unit tests:
+
+```php
+user = \App\User::create();
+
+ $this->specify("username is required", function() {
+ $this->user->username = null;
+ $this->assertFalse($this->user->validate(['username']));
+ });
+
+ $this->specify("username is too long", function() {
+ $this->user->username = 'toolooooongnaaaaaaameeee';
+ $this->assertFalse($this->user->validate(['username']));
+ });
+
+ $this->specify("username is ok", function() {
+ $this->user->username = 'davert';
+ $this->assertTrue($this->user->validate(['username']));
+ });
+ }
+}
+```
+
+By using `specify` codeblocks, you can describe any piece of a test.
+This makes tests much cleaner and comprehensible for everyone in your team.
+
+Code inside `specify` blocks is isolated. In the example above, any changes to `$this->user`
+will not be reflected in other code blocks as it is marked with `@specify` annotation.
+
+
+### Domain Assertions
+
+The more complicated your domain is the more explicit your tests should be. With [DomainAssert](https://github.com/Codeception/DomainAssert)
+library you can easily create custom assertion methods for unit and integration tests.
+
+It allows to reuse business rules inside assertion methods:
+
+```php
+$user = new \App\User;
+
+// simple custom assertions below:
+$this->assertUserIsValid($user);
+$this->assertUserIsAdmin($user);
+
+// use combined explicit assertion
+// to tell what you expect to check
+$this->assertUserCanPostToBlog($user, $blog);
+// instead of just calling a bunch of assertions
+$this->assertNotNull($user);
+$this->assertNotNull($blog);
+$this->assertContain($user, $blog->getOwners());
+```
+
+With custom assertion methods you can improve readability of your tests and keep them focused around the specification.
+
+### AspectMock
+
+[AspectMock](https://github.com/Codeception/AspectMock) is an advanced mocking framework which allows you to replace any methods of any class in a test.
+Static methods, class methods, date and time functions can be easily replaced with AspectMock.
+For instance, you can test singletons!
+
+```php
+assertInstanceOf('MySingleton', $class);
+ test::double('MySingleton', ['getInstance' => new DOMDocument]);
+ $this->assertInstanceOf('DOMDocument', $class);
+}
+```
+
+* [AspectMock on GitHub](https://github.com/Codeception/AspectMock)
+* [AspectMock in Action](https://codeception.com/07-31-2013/nothing-is-untestable-aspect-mock.html)
+* [How it Works](https://codeception.com/09-13-2013/understanding-aspectmock.html)
+
+## Error Reporting
+
+By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
+In unit tests you might want to change this level depending on your framework's error policy.
+The error reporting level can be set in the suite configuration file:
+
+```yaml
+actor: UnitTester
+...
+error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
+```
+
+`error_level` can also be set globally in `codeception.yml` file. In order to do that, you need to specify `error_level` as a part of `settings`. For more information, see [Global Configuration](https://codeception.com/docs/reference/Configuration). Note that suite specific `error_level` value will override global value.
+
+## Conclusion
+
+PHPUnit tests are first-class citizens in test suites. Whenever you need to write and execute unit tests,
+you don't need to install PHPUnit separately, but use Codeception directly to execute them.
+Some nice features can be added to common unit tests by integrating Codeception modules.
+For most unit and integration testing, PHPUnit tests are enough. They run fast, and are easy to maintain.
diff --git a/guides/06-Debugging.md b/guides/06-Debugging.md
new file mode 100644
index 000000000..e52d15071
--- /dev/null
+++ b/guides/06-Debugging.md
@@ -0,0 +1,75 @@
+# Debugging
+
+Writing a test is always the process of learning the code and the application.
+It is ok, if a test can't be writtng from scratch or you don't understand the effects of the code.
+By looking into the following debugging practices you will learn how to get all required information inside a test to finish it.
+
+## Re-Running Failed Tests
+
+Codeception saves the list of failed tests. To re-run failed test run tests from `failed` group:
+
+```php
+php vendor/bin/codecept run -g failed
+```
+
+If no tests have failed this group will be empty.
+
+## Output
+
+Codeception provides `codecept_debug` function to print a debug output when running test.
+Think of it as `var_dump` but for testing:
+
+```php
+codecept_debug($user);
+```
+
+Unlinke var_dump, the output will be printed to screen only if tests are executed with `--debug` flag.
+
+```
+php vendor/bin/codecept run --debug
+```
+
+So it is safe to keep `codecept_debug` inside a test, it won't affect the code running on Continuous Integration server.
+
+`codecept_debug` can be used in any place of your tests, but it is prohibited to use it in application code.
+This function is loaded only by Codeception, so the application may be broken trying to call this line.
+
+Inside a [Helper](/docs/06-ModulesAndHelpers#Helpers) you can use analogs of this function to provide a debug output for a complex action.
+
+
+```php
+// print variable from helper
+$this->debug($response);
+
+// print variable with a short comment
+$this->debugSection('Response', $response);
+```
+
+Codeception Modules use debug output to give more information to user about the data used by a test. For instance, in debug mode you can see request and responses body when testing REST API.
+
+
+## Pause
+
+When running acceptance or functional test it might be needed to pause execution at one point to figure out what to do next. For instance, when interacting with a page in a web browser, you might need the execution to be paused to interact with elements on a page, discover proper locators, and next steps for the scenario. That's why Codeception has an interactive pause mode (powered by [PsySH](https://psysh.org)) which can be started by `codecept_pause` function or `$I->pause()`.
+
+Writing a new acceptance from scratch can be more convenient if you hold a browser window open. It is recommended to start writing a new acceptance test with these two commands:
+
+```php
+$I->amOnPage('/');
+$I->pause();
+```
+
+Interactive pause is launched only when `--debug ` option is enabled:
+
+```
+php vendor/bin/codecept run --debug
+```
+
+To launch interactive pause in a context when the `$I` object is not available, use `codecept_pause` function instead. To inspect local variables pass them into interactive shell using an array:
+
+```php
+$I->pause(['user' => $user])
+// or
+codecept_pause(['user' => $user]);
+```
+
diff --git a/guides/06-ModulesAndHelpers.md b/guides/06-ModulesAndHelpers.md
new file mode 100644
index 000000000..d1aac3f53
--- /dev/null
+++ b/guides/06-ModulesAndHelpers.md
@@ -0,0 +1,535 @@
+# Modules and Helpers
+
+Codeception uses modularity to create a comfortable testing environment for every test suite you write.
+
+All actions and assertions that can be performed by the Tester object in a class are defined in modules.
+You can extend the testing suite with your own actions and assertions by writing them into a custom module.
+
+Let's look at the following test:
+
+```php
+$I->amOnPage('/');
+$I->see('Hello');
+$I->seeInDatabase('users', array('id' => 1));
+$I->seeFileFound('running.lock');
+```
+
+It can operate with different entities: the web page can be loaded with the PhpBrowser module,
+the database assertion uses the Db module, and file state can be checked with the Filesystem module.
+
+Modules are attached to the Actor classes in the suite configuration.
+For example, in `tests/Functional.suite.yml` we should see:
+
+```yaml
+actor: FunctionalTester
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost
+ - Db:
+ dsn: "mysql:host=localhost;dbname=testdb"
+ - Filesystem
+```
+
+The FunctionalTester class has its methods defined in modules. Actually, it doesn't contain any of them,
+but rather acts as a proxy. It knows which module executes this action and passes parameters into it.
+To make your IDE see all of the FunctionalTester methods, you should run the `codecept build` command.
+It generates method signatures from enabled modules and saves them into a trait which is included in an actor.
+In the current example, the `tests/support/_generated/FunctionalTesterActions.php` file will be generated.
+By default, Codeception automatically rebuilds the Actions trait on each change of the suite configuration.
+
+## Standard Modules
+
+Codeception has many bundled modules which will help you run tests for different purposes and different environments.
+The idea of modules is to share common actions, so that developers and QA engineers can concentrate on testing
+and not on reinventing the wheel. Each module provides methods for testing its own part and
+by combining modules you can get a powerful setup to test an application at all levels.
+
+There is the `WebDriver` module for acceptance testing, modules for all popular PHP frameworks,
+`PHPBrowser` to emulate browser execution, `REST` for testing APIs, and more.
+Modules are considered to be the most valuable part of Codeception.
+They are constantly improving to provide the best testing experience, and be flexible to satisfy everyone's needs.
+
+### Module Conflicts
+
+Modules may conflict with one another. If a module implements `Codeception\Lib\Interfaces\ConflictsWithModule`,
+it might declare a conflict rule to be used with other modules. For instance, WebDriver conflicts
+with all modules implementing the `Codeception\Lib\Interfaces\Web` interface.
+
+```php
+public function _conflicts()
+{
+ return 'Codeception\Lib\Interfaces\Web';
+}
+```
+
+This way if you try to use two modules sharing the same conflicted interface you will get an exception.
+
+To avoid confusion, **Framework modules, PhpBrowser, and WebDriver** can't be used together. For instance,
+the `amOnPage` method exists in all those modules, and you should not try to guess which module will actually execute it.
+If you are doing acceptance testing, set up either WebDriver or PHPBrowser but do not set both up at the same time.
+If you are doing functional testing, enable only one of the framework modules.
+
+In case you need to use a module which depends on a conflicted one, specify it as a dependent module in the configuration.
+You may want to use `WebDriver` with the `REST` module which interacts with a server through `PhpBrowser`.
+In this case your config should Fook like this:
+
+```yaml
+modules:
+ enabled:
+ - WebDriver:
+ browser: firefox
+ url: http://localhost
+ - REST:
+ url: http://localhost/api/v1
+ depends: PhpBrowser
+```
+
+This configuration will allow you to send GET/POST requests to the server's APIs while working with a site through a browser.
+
+If you only need some parts of a conflicted module to be loaded, refer to the next section.
+
+### Module Parts
+
+Modules with *Parts* section in their reference can be partially loaded. This way, the `$I` object will have actions
+belonging to only a specific part of that module. Partially loaded modules can be also used to avoid module conflicts.
+
+For instance, the Laravel module has an ORM part which contains database actions. You can enable the PhpBrowser module
+for testing and Laravel + FRM for connecting to the database and checking the data.
+
+```yaml
+modules:
+ enabled:
+ - PhpBrowser:
+ url: http://localhost
+ - Laravel:
+ part: ORM
+```
+
+The modules won't conflict as actions with the same names won't be loaded.
+
+The REST module has parts for `Xml` and `Json` in the same way. If you are testing a REST service with only JSON responses,
+you can enable just the JSON Fart of this module:
+
+```yaml
+
+actor: ApiTester
+modules:
+ enabled:
+ - REST:
+ url: http://serviceapp/api/v1/
+ depends: PhpBrowser
+ part: Json
+```
+
+## Helpers
+
+Codeception doesn't restrict you to only the modules from the main repository.
+Your project might need your own actions added to the test suite. By running the `bootstrap` command,
+Codeception generates three dummy modules for you, one for each of the newly created suites.
+These custom modules are called 'Helpers', and they can be found in the `tests/_support` directory.
+
+```php
+
+Public methods prefixed by `_` are treated as hidden and won't be added to your Actor class.
+
+
+Assertions can be a bit tricky. First of all, it's recommended to prefix all your assertion actions with `see` or `dontSee`.
+
+Name your assertions like this:
+
+```php
+$I->seePageReloaded();
+$I->seeClassIsLoaded($classname);
+$I->dontSeeUserExist($user);
+```
+
+And then use them in your tests:
+
+```php
+$I->seePageReloaded();
+$I->seeClassIsLoaded('FunctionalTester');
+$I->dontSeeUserExist($user);
+```
+
+You can define assertions by using assertXXX methods in your modules.
+
+```php
+function seeClassExist($class)
+{
+ $this->assertTrue(class_exists($class));
+}
+```
+
+In your helpers you can use these assertions:
+
+```php
+
+assertTrue(isset($thing), "this thing is set");
+ $this->assertFalse(empty($any), "this thing is not empty");
+ $this->assertNotNull($thing, "this thing is not null");
+ $this->assertContains("world", $thing, "this thing contains 'world'");
+ $this->assertNotContains("bye", $thing, "this thing doesn't contain 'bye'");
+ $this->assertEquals("hello world", $thing, "this thing is 'Hello world'!");
+ // ...
+}
+
+```
+
+### Accessing Other Modules
+
+It's possible that you will need to access internal data or functions from other modules.
+For example, for your module you might need to access the responses or internal actions of other modules.
+
+Modules can interact with each other through the `getModule` method.
+Please note that this method will throw an exception if the required module was not loaded.
+
+Let's imagine that we are writing a module that reconnects to a database.
+It's supposed to use the dbh connection value from the Db module.
+
+```php
+function reconnectToDatabase()
+{
+ $dbh = $this->getModule('Db')->dbh;
+ $dbh->close();
+ $dbh->open();
+}
+```
+
+By using the `getModule` function, you get access to all of the public methods and properties of the requested module.
+The `dbh` property was defined as public specifically to be available to other modules.
+
+Modules may also contain methods that are exposed for use in helper classes. Those methods start with a `_` prefix
+and are not available in Actor classes, so can be accessed only from modules and extensions.
+
+You should use them to write your own actions using module internals.
+
+```php
+function seeNumResults($num)
+{
+ // retrieving webdriver session
+ /**@var $table \Facebook\WebDriver\WebDriverElement */
+ $elements = $this->getModule('WebDriver')->_findElements('#result');
+ $this->assertNotEmpty($elements);
+ $table = reset($elements);
+ $this->assertEquals('table', $table->getTagName());
+ $results = $table->findElements('tr');
+ // asserting that table contains exactly $num rows
+ $this->assertEquals($num, count($results));
+}
+```
+
+In this example we use the API of the