Подтвердить что ты не робот

Кодекс: сохранить зарегистрированное состояние

Я хочу сохранить или запустить логин перед большинством моих тестов. Но если я попытаюсь переместить код входа в систему до того, как он не будет работать, поскольку для меня нет экземпляра webguy.

Каков наилучший способ сохранить сеанс между несколькими тестами? Это мой код до сих пор, был бы рад получить некоторую помощь. У меня есть googled и проверили документацию, но я ничего не могу найти о работе сессии.

<?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']", "[email protected]");
        $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);
    }

}
4b9b3361

Ответ 1

<?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']", "[email protected]");
        $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);
    }
}

Это должно работать.

Ответ 2

Я думаю, что принятый ответ - способ сделать это, но не самый лучший. При этом вам всегда нужно будет воспроизвести все шаги для входа в систему, когда вам нужно только поделиться сеансом пользователя. Я думаю, что захват 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, вы ВСЕГДА будете выполнять код в тесте раньше, и тесты будут выполняться только после Войти.

UPDATE

Существует еще один ответ ниже, fooobar.com/questions/292176/..., который также может помочь вам, поскольку структура для Codeception развилась с момента написания этого ответа.

Ответ 3

Все предыдущие ответы устарели, теперь это делается прямо в методе _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, вы можете использовать глобальный класс Registry, реализующий шаблон проектирования Registry (см. Https://dzone.com/articles/practical-php-patterns/basic/practical-php-patterns- 0) наряду с некоторой ленивой загрузкой. Вот рабочий код для моих интеграционных тестов 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, чтобы получить совершенно такой же результат.

Ответ 4

Я думаю, что ответ @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
}

Ответ 5

Следует отметить, что если вы тестируете WordPress, в модуле WP-браузера есть методы "сахара" для входа в систему:

loginAsAdmin();
loginAs($username, $password);

https://github.com/lucatume/wp-browser

Ответ 6

Сейчас Codeception заботится об этом благодаря методам saveSessionSnapshot и loadSessionSnapshot.

<?php
// inside AcceptanceTester class:

public function login()
{
     // if snapshot exists - skipping login
     if ($I->loadSessionSnapshot('login')) return;

     // logging in
     $I->amOnPage('/login');
     $I->fillField('name', 'jon');
     $I->fillField('password', '123345');
     $I->click('Login');

     // saving snapshot
     $I->saveSessionSnapshot('login');
}
?>