Skip to content

Commit 331e90a

Browse files
author
davert
committed
ragazzos post added
1 parent f3cd1b6 commit 331e90a

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
layout: post
3+
title: "Specification and Testing (by @Ragazzo)"
4+
date: 2013-05-06 22:03:50
5+
---
6+
7+
*This is guest post by [@Ragazzo](https://github.com/Ragazzo). He uses Behat as well as Codeception for making his project better. He was often asked to do a **comparison between Codeception, Behat, and PhpUnit**. In this post he explains the commons and different parts of this products.*
8+
9+
In nowadays almost everyone knows how it is important to have stable and tested application. It is very difficult to create good application without involving different specific tools in your project. It is very important to develop your application through testing, according to TDD principle. There are different ways to write tests in PHP:
10+
11+
* Classical unit-tests with PhpUnit;
12+
* Functional (integration / end-to-end) tests with PhpUnit
13+
* Functional web tests with Codeception / Behat+Mink
14+
* Acceptance web tests with Codeception / Behat+Mink.
15+
16+
### My vision of BDD.
17+
18+
Main difference between usual functional and acceptance tests is that in acceptance tests you can not manipulate directly with some "underground" application code. All you can do is just interact with things that was given to you by application. In functional tests you can interact with some "underground" application code, proceed some checks and conditions that can involve application parts not available for end-user.
19+
20+
If we are talking about "classical" functional tests also known as "end-to-end" or "integration" tests then simple example can be when you have to test some behavior of 2-3 components together, like logging, writing configs and etc. For "classical" (but not web) functional tests **I prefer to use Behat** by itself. And I have some reasons for that.
21+
22+
In ideal, all development process must be the sequence of this: **DDD->BDD->TDD**.
23+
24+
Of course it is a matter of time, thats why DDD is not applied on every project, but BDD is a thing that can be easily applied to projects and won't waste your time. Main reason is that you start to develop your project from "how it must behave" and not from "what concrete components it must include in particular".
25+
26+
It can be said that you write your thoughts about how your application must behave and this help you to build not simply a couple of classes powered by unit-tests, but just a application with good design based on application behavior. **Behat** is very powerful tool, but it has some "common pitfalls" that maybe looks weird to the user:
27+
28+
* It could be said that it is a "feature driven development". Thats why it is not so easy to use *subcontexts* in Behat. For example, if you have 30-40 tests it could be hard to maintain them, because of the same PhpDoc definitions for matching methods.
29+
* If you use Behat+Mink for functional and acceptance tests, it also requires from you a good knowledge of Mink's internals to make your specific methods to interact with a page.
30+
31+
Lets see the example on how you can determine what components you need in your application in a "BDD" way.
32+
Here we are creating dummy application for managing football clubs. Lets write some 2-3 scenarios in **Gherkin**:
33+
34+
{% highlight gherkin %}
35+
#football_clubs.feature
36+
37+
Feature: football_clubs
38+
As a football club owner
39+
I want to perform different actions with it.
40+
41+
Scenario: transfer player to the club
42+
Given I have a football club "MyClub"
43+
Given Football club budget is 100 mln. dollars
44+
Given Football player "GoodSkilledPlayer" costs 35 mln. dollars
45+
When I try to buy this player
46+
And He see is available for transfer
47+
Then I sign player contract with 10 mln. dollars salary
48+
And I see player club is now "MyClub"
49+
50+
Scenario: get list of injured players
51+
Given I have a football club "MyClub"
52+
When I get a list of injured players
53+
Then I see players in list:
54+
"""
55+
FirstFootballPlayer
56+
SecondFootballPlayer
57+
"""
58+
And I dont see players in list:
59+
"""
60+
ThirdFootballPlayer
61+
"""
62+
{% endhighlight %}
63+
64+
Thats all. We just wrote some thoughts on how an application should behave. From here we know what exactly we need: "Football Player" object, "Football Club" object, "Transfers Market" object. **If you know how they must behave you do not need to think for hours on what unit-test you need to write, and whether they are really needed in the component behavior.**
65+
66+
Lets see another example of functional tests with Behat, for example we need to test config files of our system. Feature for that can be like this:
67+
68+
{% highlight gherkin %}
69+
#config.feature
70+
Feature:
71+
In order to proceed config files for MyModule
72+
As a system root user i should be able
73+
to write correct info in files
74+
75+
Scenario: write some users "context" info
76+
Given I have users in system:
77+
| username | email |
78+
| first | first@example.com |
79+
| second | second@example.com |
80+
When I dump users info to config file
81+
Then I should see
82+
"""
83+
#users
84+
username=first
85+
email=first@example.com
86+
87+
username=second
88+
email=second@example.com
89+
"""
90+
{% endhighlight %}
91+
92+
As you see it is easy to read and also easy to understand. Thats why I prefer ```Behat``` for "classic" functional tests against usage of PhpUnit to test behavior of 2-3 components.
93+
94+
## Ways of Writing Acceptance Tests
95+
96+
Now lets talk about functional and acceptance tests for web. Now we know difference between acceptance and functional tests, so in web tests difference is the same. There is a couple of tools to use for web functional and acceptance tests:
97+
98+
* PhpUnit + Selenium
99+
* Behat + Mink
100+
* Codeception
101+
102+
I do prefer **Codeception** over Behat+Mink for web acceptance and functional tests for these reasons:
103+
104+
* In web it is not very important to develop pages from how they need to behave. So there all power of Gherkin could not be applied. In this case Gherkin works just as simple translator and nothing more. My decision is to use right things for right purposes.
105+
* As I've pointed out above you also need to know Mink "internals" (API) to proceed some your custom methods.
106+
* Testing web-pages can lead to many ambiguous or redundant Gherkin steps.
107+
108+
Of course there are some things to avoid this, but i prefer "easy-to-learn things" in this situation.
109+
110+
In that case Codeception offeres you a simple and very easy way to test your web application. Also I need to
111+
notice that Codeception takes low-level Mink's API and provides a high-level commands for end-user.
112+
113+
For example lets see simple ```Codeception``` Cept test case:
114+
115+
{% highlight php %}
116+
<?php
117+
$I = new TestGuy($scenario);
118+
$I->wantTo('Test index page');
119+
$I->amOnPage('/index.php');
120+
$I->see('My Web Application','#header #logo');
121+
$I->click('Login');
122+
$I->see('Login','h1');
123+
$I->see('Username');
124+
$I->amGoingTo('login in the test app');
125+
$I->fillField('#LoginForm_username','demo');
126+
$I->fillField('#LoginForm_password','demo');
127+
$I->click('#login-form input[type="submit"]');
128+
$I->seeLink('Logout (demo)');
129+
$I->click('Logout (demo)');
130+
$I->seeLink('Login');
131+
?>
132+
{% endhighlight %}
133+
134+
As you can see it is easy to read, and one really great thing is it is easy to write, because of auto-completion. In Behat when using Gherkin you can get some *"Undefined steps"* errors, just because you mistyped something. And it happens to be annoying.
135+
136+
Codeception bundled with modules for functional and acceptance tests: PhpBrowser (functional tests over curl), Selenium (1,2) for acceptance tests, etc. There are also some nice modules for REST, SOAP and XML-RPC that can help you to test your API.
137+
138+
It is need to be noticed that there are two types of web tests in ```Codeception```: ones requires server(nginx, apache, etc) and others not - all requests are processed directly by your applcation using Symfony's BrowserKit Component.
139+
140+
Overall, my choice in Codeception is to use "PhpBrowser" module (requires a web-server) for headless web functional tests, and "Selenium2" module for complete web acceptance tests. Codeception also can generate BDD-style scenarios for you based on your Cepts.
141+
142+
Also need to notice that maybe Codeception is not a "true" BDD, unlike Behat. Behat+Gherkin helps you to use and design your application. Codeception helps you to test it nicely.

0 commit comments

Comments
 (0)