commit | author | age
|
2207d6
|
1 |
# Advanced Usage |
W |
2 |
|
|
3 |
In this chapter we will cover some techniques and options that you can use to improve your testing experience |
|
4 |
and keep your project better organized. |
|
5 |
|
|
6 |
## Cest Classes |
|
7 |
|
|
8 |
If you want to get a class-like structure for your Cepts, you can use the Cest format instead of plain PHP. |
|
9 |
It is very simple and is fully compatible with Cept scenarios. It means that if you feel that your test is long enough |
|
10 |
and you want to split it, you can easily move it into classes. |
|
11 |
|
|
12 |
You can create a Cest file by running the command: |
|
13 |
|
|
14 |
```bash |
|
15 |
$ php vendor/bin/codecept generate:cest suitename CestName |
|
16 |
``` |
|
17 |
|
|
18 |
The generated file will look like this: |
|
19 |
|
|
20 |
```php |
|
21 |
<?php |
|
22 |
class BasicCest |
|
23 |
{ |
|
24 |
public function _before(\AcceptanceTester $I) |
|
25 |
{ |
|
26 |
} |
|
27 |
|
|
28 |
public function _after(\AcceptanceTester $I) |
|
29 |
{ |
|
30 |
} |
|
31 |
|
|
32 |
// tests |
|
33 |
public function tryToTest(\AcceptanceTester $I) |
|
34 |
{ |
|
35 |
} |
|
36 |
} |
|
37 |
``` |
|
38 |
|
|
39 |
**Each public method of Cest (except those starting with `_`) will be executed as a test** |
|
40 |
and will receive an instance of the Actor class as the first parameter and the `$scenario` variable as the second one. |
|
41 |
|
|
42 |
In `_before` and `_after` methods you can use common setups and teardowns for the tests in the class. |
|
43 |
|
|
44 |
As you see, we are passing the Actor object into `tryToTest` method. This allows us to write scenarios the way we did before: |
|
45 |
|
|
46 |
```php |
|
47 |
<?php |
|
48 |
class BasicCest |
|
49 |
{ |
|
50 |
// test |
|
51 |
public function tryToTest(\AcceptanceTester $I) |
|
52 |
{ |
|
53 |
$I->amOnPage('/'); |
|
54 |
$I->click('Login'); |
|
55 |
$I->fillField('username', 'john'); |
|
56 |
$I->fillField('password', 'coltrane'); |
|
57 |
$I->click('Enter'); |
|
58 |
$I->see('Hello, John'); |
|
59 |
$I->seeInCurrentUrl('/account'); |
|
60 |
} |
|
61 |
} |
|
62 |
``` |
|
63 |
|
|
64 |
As you see, Cest classes have no parents. |
|
65 |
This is done intentionally. It allows you to extend your classes with common behaviors and workarounds |
|
66 |
that may be used in child classes. But don't forget to make these methods `protected` so they won't be executed as tests. |
|
67 |
|
|
68 |
Cest format also can contain hooks based on test results: |
|
69 |
|
|
70 |
* `_failed` will be executed on failed test |
|
71 |
* `_passed` will be executed on passed test |
|
72 |
|
|
73 |
```php |
|
74 |
<?php |
|
75 |
public function _failed(\AcceptanceTester $I) |
|
76 |
{ |
|
77 |
// will be executed on test failure |
|
78 |
} |
|
79 |
|
|
80 |
public function _passed(\AcceptanceTester $I) |
|
81 |
{ |
|
82 |
// will be executed when test is successful |
|
83 |
} |
|
84 |
``` |
|
85 |
|
|
86 |
## Dependency Injection |
|
87 |
|
|
88 |
Codeception supports simple dependency injection for Cest and \Codeception\TestCase\Test classes. |
|
89 |
It means that you can specify which classes you need as parameters of the special `_inject()` method, |
|
90 |
and Codeception will automatically create the respective objects and invoke this method, |
|
91 |
passing all dependencies as arguments. This may be useful when working with Helpers. Here's an example for Cest: |
|
92 |
|
|
93 |
```php |
|
94 |
<?php |
|
95 |
class SignUpCest |
|
96 |
{ |
|
97 |
/** |
|
98 |
* @var Helper\SignUp |
|
99 |
*/ |
|
100 |
protected $signUp; |
|
101 |
|
|
102 |
/** |
|
103 |
* @var Helper\NavBarHelper |
|
104 |
*/ |
|
105 |
protected $navBar; |
|
106 |
|
|
107 |
protected function _inject(\Helper\SignUp $signUp, \Helper\NavBar $navBar) |
|
108 |
{ |
|
109 |
$this->signUp = $signUp; |
|
110 |
$this->navBar = $navBar; |
|
111 |
} |
|
112 |
|
|
113 |
public function signUp(\AcceptanceTester $I) |
|
114 |
{ |
|
115 |
$this->navBar->click('Sign up'); |
|
116 |
$this->signUp->register([ |
|
117 |
'first_name' => 'Joe', |
|
118 |
'last_name' => 'Jones', |
|
119 |
'email' => 'joe@jones.com', |
|
120 |
'password' => '1234', |
|
121 |
'password_confirmation' => '1234' |
|
122 |
]); |
|
123 |
} |
|
124 |
} |
|
125 |
``` |
|
126 |
|
|
127 |
And for Test classes: |
|
128 |
|
|
129 |
```php |
|
130 |
<?php |
|
131 |
class MathTest extends \Codeception\TestCase\Test |
|
132 |
{ |
|
133 |
/** |
|
134 |
* @var \UnitTester |
|
135 |
*/ |
|
136 |
protected $tester; |
|
137 |
|
|
138 |
/** |
|
139 |
* @var Helper\Math |
|
140 |
*/ |
|
141 |
protected $math; |
|
142 |
|
|
143 |
protected function _inject(\Helper\Math $math) |
|
144 |
{ |
|
145 |
$this->math = $math; |
|
146 |
} |
|
147 |
|
|
148 |
public function testAll() |
|
149 |
{ |
|
150 |
$this->assertEquals(3, $this->math->add(1, 2)); |
|
151 |
$this->assertEquals(1, $this->math->subtract(3, 2)); |
|
152 |
} |
|
153 |
} |
|
154 |
``` |
|
155 |
|
|
156 |
However, Dependency Injection is not limited to this. It allows you to **inject any class**, |
|
157 |
which can be constructed with arguments known to Codeception. |
|
158 |
|
|
159 |
In order to make auto-wiring work, you will need to implement the `_inject()` method with the list of desired arguments. |
|
160 |
It is important to specify the type of arguments, so Codeception can guess which objects are expected to be received. |
|
161 |
The `_inject()` will only be invoked once, just after creation of the TestCase object (either Cest or Test). |
|
162 |
Dependency Injection will also work in a similar manner for Helper and Actor classes. |
|
163 |
|
|
164 |
Each test of a Cest class can declare its own dependencies and receive them from method arguments: |
|
165 |
|
|
166 |
```php |
|
167 |
<?php |
|
168 |
class UserCest |
|
169 |
{ |
|
170 |
function updateUser(\Helper\User $u, \AcceptanceTester $I, \Page\User $userPage) |
|
171 |
{ |
|
172 |
$user = $u->createDummyUser(); |
|
173 |
$userPage->login($user->getName(), $user->getPassword()); |
|
174 |
$userPage->updateProfile(['name' => 'Bill']); |
|
175 |
$I->see('Profile was saved'); |
|
176 |
$I->see('Profile of Bill','h1'); |
|
177 |
} |
|
178 |
} |
|
179 |
``` |
|
180 |
|
|
181 |
Moreover, Codeception can resolve dependencies recursively (when `A` depends on `B`, and `B` depends on `C` etc.) |
|
182 |
and handle parameters of primitive types with default values (like `$param = 'default'`). |
|
183 |
Of course, you are not allowed to have *cyclic dependencies*. |
|
184 |
|
|
185 |
## Example Annotation |
|
186 |
|
|
187 |
What if you want to execute the same test scenario with different data? In this case you can inject examples |
|
188 |
as `\Codeception\Example` instances. |
|
189 |
Data is defined via the `@example` annotation, using JSON or Doctrine-style notation (limited to a single line). Doctrine-style: |
|
190 |
|
|
191 |
```php |
|
192 |
<?php |
|
193 |
class EndpointCest |
|
194 |
{ |
|
195 |
/** |
|
196 |
* @example ["/api/", 200] |
|
197 |
* @example ["/api/protected", 401] |
|
198 |
* @example ["/api/not-found-url", 404] |
|
199 |
* @example ["/api/faulty", 500] |
|
200 |
*/ |
|
201 |
public function checkEndpoints(ApiTester $I, \Codeception\Example $example) |
|
202 |
{ |
|
203 |
$I->sendGET($example[0]); |
|
204 |
$I->seeResponseCodeIs($example[1]); |
|
205 |
} |
|
206 |
} |
|
207 |
``` |
|
208 |
|
|
209 |
JSON: |
|
210 |
|
|
211 |
```php |
|
212 |
<?php |
|
213 |
class PageCest |
|
214 |
{ |
|
215 |
/** |
|
216 |
* @example { "url": "/", "title": "Welcome" } |
|
217 |
* @example { "url": "/info", "title": "Info" } |
|
218 |
* @example { "url": "/about", "title": "About Us" } |
|
219 |
* @example { "url": "/contact", "title": "Contact Us" } |
|
220 |
*/ |
|
221 |
public function staticPages(AcceptanceTester $I, \Codeception\Example $example) |
|
222 |
{ |
|
223 |
$I->amOnPage($example['url']); |
|
224 |
$I->see($example['title'], 'h1'); |
|
225 |
$I->seeInTitle($example['title']); |
|
226 |
} |
|
227 |
} |
|
228 |
``` |
|
229 |
|
|
230 |
<div class="alert alert-info"> |
|
231 |
If you use JSON notation please keep in mind that all string keys |
|
232 |
and values should be enclosed in double quotes (`"`) according to JSON standard. |
|
233 |
</div> |
|
234 |
|
|
235 |
Key-value data in Doctrine-style annotation syntax: |
|
236 |
|
|
237 |
```php |
|
238 |
<?php |
|
239 |
class PageCest |
|
240 |
{ |
|
241 |
/** |
|
242 |
* @example(url="/", title="Welcome") |
|
243 |
* @example(url="/info", title="Info") |
|
244 |
* @example(url="/about", title="About Us") |
|
245 |
* @example(url="/contact", title="Contact Us") |
|
246 |
*/ |
|
247 |
public function staticPages(AcceptanceTester $I, \Codeception\Example $example) |
|
248 |
{ |
|
249 |
$I->amOnPage($example['url']); |
|
250 |
$I->see($example['title'], 'h1'); |
|
251 |
$I->seeInTitle($example['title']); |
|
252 |
} |
|
253 |
} |
|
254 |
``` |
|
255 |
|
|
256 |
## DataProvider Annotations |
|
257 |
|
|
258 |
You can also use the `@dataProvider` annotation for creating dynamic examples for [Cest classes](#Cest-Classes), using a **protected method** for providing example data: |
|
259 |
|
|
260 |
```php |
|
261 |
<?php |
|
262 |
class PageCest |
|
263 |
{ |
|
264 |
/** |
|
265 |
* @dataProvider pageProvider |
|
266 |
*/ |
|
267 |
public function staticPages(AcceptanceTester $I, \Codeception\Example $example) |
|
268 |
{ |
|
269 |
$I->amOnPage($example['url']); |
|
270 |
$I->see($example['title'], 'h1'); |
|
271 |
$I->seeInTitle($example['title']); |
|
272 |
} |
|
273 |
|
|
274 |
/** |
|
275 |
* @return array |
|
276 |
*/ |
|
277 |
protected function pageProvider() // alternatively, if you want the function to be public, be sure to prefix it with `_` |
|
278 |
{ |
|
279 |
return [ |
|
280 |
['url'=>"/", 'title'=>"Welcome"], |
|
281 |
['url'=>"/info", 'title'=>"Info"], |
|
282 |
['url'=>"/about", 'title'=>"About Us"], |
|
283 |
['url'=>"/contact", 'title'=>"Contact Us"] |
|
284 |
]; |
|
285 |
} |
|
286 |
} |
|
287 |
``` |
|
288 |
|
|
289 |
`@dataprovider` annotation is also available for [unit tests](https://codeception.com/docs/05-UnitTests), in this case the data provider **method must be public**. |
|
290 |
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). |
|
291 |
|
|
292 |
## Before/After Annotations |
|
293 |
|
|
294 |
You can control execution flow with `@before` and `@after` annotations. You may move common actions |
|
295 |
into protected (non-test) methods and invoke them before or after the test method by putting them into annotations. |
|
296 |
It is possible to invoke several methods by using more than one `@before` or `@after` annotation. |
|
297 |
Methods are invoked in order from top to bottom. |
|
298 |
|
|
299 |
```php |
|
300 |
<?php |
|
301 |
class ModeratorCest { |
|
302 |
|
|
303 |
protected function login(AcceptanceTester $I) |
|
304 |
{ |
|
305 |
$I->amOnPage('/login'); |
|
306 |
$I->fillField('Username', 'miles'); |
|
307 |
$I->fillField('Password', 'davis'); |
|
308 |
$I->click('Login'); |
|
309 |
} |
|
310 |
|
|
311 |
/** |
|
312 |
* @before login |
|
313 |
*/ |
|
314 |
public function banUser(AcceptanceTester $I) |
|
315 |
{ |
|
316 |
$I->amOnPage('/users/charlie-parker'); |
|
317 |
$I->see('Ban', '.button'); |
|
318 |
$I->click('Ban'); |
|
319 |
} |
|
320 |
|
|
321 |
/** |
|
322 |
* @before login |
|
323 |
* @before cleanup |
|
324 |
* @after logout |
|
325 |
* @after close |
|
326 |
*/ |
|
327 |
public function addUser(AcceptanceTester $I) |
|
328 |
{ |
|
329 |
$I->amOnPage('/users/charlie-parker'); |
|
330 |
$I->see('Ban', '.button'); |
|
331 |
$I->click('Ban'); |
|
332 |
} |
|
333 |
} |
|
334 |
``` |
|
335 |
|
|
336 |
## Environments |
|
337 |
|
|
338 |
For cases where you need to run tests with different configurations you can define different config environments. |
|
339 |
The most typical use cases are running acceptance tests in different browsers, |
|
340 |
or running database tests using different database engines. |
|
341 |
|
|
342 |
Let's demonstrate the usage of environments for the browsers case. |
|
343 |
|
|
344 |
We need to add some new lines to `acceptance.suite.yml`: |
|
345 |
|
|
346 |
``` yaml |
|
347 |
actor: AcceptanceTester |
|
348 |
modules: |
|
349 |
enabled: |
|
350 |
- WebDriver |
|
351 |
- \Helper\Acceptance |
|
352 |
config: |
|
353 |
WebDriver: |
|
354 |
url: 'http://127.0.0.1:8000/' |
|
355 |
browser: 'firefox' |
|
356 |
|
|
357 |
env: |
|
358 |
phantom: |
|
359 |
modules: |
|
360 |
config: |
|
361 |
WebDriver: |
|
362 |
browser: 'phantomjs' |
|
363 |
|
|
364 |
chrome: |
|
365 |
modules: |
|
366 |
config: |
|
367 |
WebDriver: |
|
368 |
browser: 'chrome' |
|
369 |
|
|
370 |
firefox: |
|
371 |
# nothing changed |
|
372 |
``` |
|
373 |
|
|
374 |
Basically you can define different environments inside the `env` root, name them (`phantom`, `chrome` etc.), |
|
375 |
and then redefine any configuration parameters that were set before. |
|
376 |
|
|
377 |
You can also define environments in separate configuration files placed in the directory specified by the `envs` option in |
|
378 |
the `paths` configuration: |
|
379 |
|
|
380 |
```yaml |
|
381 |
paths: |
|
382 |
envs: tests/_envs |
|
383 |
``` |
|
384 |
|
|
385 |
The names of these files are used as environments names |
|
386 |
(e.g. `chrome.yml` or `chrome.dist.yml` for an environment named `chrome`). |
|
387 |
You can generate a new file with this environment configuration by using the `generate:environment` command: |
|
388 |
|
|
389 |
```bash |
|
390 |
$ php vendor/bin/codecept g:env chrome |
|
391 |
``` |
|
392 |
|
|
393 |
In that file you can specify just the options you wish to override: |
|
394 |
|
|
395 |
```yaml |
|
396 |
modules: |
|
397 |
config: |
|
398 |
WebDriver: |
|
399 |
browser: 'chrome' |
|
400 |
``` |
|
401 |
|
|
402 |
The environment configuration files are merged into the main configuration before the suite configuration is merged. |
|
403 |
|
|
404 |
You can easily switch between those configs by running tests with `--env` option. |
|
405 |
To run the tests only for PhantomJS you just need to pass `--env phantom` as an option: |
|
406 |
|
|
407 |
```bash |
|
408 |
$ php vendor/bin/codecept run acceptance --env phantom |
|
409 |
``` |
|
410 |
|
|
411 |
To run the tests in all 3 browsers, list all the environments: |
|
412 |
|
|
413 |
```bash |
|
414 |
$ php vendor/bin/codecept run acceptance --env phantom --env chrome --env firefox |
|
415 |
``` |
|
416 |
|
|
417 |
The tests will be executed 3 times, each time in a different browser. |
|
418 |
|
|
419 |
It's also possible to merge multiple environments into a single configuration by separating them with a comma: |
|
420 |
|
|
421 |
```bash |
|
422 |
$ php vendor/bin/codecept run acceptance --env dev,phantom --env dev,chrome --env dev,firefox |
|
423 |
``` |
|
424 |
|
|
425 |
The configuration is merged in the order given. |
|
426 |
This way you can easily create multiple combinations of your environment configurations. |
|
427 |
|
|
428 |
Depending on the environment, you may choose which tests are to be executed. |
|
429 |
For example, you might need some tests to be executed in Firefox only, and some tests in Chrome only. |
|
430 |
|
|
431 |
The desired environments can be specified with the `@env` annotation for tests in Test and Cest formats: |
|
432 |
|
|
433 |
```php |
|
434 |
<?php |
|
435 |
class UserCest |
|
436 |
{ |
|
437 |
/** |
|
438 |
* This test will be executed only in 'firefox' and 'phantom' environments |
|
439 |
* |
|
440 |
* @env firefox |
|
441 |
* @env phantom |
|
442 |
*/ |
|
443 |
public function webkitOnlyTest(AcceptanceTester $I) |
|
444 |
{ |
|
445 |
// I do something |
|
446 |
} |
|
447 |
} |
|
448 |
``` |
|
449 |
|
|
450 |
For Cept you should use simple comments: |
|
451 |
|
|
452 |
```php |
|
453 |
<?php |
|
454 |
// @env firefox |
|
455 |
// @env phantom |
|
456 |
``` |
|
457 |
|
|
458 |
This way you can easily control which tests will be executed for each environment. |
|
459 |
|
|
460 |
### Current values |
|
461 |
|
|
462 |
Sometimes you may need to change the test behavior in real time. |
|
463 |
For instance, the behavior of the same test may differ in Firefox and in Chrome. |
|
464 |
In runtime we can retrieve the current environment name, test name, |
|
465 |
or list of enabled modules by calling the `$scenario->current()` method. |
|
466 |
|
|
467 |
```php |
|
468 |
<?php |
|
469 |
// retrieve current environment |
|
470 |
$scenario->current('env'); |
|
471 |
|
|
472 |
// list of all enabled modules |
|
473 |
$scenario->current('modules'); |
|
474 |
|
|
475 |
// test name |
|
476 |
$scenario->current('name'); |
|
477 |
|
|
478 |
// browser name (if WebDriver module enabled) |
|
479 |
$scenario->current('browser'); |
|
480 |
|
|
481 |
// capabilities (if WebDriver module enabled) |
|
482 |
$scenario->current('capabilities'); |
|
483 |
``` |
|
484 |
|
|
485 |
You can access `\Codeception\Scenario` in the Cept and Cest formats. |
|
486 |
In Cept, the `$scenario` variable is available by default, |
|
487 |
while in Cest you should retrieve it through dependency injection: |
|
488 |
|
|
489 |
```php |
|
490 |
<?php |
|
491 |
public function myTest(\AcceptanceTester $I, \Codeception\Scenario $scenario) |
|
492 |
{ |
|
493 |
if ($scenario->current('browser') == 'phantomjs') { |
|
494 |
// emulate popups for PhantomJS |
|
495 |
$I->executeScript('window.alert = function(){return true;}'); |
|
496 |
} |
|
497 |
} |
|
498 |
``` |
|
499 |
|
|
500 |
`Codeception\Scenario` is also available in Actor classes and StepObjects. You can access it with `$this->getScenario()`. |
|
501 |
|
|
502 |
### Dependencies |
|
503 |
|
|
504 |
With the `@depends` annotation you can specify a test that should be passed before the current one. |
|
505 |
If that test fails, the current test will be skipped. You should pass the method name of the test you are relying on. |
|
506 |
|
|
507 |
```php |
|
508 |
<?php |
|
509 |
class ModeratorCest { |
|
510 |
|
|
511 |
public function login(AcceptanceTester $I) |
|
512 |
{ |
|
513 |
// logs moderator in |
|
514 |
} |
|
515 |
|
|
516 |
/** |
|
517 |
* @depends login |
|
518 |
*/ |
|
519 |
public function banUser(AcceptanceTester $I) |
|
520 |
{ |
|
521 |
// bans user |
|
522 |
} |
|
523 |
} |
|
524 |
``` |
|
525 |
|
|
526 |
`@depends` applies to the `Cest` and `Codeception\Test\Unit` formats. Dependencies can be set across different classes. |
|
527 |
To specify a dependent test from another file you should provide a *test signature*. |
|
528 |
Normally, the test signature matches the `className:methodName` format. |
|
529 |
But to get the exact test signature just run the test with the `--steps` option to see it: |
|
530 |
|
|
531 |
``` |
|
532 |
Signature: ModeratorCest:login` |
|
533 |
``` |
|
534 |
|
|
535 |
Codeception reorders tests so dependent tests will always be executed before the tests that rely on them. |
|
536 |
|
|
537 |
### Shuffle |
|
538 |
|
|
539 |
By default Codeception runs tests in alphabetic order. |
|
540 |
To ensure that tests are not depending on each other (unless explicitly declared via `@depends`) you can enable `shuffle` option. |
|
541 |
|
|
542 |
```yaml |
|
543 |
# inside codeception.yml |
|
544 |
settings: |
|
545 |
shuffle: true |
|
546 |
``` |
|
547 |
|
|
548 |
Alternatively, you may run tests in shuffle without changing the config: |
|
549 |
|
|
550 |
``` |
|
551 |
codecept run -o "settings: shuffle: true" |
|
552 |
``` |
|
553 |
|
|
554 |
|
|
555 |
Tests will be randomly reordered on each run. When tests executed in shuffle mode a seed value will be printed. |
|
556 |
Copy this seed value from output to be able to rerun tests in the same order. |
|
557 |
|
|
558 |
``` |
|
559 |
$ codecept run |
|
560 |
Codeception PHP Testing Framework v2.4.5 |
|
561 |
Powered by PHPUnit 5.7.27 by Sebastian Bergmann and contributors. |
|
562 |
[Seed] 1872290562 |
|
563 |
``` |
|
564 |
|
|
565 |
Pass the copied seed into `--seed` option: |
|
566 |
|
|
567 |
``` |
|
568 |
codecept run --seed 1872290562 |
|
569 |
``` |
|
570 |
|
|
571 |
|
|
572 |
|
|
573 |
## Interactive Console |
|
574 |
|
|
575 |
The interactive console was added to try Codeception commands before executing them inside a test. |
|
576 |
|
|
577 |
![console](http://codeception.com/images/console.png) |
|
578 |
|
|
579 |
You can run the console with the following command: |
|
580 |
|
|
581 |
``` bash |
|
582 |
$ php vendor/bin/codecept console suitename |
|
583 |
``` |
|
584 |
|
|
585 |
Now you can execute all the commands of an appropriate Actor class and see the results immediately. |
|
586 |
This is especially useful when used with the `WebDriver` module. It always takes too long to launch Selenium |
|
587 |
and the browser for tests. But with the console you can try different selectors, and different commands, |
|
588 |
and then write a test that should pass when executed. |
|
589 |
|
|
590 |
And a special hint: show your boss how you can easily manipulate web pages with the console and Selenium. |
|
591 |
It will be easy to convince them to automate this step and introduce acceptance testing to the project. |
|
592 |
|
|
593 |
## Running from different folders |
|
594 |
|
|
595 |
If you have several projects with Codeception tests, you can use a single `codecept` file to run all of your tests. |
|
596 |
You can pass the `-c` option to any Codeception command (except `bootstrap`), to execute Codeception in another directory: |
|
597 |
|
|
598 |
```bash |
|
599 |
$ php vendor/bin/codecept run -c ~/projects/ecommerce/ |
|
600 |
$ php vendor/bin/codecept run -c ~/projects/drupal/ |
|
601 |
$ php vendor/bin/codecept generate:cept acceptance CreateArticle -c ~/projects/drupal/ |
|
602 |
``` |
|
603 |
|
|
604 |
To create a project in directory different from the current one, just provide its path as a parameter: |
|
605 |
|
|
606 |
```bash |
|
607 |
$ php vendor/bin/codecept bootstrap ~/projects/drupal/ |
|
608 |
``` |
|
609 |
|
|
610 |
Also, the `-c` option allows you to specify another config file to be used. |
|
611 |
Thus, you can have several `codeception.yml` files for your test suite (e.g. to to specify different environments |
|
612 |
and settings). Just pass the `.yml` filename as the `-c` parameter to execute tests with specific config settings. |
|
613 |
|
|
614 |
## Groups |
|
615 |
|
|
616 |
There are several ways to execute a bunch of tests. You can run tests from a specific directory: |
|
617 |
|
|
618 |
```bash |
|
619 |
$ php vendor/bin/codecept run tests/acceptance/admin |
|
620 |
``` |
|
621 |
|
|
622 |
You can execute one (or several) specific groups of tests: |
|
623 |
|
|
624 |
```bash |
|
625 |
$ php vendor/bin/codecept run -g admin -g editor |
|
626 |
``` |
|
627 |
|
|
628 |
The concept of groups was taken from PHPUnit and behave in the same way. |
|
629 |
|
|
630 |
For Test and Cest files you can use the `@group` annotation to add a test to a group. |
|
631 |
|
|
632 |
```php |
|
633 |
<?php |
|
634 |
/** |
|
635 |
* @group admin |
|
636 |
*/ |
|
637 |
public function testAdminUser() |
|
638 |
{ |
|
639 |
} |
|
640 |
``` |
|
641 |
|
|
642 |
For Cept files, use pseudo-annotations in comments: |
|
643 |
|
|
644 |
```php |
|
645 |
<?php |
|
646 |
// @group admin |
|
647 |
// @group editor |
|
648 |
$I = new AcceptanceTester($scenario); |
|
649 |
$I->wantToTest('admin area'); |
|
650 |
``` |
|
651 |
|
|
652 |
For `.feature`-files (Gherkin) use tags: |
|
653 |
|
|
654 |
```gherkin |
|
655 |
@admin @editor |
|
656 |
Feature: Admin area |
|
657 |
``` |
|
658 |
|
|
659 |
### Group Files |
|
660 |
|
|
661 |
Groups can be defined in global or suite configuration files. |
|
662 |
Tests for groups can be specified as an array of file names or directories containing them: |
|
663 |
|
|
664 |
```yaml |
|
665 |
groups: |
|
666 |
# add 2 tests to db group |
|
667 |
db: [tests/unit/PersistTest.php, tests/unit/DataTest.php] |
|
668 |
|
|
669 |
# add all tests from a directory to api group |
|
670 |
api: [tests/functional/api] |
|
671 |
``` |
|
672 |
|
|
673 |
A list of tests for the group can be passed from a Group file. It should be defined in plain text with test names on separate lines: |
|
674 |
|
|
675 |
```bash |
|
676 |
tests/unit/DbTest.php |
|
677 |
tests/unit/UserTest.php:create |
|
678 |
tests/unit/UserTest.php:update |
|
679 |
``` |
|
680 |
A group file can be included by its relative filename: |
|
681 |
|
|
682 |
```yaml |
|
683 |
groups: |
|
684 |
# requiring a group file |
|
685 |
slow: tests/_data/slow.txt |
|
686 |
``` |
|
687 |
|
|
688 |
You can create group files manually or generate them from third party applications. |
|
689 |
For example, you can write a script that updates the slow group by taking the slowest tests from xml report. |
|
690 |
|
|
691 |
You can even specify patterns for loading multiple group files with a single definition: |
|
692 |
|
|
693 |
```yaml |
|
694 |
groups: |
|
695 |
p*: tests/_data/p* |
|
696 |
``` |
|
697 |
|
|
698 |
This will load all found `p*` files in `tests/_data` as groups. Group names will be as follows p1,p2,...,pN. |
|
699 |
|
|
700 |
## Formats |
|
701 |
|
|
702 |
In addition to the standard test formats (Cept, Cest, Unit, Gherkin) you can implement your own format classes to customise your test execution. |
|
703 |
Specify these in your suite configuration: |
|
704 |
|
|
705 |
```yaml |
|
706 |
formats: |
|
707 |
- \My\Namespace\MyFormat |
|
708 |
``` |
|
709 |
|
|
710 |
Then define a class which implements the LoaderInterface |
|
711 |
|
|
712 |
```php |
|
713 |
namespace My\Namespace; |
|
714 |
|
|
715 |
class MyFormat implements \Codeception\Test\Loader\LoaderInterface |
|
716 |
{ |
|
717 |
protected $tests; |
|
718 |
|
|
719 |
protected $settings; |
|
720 |
|
|
721 |
public function __construct($settings = []) |
|
722 |
{ |
|
723 |
//These are the suite settings |
|
724 |
$this->settings = $settings; |
|
725 |
} |
|
726 |
|
|
727 |
public function loadTests($filename) |
|
728 |
{ |
|
729 |
//Load file and create tests |
|
730 |
} |
|
731 |
|
|
732 |
public function getTests() |
|
733 |
{ |
|
734 |
return $this->tests; |
|
735 |
} |
|
736 |
|
|
737 |
public function getPattern() |
|
738 |
{ |
|
739 |
return '~Myformat\.php$~'; |
|
740 |
} |
|
741 |
} |
|
742 |
``` |
|
743 |
|
|
744 |
## Shell auto-completion |
|
745 |
|
|
746 |
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): |
|
747 |
```bash |
|
748 |
# BASH ~4.x, ZSH |
|
749 |
source <([codecept location] _completion --generate-hook --program codecept --use-vendor-bin) |
|
750 |
|
|
751 |
# BASH ~3.x, ZSH |
|
752 |
[codecept location] _completion --generate-hook --program codecept --use-vendor-bin | source /dev/stdin |
|
753 |
|
|
754 |
# BASH (any version) |
|
755 |
eval $([codecept location] _completion --generate-hook --program codecept --use-vendor-bin) |
|
756 |
``` |
|
757 |
|
|
758 |
### Explanation |
|
759 |
|
|
760 |
By using the above code in your shell, Codeception will try to autocomplete the following: |
|
761 |
* Commands |
|
762 |
* Suites |
|
763 |
* Test paths |
|
764 |
|
|
765 |
Usage of `-use-vendor-bin` is optional. This option will work for most Codeception projects, where Codeception is located in your `vendor/bin` folder. |
|
766 |
But in case you are using a global Codeception installation for example, you wouldn't use this option. |
|
767 |
|
|
768 |
Note that with the `-use-vendor-bin` option, your commands will be completed using the Codeception binary located in your project's root. |
|
769 |
Without the option, it will use whatever Codeception binary you originally used to generate the completion script ('codecept location' in the above examples) |
|
770 |
|
|
771 |
## Conclusion |
|
772 |
|
|
773 |
Codeception is a framework which may look simple at first glance |
|
774 |
but it allows you to build powerful tests with a single API, refactor them, |
|
775 |
and write them faster using the interactive console. Codeception tests can be easily organized in groups or Cest classes. |