@@ -79,129 +79,6 @@ The most important part is the `_generated\AcceptanceTesterActions` trait, which
7979It knows which module executes which action and passes parameters into it.
8080This trait was created by running `codecept build` and is regenerated each time module or configuration changes.
8181
82- <<<<<<< HEAD
83-
84- ## PageObjects
85-
86- For acceptance and functional testing, we will not only need to have common actions being reused across different tests,
87- we should have buttons, links and form fields being reused as well. For those cases we need to implement
88- the [PageObject pattern](http://docs.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern),
89- which is widely used by test automation engineers. The PageObject pattern represents a web page as a class
90- and the DOM elements on that page as its properties, and some basic interactions as its methods.
91- PageObjects are very important when you are developing a flexible architecture of your tests.
92- Do not hard-code complex CSS or XPath locators in your tests but rather move them into PageObject classes.
93-
94- Codeception can generate a PageObject class for you with command:
95-
96- {% highlight bash %}
97-
98- php vendor/bin/codecept generate:pageobject Login
99-
100- {% endhighlight %}
101-
102- This will create a `Login` class in `tests/_support/Page`.
103- The basic PageObject is nothing more than an empty class with a few stubs.
104- It is expected that you will populate it with the UI locators of a page it represents
105- and then those locators will be used on a page.
106- Locators are represented with public static properties:
107-
108- {% highlight php %}
109-
110- <?php
111- namespace Page;
112-
113- class Login
114- {
115- public static $URL = '/login';
116-
117- public static $usernameField = '#mainForm #username';
118- public static $passwordField = '#mainForm input[name=password]';
119- public static $loginButton = '#mainForm input[type=submit]';
120- }
121-
122- {% endhighlight %}
123-
124- And this is how this page object can be used in a test:
125-
126- {% highlight php %}
127-
128- <?php
129- $I-> amOnPage(\Page\Login::$URL);
130- $I->fillField(\Page\Login::$usernameField, 'bill evans');
131- $I->fillField(\Page\Login::$passwordField, 'debby');
132- $I->click(\Page\Login::$loginButton);
133- $I->see('Welcome, bill');
134-
135- {% endhighlight %}
136-
137- As you see, you can freely change markup of your login page, and all the tests interacting with this page
138- will have their locators updated according to properties of LoginPage class.
139-
140- But let's move further. The PageObject concept specifies that the methods for the page interaction should also be stored in a PageObject class.
141-
142- Let's define a `login` method in this class:
143-
144- {% highlight php %}
145-
146- <? php
147- namespace Page;
148-
149- class Login
150- {
151- public static $URL = '/login';
152-
153- public static $usernameField = '#mainForm #username';
154- public static $passwordField = '#mainForm input[name=password]';
155- public static $loginButton = '#mainForm input[type=submit]';
156-
157- /**
158- * @var AcceptanceTester
159- */
160- protected $tester;
161-
162- // we inject AcceptanceTester into our class
163- public function __construct(\AcceptanceTester $I)
164- {
165- $this-> tester = $I;
166- }
167-
168- public function login($name, $password)
169- {
170- $I = $this->tester;
171-
172- $I->amOnPage(self::$URL);
173- $I->fillField(self::$usernameField, $name);
174- $I->fillField(self::$passwordField, $password);
175- $I->click(self::$loginButton);
176- }
177- }
178-
179- {% endhighlight %}
180-
181- If you specify which object you need for a test, Codeception will try to create it using the dependency injection container.
182- In the case of a PageObject you should declare a class as a parameter for a test method:
183-
184- {% highlight php %}
185-
186- <? php
187- class UserCest
188- {
189- function showUserProfile(AcceptanceTester $I, \Page\Login $loginPage)
190- {
191- $loginPage-> login('bill evans', 'debby');
192- $I->amOnPage('/profile');
193- $I->see('Bill Evans Profile', 'h1');
194- }
195- }
196-
197- {% endhighlight %}
198-
199- The dependency injection container can construct any object that requires any known class type.
200- For instance, `Page\Login` required `AcceptanceTester`, and so it was injected into `Page\Login` constructor,
201- and PageObject was created and passed into method arguments. You should explicitly specify
202- the types of required objects for Codeception to know what objects should be created for a test.
203- Dependency Injection will be described in the next chapter.
204- =======
20582> Use actor classes to set common actions which can be used accross a suite.
20683
20784
@@ -405,98 +282,6 @@ If you feel like adding too many actions into your Actor class
405282
406283> Use StepObjects when you have multiple areas of applications or multiple roles.
407284
408- >>>>>>> 82997221b762bc09876379f9f30906c9d364a4f5
409-
410- ## StepObjects
411-
412- StepObjects are great if you need some common functionality for a group of tests.
413- 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
414- while testing the front end, so it's a good idea to move these admin-specific tests into their own class.
415- We call such a classes StepObjects.
416-
417- Lets create an Admin StepObject with the generator:
418-
419- {% highlight bash %}
420-
421- php vendor/bin/codecept generate:stepobject acceptance Admin
422-
423- {% endhighlight %}
424-
425- You can supply optional action names. Enter one at a time, followed by a newline.
426- End with an empty line to continue to StepObject creation.
427-
428- {% highlight bash %}
429-
430- php vendor/bin/codecept generate:stepobject acceptance Admin
431- Add action to StepObject class (ENTER to exit): loginAsAdmin
432- Add action to StepObject class (ENTER to exit):
433- StepObject was created in /tests/acceptance/_support/Step/Acceptance/Admin.php
434-
435- {% endhighlight %}
436-
437- This will generate a class in `/tests/_support/Step/Acceptance/Admin.php` similar to this:
438-
439- {% highlight php %}
440-
441- <? php
442- namespace Step\Acceptance;
443-
444- class Admin extends \AcceptanceTester
445- {
446- public function loginAsAdmin()
447- {
448- $I = $this;
449- }
450- }
451-
452- {% endhighlight %}
453-
454- As you see, this class is very simple. It extends the `AcceptanceTester` class,
455- meaning it can access all the methods and properties of `AcceptanceTester`.
456-
457- The `loginAsAdmin` method may be implemented like this:
458-
459- {% highlight php %}
460-
461- <?php
462- namespace Step\Acceptance;
463-
464- class Admin extends \AcceptanceTester
465- {
466- public function loginAsAdmin()
467- {
468- $I = $this;
469- $I-> amOnPage('/admin');
470- $I->fillField('username', 'admin');
471- $I->fillField('password', '123456');
472- $I->click('Login');
473- }
474- }
475-
476- {% endhighlight %}
477-
478-
479- StepObject can be instantiated automatically when used inside the Cest format:
480-
481- {% highlight php %}
482-
483- <? php
484- class UserCest
485- {
486- function showUserProfile(\Step\Acceptance\Admin $I)
487- {
488- $I-> loginAsAdmin();
489- $I->amOnPage('/admin/profile');
490- $I->see('Admin Profile', 'h1');
491- }
492- }
493-
494- {% endhighlight %}
495-
496- If you have a complex interaction scenario, you may use several step objects in one test.
497- If you feel like adding too many actions into your Actor class
498- (which is AcceptanceTester in this case) consider moving some of them into separate StepObjects.
499-
500285
501286## Conclusion
502287
0 commit comments