Я хочу сохранить или запустить логин перед большинством моих тестов. Но если я попытаюсь переместить код входа в систему до того, как он не будет работать, поскольку для меня нет экземпляра webguy.
Каков наилучший способ сохранить сеанс между несколькими тестами? Это мой код до сих пор, был бы рад получить некоторую помощь. Я просмотрел документацию по Google и проверил документацию, но я ничего не могу найти о работе сессии.
<?php use \WebGuy; class ProductCest { private $product_id = '1'; public function _before() { } public function _after() { } // tests public function login(WebGuy $I) { $I->seeInCurrentUrl('/auth/login'); $I->fillField("//input[@type='email']", "username@email.com"); $I->fillField("//input[@type='password']", "1234"); $I->click('#signIn .submit'); $I->wait(500); $I->seeInCurrentUrl('/account'); } /** * @depends login */ public function chooseProduct(WebGuy $I) { $I->wantTo('go to products and choose one'); $I->amOnPage('/?product=' . $this->client_id); } }
<?php use \WebGuy; class ProductCest { private $product_id = '1'; public function _before() { } public function _after() { } private function executeLogin(WebGuy $I){ $I->seeInCurrentUrl('/auth/login'); $I->fillField("//input[@type='email']", "username@email.com"); $I->fillField("//input[@type='password']", "1234"); $I->click('#signIn .submit'); $I->wait(500); return $I; } // tests public function login(WebGuy $I) { $I = $this->executeLogin($I); $I->seeInCurrentUrl('/account'); } /** * @depends login */ public function chooseProduct(WebGuy $I) { $I = $this->executeLogin($I); $I->wantTo('go to products and choose one'); $I->amOnPage('/?product=' . $this->client_id); } }
Это должно сработать.
Я думаю, что принятый ответ – это способ его достижения, но не самый лучший. При этом вам всегда нужно будет воспроизвести все шаги для входа в систему, когда вам нужно только поделиться сеансом пользователя. Я думаю, что захват cookie сеанса и передача его через требуемые тесты, зарегистрированные пользователем, лучше. Для этого вы создаете функцию входа в систему, получаете файл cookie и сначала проверяете тесты на вход в систему:
<?php use \AcceptanceTester; class testingCest { private $cookie = null; public function _before(AcceptanceTester $I) { } public function _after(AcceptanceTester $I) { } // tests public function login(AcceptanceTester $I) { $I->wantTo('entrar al sistema'); $I->amOnPage('/'); $I->seeInCurrentUrl('/admin/login'); $I->fillField('user','perry'); $I->fillField('pass','pass-perry'); $I->click('Login'); $I->see('You\'re logged!'); $this->cookie = $I->grabCookie('your-session-cookie-name'); } /** * @depends login */ public function listUsers(AcceptanceTester $I) { $I->setCookie( 'your-session-cookie-name', $this->cookie ); $I->amOnPage('/admin/users'); $I->seeInCurrentUrl('/admin/users/1'); } /** * @depends login */ public function listRols(AcceptanceTester $I) { $I->setCookie( 'your-session-cookie-name', $this->cookie ); $I->amOnPage('/admin/rols'); $I->seeInCurrentUrl('/admin/rols/1'); } }
Таким образом, если тест входа не удался, вы не получите cookie, и вы не пройдете другие тесты.
Я предпочитаю эту аннотацию @depends
вместо предложенной @before
в другом ответе, потому что если вы используете @depends
вы ВСЕГДА будете выполнять код в тесте раньше, и тесты будут выполняться только после входа в систему.
Ниже приведен еще один ответ https://stackoverflow.com/a/41109855/1168804, который также может помочь вам, поскольку структура для Codeception развилась с момента написания этого ответа.
Все более ранние ответы старые , теперь это делается непосредственно в методе _before, который принимает класс Actor в качестве аргумента.
<?php namespace Test\Api; use ApiTester; class TrainingCest { public function _before(ApiTester $I) { $I->amLoggedInAs('kgkg'); } public function _after(ApiTester $I) { } // tests public function testForLoggedInUser(ApiTester $I) { } public function anotherTestForLoggedInUser(ApiTester $I) { } }
И если вы хотите войти в систему только один раз для всех файлов CEST , вы можете использовать глобальный шаблон класса реестра вместе с некоторыми lazyloading. Вот рабочий код для моих тестов интеграции api, определенных в классе Actor (в моем случае ApiTester):
public function amLoggedInAs($userLogin) { $I = $this; if (Registry::getInstance()->exists($userLogin)) { // get data from registry $storedUserData = Registry::getInstance()->get($userLogin); $newAccessToken = $storedUserData['accessToken']; $playerId = $storedUserData['playerId']; } else { // no registry data - log in and save data in registry $I->tryToLogin($userLogin); $newAccessToken = $I->grabDataFromResponseByJsonPath('data.newToken'); $playerId = (int)$I->grabDataFromResponseByJsonPath('data.userId'); Registry::getInstance()->set($userLogin, [ 'accessToken' => $newAccessToken, 'playerId' => $playerId ]); } // finally set headers and some other data $I->haveHttpHeader('X-Token', $newAccessToken); $I->havePlayerId($playerId); } protected function tryToLogin($userLogin) { $I = $this; $I->wantTo('login into api'); $I->amGoingTo('try to log to API using login and password'); $I->sendPOST('/system/login', ['login' => $userLogin, 'password' => self::getPassword($userLogin)]); // ...some other checking if user was correctly logged in ... }
Этот код в основном сохраняет accessToken вместе с некоторыми дополнительными данными в реестре после регистрации пользователя в первый раз. Если вызывается другой вызов $ I-> amLoggedInAs ('kgkg'), он получает эти значения из реестра. Таким образом, у вас может быть много зарегистрированных пользователей, каждый из которых регистрируется только один раз для каждого пакета.
Вы можете использовать другой метод для авторизации вместо пользовательского токена, логика все равно будет одинаковой.
Также, если вы используете WebDriver (не PhpBrowser), вы можете использовать loadSessionSnapshot и saveSessionSnapshot вместо Registry, чтобы получить тот же результат.
Я думаю, что ответ @Sinisa – это «рабочий», но не «правильный».
Что вы хотите, а не @depends аннотации, но @before.
Разница в том, что с @depends текущий контекст не сохраняется, а при использовании @ перед сохранением контекста.
public function foo(WebGuy $I) { $I->amOnPage('/foobar'); } /** * @depends foo */ public function bar(WebGuy $I) { $I->seeInCurrentUrl('foobar'); // Wil fail } /** * @before foo */ public function baz(WebGuy $I) { $I->seeInCurrentUrl('foobar'); // Will pass }
Следует отметить, что если вы тестируете WordPress, в модуле WP-браузера есть методы «сахара» для входа в систему:
loginAsAdmin(); loginAs($username, $password);