最新服务器上的版本,以后用这个
wangzhenxin
2023-11-19 bc164b8bdbfbdf1d8229a5ced6b08d7cb8db7361
commit | author | age
2207d6 1 # Functional Tests
W 2
3 Now that we've written some acceptance tests, functional tests are almost the same, with one major difference:
4 Functional tests don't require a web server.
5
6 In simple terms we set the `$_REQUEST`, `$_GET` and `$_POST` variables and then we execute the application from a test.
7 This may be valuable, as functional tests are faster and provide detailed stack traces on failures.
8
9 Codeception can connect to different PHP frameworks that support functional testing: Symfony2, Laravel5, Yii2,
10 Zend Framework and others. You just need to enable the desired module in your functional suite configuration to start.
11
12 Modules for all of these frameworks share the same interface, and thus your tests are not bound to any one of them.
13 This is a sample functional test:
14
15 ```php
16 <?php
17 // LoginCest.php
18
19 class LoginCest
20 {
21     public function tryLogin (FunctionalTester $I)
22     {
23         $I->amOnPage('/');
24         $I->click('Login');
25         $I->fillField('Username', 'Miles');
26         $I->fillField('Password', 'Davis');
27         $I->click('Enter');
28         $I->see('Hello, Miles', 'h1');
29         // $I->seeEmailIsSent(); // only for Symfony2
30     }
31 }
32 ```
33
34 As you see, the syntax is the same for functional and acceptance tests.
35
36 ## Limitations
37
38 Functional tests are usually much faster than acceptance tests. But functional tests are less stable as they run Codeception
39 and the application in one environment. If your application was not designed to run in long lived processes (e.g.
40 if you use the `exit` operator or global variables), then functional tests are probably not for you.
41
42 ### Headers, Cookies, Sessions
43
44 One of the common issues with functional tests is the use of PHP functions that deal with headers, sessions and cookies.
45 As you may already know, the `header` function triggers an error if it is executed after PHP has already output something.
46 In functional tests we run the application multiple times, thus we will get lots of irrelevant errors in the result.
47
48 ### External URL's
49
50 Functional tests cannot access external URL's, just URL's within your project. You can use Guzzle to open external URL's.
51
52 ### Shared Memory
53
54 In functional testing, unlike running the application the traditional way, the PHP application does not stop
55 after it has finished processing a request. Since all requests are run in one memory container, they are not isolated.
56 So **if you see that your tests are mysteriously failing when they shouldn't - try to execute a single test.**
57 This will show if the tests were failing because they weren't isolated during the run.
58 Keep your memory clean, avoid memory leaks and clean global and static variables.
59
60 ## Enabling Framework Modules
61
62 You have a functional testing suite in the `tests/functional` directory.
63 To start, you need to include one of the framework modules in the suite configuration file: `tests/functional.suite.yml`.
64
65 ### Symfony
66
67 To perform Symfony integration you just need to include the Symfony module into your test suite. If you also use Doctrine2,
68 don't forget to include it too. To make the Doctrine2 module connect using the `doctrine` service from Symfony,
69 you should specify the Symfony module as a dependency for Doctrine2:
70
71 ```yaml
72 # functional.suite.yml
73
74 actor: FunctionalTester
75 modules:
76     enabled:
77         - Symfony
78         - Doctrine2:
79             depends: Symfony # connect to Symfony
80         - \Helper\Functional
81 ```
82
83 By default this module will search for AppKernel in the `app` directory.
84
85 The module uses the Symfony Profiler to provide additional information and assertions.
86
87 [See the full reference](http://codeception.com/docs/modules/Symfony)
88
89 ### Laravel5
90
91 The [Laravel5](http://codeception.com/docs/modules/Laravel5) module is included and requires no configuration:
92
93 ```yaml
94 # functional.suite.yml
95
96 actor: FunctionalTester
97 modules:
98     enabled:
99         - Laravel5
100         - \Helper\Functional
101 ```
102
103 ### Yii2
104
105 Yii2 tests are included in [Basic](https://github.com/yiisoft/yii2-app-basic)
106 and [Advanced](https://github.com/yiisoft/yii2-app-advanced) application templates. Follow the Yii2 guides to start.
107
108 ### Yii
109
110 By itself Yii framework does not have an engine for functional testing.
111 So Codeception is the first and the only functional testing framework for Yii.
112 To use it with Yii include `Yii1` module into config:
113
114 ```yaml
115 # functional.suite.yml
116
117 actor: FunctionalTester
118 modules:
119     enabled:
120         - Yii1
121         - \Helper\Functional
122 ```
123
124 To avoid the common pitfalls we discussed earlier, Codeception provides basic hooks over the Yii engine.
125 Please set them up following [the installation steps in the module reference](http://codeception.com/docs/modules/Yii1).
126
127 ### Zend Framework 2
128
129 Use [the ZF2 module](http://codeception.com/docs/modules/ZF2) to run functional tests inside Zend Framework 2:
130
131 ```yaml
132 # functional.suite.yml
133
134 actor: FunctionalTester
135 modules:
136     enabled:
137         - ZF2
138         - \Helper\Functional
139 ```
140
141 ### Zend Framework 1.x
142
143 The module for Zend Framework is highly inspired by the ControllerTestCase class, used for functional testing with PHPUnit.
144 It follows similar approaches for bootstrapping and cleaning up.
145 To start using Zend Framework in your functional tests, include the `ZF1` module:
146
147 ```yaml
148 # functional.suite.yml
149
150 actor: FunctionalTester
151 modules:
152     enabled:
153         - ZF1
154         - \Helper\Functional
155 ```
156
157 [See the full reference](http://codeception.com/docs/modules/ZF1)
158
159 ### Phalcon
160
161 The `Phalcon` module requires creating a bootstrap file which returns an instance of `\Phalcon\Mvc\Application`.
162 To start writing functional tests with Phalcon support you should enable the `Phalcon` module
163 and provide the path to this bootstrap file:
164
165 ```yaml
166 # functional.suite.yml
167
168 actor: FunctionalTester
169 modules:
170     enabled:
171         - Phalcon:
172             bootstrap: 'app/config/bootstrap.php'
173              cleanup: true
174              savepoints: true
175         - \Helper\Functional
176 ```
177
178 [See the full reference](http://codeception.com/docs/modules/Phalcon)
179
180 ## Writing Functional Tests
181
182 Functional tests are written in the same manner as [Acceptance Tests](http://codeception.com/docs/03-AcceptanceTests)
183 with the `PhpBrowser` module enabled. All framework modules and the `PhpBrowser` module share the same methods
184 and the same engine.
185
186 Therefore we can open a web page with `amOnPage` method:
187
188 ```php
189 <?php
190 $I = new FunctionalTester($scenario);
191 $I->amOnPage('/login');
192 ```
193
194 We can click links to open web pages:
195
196 ```php
197 <?php
198 $I->click('Logout');
199 // click link inside .nav element
200 $I->click('Logout', '.nav');
201 // click by CSS
202 $I->click('a.logout');
203 // click with strict locator
204 $I->click(['class' => 'logout']);
205 ```
206
207 We can submit forms as well:
208
209 ```php
210 <?php
211 $I->submitForm('form#login', ['name' => 'john', 'password' => '123456']);
212 // alternatively
213 $I->fillField('#login input[name=name]', 'john');
214 $I->fillField('#login input[name=password]', '123456');
215 $I->click('Submit', '#login');
216 ```
217
218 And do assertions:
219
220 ```php
221 <?php
222 $I->see('Welcome, john');
223 $I->see('Logged in successfully', '.notice');
224 $I->seeCurrentUrlEquals('/profile/john');
225 ```
226
227 Framework modules also contain additional methods to access framework internals. For instance, Laravel5, Phalcon,
228 and Yii2 modules have a `seeRecord` method which uses the ActiveRecord layer to check that a record exists in the database.
229
230 Take a look at the complete reference for the module you are using. Most of its methods are common to all modules
231 but some of them are unique.
232
233 You can also access framework globals inside a test or access the dependency injection container
234 inside the `Helper\Functional` class:
235
236 ```php
237 <?php
238 namespace Helper;
239
240 class Functional extends \Codeception\Module
241 {
242     function doSomethingWithMyService()
243     {
244         $service = $this->getModule('Symfony')->grabServiceFromContainer('myservice');
245         $service->doSomething();
246     }
247 }
248 ```
249
250 Also check all available *Public Properties* of the used modules to get full access to their data.
251
252 ## Error Reporting
253
254 By default Codeception uses the `E_ALL & ~E_STRICT & ~E_DEPRECATED` error reporting level.
255 In functional tests you might want to change this level depending on your framework's error policy.
256 The error reporting level can be set in the suite configuration file:
257
258 ```yaml
259 actor: FunctionalTester
260 modules:
261     enabled:
262         - Yii1
263         - \Helper\Functional
264 error_level: "E_ALL & ~E_STRICT & ~E_DEPRECATED"
265 ```
266
267 `error_level` can also be set globally in `codeception.yml` file.
268
269 ## Conclusion
270
271 Functional tests are great if you are using powerful frameworks. By using functional tests you can access
272 and manipulate their internal state. This makes your tests shorter and faster. In other cases,
273 if you don't use frameworks there is no practical reason to write functional tests.
274 If you are using a framework other than the ones listed here, create a module for it and share it with the community.