In
I went over test basics and how to setup an empty Codecept project (for lack of a better term).Now I'm going to talk about Codecept's approach to testing. Understanding this will be the key to structuring your actual tests.
Actors (Unit, Functional, Paid Soros Thugs, Whatever)
Tests are executed through the perspective of an actor. An actor has certain expectations:
- I want to get the contents of http://www.google.com
- I want to verify that there's a search box
- I want to check if
square(2) == 4
In terms of code, it might actually look like this:
$html = $I->wantContentFromUrl('http://www.google.com')
$I->wantToFindElement("input[title='Search']", $html)
$I->assertEquals(4, square(2), "unexpected value for square(2)");
Each test suite has a unique actor (e.g. FunctionalTester
).
Helpers
Helpers are Codecept modules -- they're classes that contain methods that an actor can use. Each test suite can define the helpers that get loaded into an actor.
In practice, Codecept will generate a
trait
with all the methods from all the enabled helpers, and proxy each method to the class actually implementing it. The actor class then uses thattrait
.
Cepts
This is the most basic test type. It's basically just a script:
I am on page 'http://www.google.com'
I see element 'input[title="Search"]'
I set value to 'input[title="Search"]', 'kaiser'
I click 'input[value="Google Search"]'
I get sent to 'https://www.google.com/search?q=kaiser'
(BTW, you can actually write Cepts like that.)
In this example, we're making the assumption
I am on page
saves the HTML somewhere where the other steps can refer to it.
If you need finer control, you can convert that to PHP:
<?php
$I = new AcceptenceTester($scenario);
$I->amOnPage('http://www.google.com');
$searchEle = 'input[title="Search"]';
$I->seeElement($searchEle);
$I->setValueTo($searchEle, 'kaiser');
$I->click('input[value="Google Search"]');
$I->getSentTo('https://www.google.com/search?q=kaiser');
?>
```
For very basic scenarios, write a Cept.
## Cests
If you need to group your steps together for better reusability, write a Cest:
```
<?php
// in file ExampleCest.php
class ExampleCest {
public function _fetchStep(FunctionalTester $I, $url) {
$I->startNewSession();
$I->amOnPage($url);
}
public function checkForSearchBox(FunctionalTester $I) {
$this->_fetchStep($I, 'http://www.google.com');
$I->seeElement('input[title="Search"]');
}
public function doSearch(FunctionalTester $I) {
$this->_fetchStep($I, 'http://www.google.com');
$I->setValueTo('input[title="Search"]', 'kaiser shahid');
$I->click('input[value="Google Search"]');
$I->getSentTo('https://www.google.com/search?q=kaiser');
}
}
?>
```
Cests let you collect multiple related scenarios together and allow reuse of common steps. Note that any function starting with `_` is not considered a test, so prefix any methods you don't want to automatically execute.
Cest classes must end in `Cest`, but they can be plain objects by default.
> Note that Codecept does dependency injection for Cests! `FunctionalTester $I` will make Codecept look for `FunctionalTester`, and if found, initialize it before passing it to the method it's about to execute. We'll get more into this in a future article.
## Unit Test
This is what you're probably used to:
```
<?php
// in ExampleTest
class ExampleTest extends \Codeception\Test\Unit {
public function testScenario1() {
$this->assertEquals(4, square(2), "unexpected result for square(2)");
}
}
?>
```
Note that the actor is no longer explicit -- its methods are automatically available to the class (probably through `__call`).
Unit test classes must end in `Test` and extend `\Codeception\Test\Unit`. Test scenarios must start with `test`.
## Conclusion
Each test suite has an actor. The actor uses 1 or more helpers to provide test writers assertions and other methods that are useful for that suite. Tests can be very simple scenarios (Cept), scenarios of varying complexity (Cest), or traditional unit tests.
Top comments (0)