(Codeception + Symfony2) セキュアなページに対するFunctional Test

How to simulate Authentication with a Token in a Functional Test (current) - Symfony に書かれている内容をCodeceptionではどのように実現するか。

1. 専用のHelperを書く

<?php
namespace Codeception\Module;

// here you can define custom functions for TestGuy 

use Symfony\Component\BrowserKit\Client;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class TestHelper extends \Codeception\Module
{
    public function amLoggedInAs($username)
    {
        $client = $this->getModule('Symfony2')->client;
        $container = $client->getContainer();

        $doctrine = $container->get('doctrine');
        $user = $doctrine
            ->getRepository('VendorSampleBundle:User')
            ->findOneBy(['username' => $username]);

        $firewall = 'secured_area';
        $token = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());

        $session = $container->get('session');
        $session->set('_security_' . $firewall, serialize($token));
        $session->save();

        $cookie = new Cookie($session->getName(), $session->getId());
        $client->getCookieJar()->set($cookie);
    }
}

2. GuyをBuildする

bin/codecept build

3. Helperを使う

<?php
$I = new TestGuy($scenario);
$I->wantToTest('secured area.');

$I->amOnPage('/');
$I->see('Hello Guest!!');

$I->amLoggedInAs('Mike');
$I->amOnPage('/');
$I->see('Hello Mike!!');

備考

上記の解決策は、OAuth認証などアプリ側に認証用のフォームが用意されていない場合や、少しでもテストを早く実行させたい場合に有効になると思います。
テスト対象のアプリがログイン用のフォームを提供している場合は、基本的にはFunctional Testsで説明されている以下のコードのように記述すれば良いです。

<?php
$I = new TestGuy($scenario);
$I->amOnPage('/');
$I->click('Login');
$I->fillField('Username','Miles');
$I->fillField('Password','Davis');
$I->click('Enter');
$I->see('Hello, Miles', 'h1');
?>

ログイン処理がテストの中で頻繁に必要となる場合は、再利用性を高める仕組みである StepObject が1.6.4から導入されています。


以上です