3

特に公式ドキュメントに従っているため、何が問題を引き起こしているのか完全にはわかりません。また、数え切れないほどの Google グループのディスカッションや質問をここで読みましたが、役に立ちませんでした。

そのため、Fabien Potencier のSilex Skeletonの上にアプリを構築してきましたが、FormServiceProvider を使用するフォームがあるページで単体テストが失敗します。

PHPUnit 3.6.12 by Sebastian Bergmann.

Configuration read from /Users/Adam/Sites/AppEngine/phpunit.xml

..E

Time: 0 seconds, Memory: 10.00Mb

There was 1 error:

1) Acme\AppEngineTest::testAppControllerForm
session_start(): Cannot send session cookie - headers already sent by (output started at /usr/local/php5-20120823-092307/lib/php/PHPUnit/Util/Printer.php:173)

現在、テストクラスは 1 つしかありません

namespace Acme;

use Silex\WebTestCase;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;

class AppEngineTest extends WebTestCase
{
    public static function setUpBeforeClass()
    {
        parent::setUpBeforeClass();

        if (! defined('BASEPATH')) {
            define('BASEPATH', __DIR__.'/../..');
        }
    }

    public function createApplication()
    {
        $app = require BASEPATH.'/src/app.php';
        $app['debug'] = true;
        $app['exception_handler']->disable();

        $app['session.storage'] = $app->share(function() {
            return new MockArraySessionStorage();
        });

        $app['session.test'] = true;

        require BASEPATH.'/config/prod.php';
        require BASEPATH.'/src/controllers.php';

        return $app;
    }

    public function testIndex()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/');

        $this->assertTrue($client->getResponse()->isOk());
    }

    public function testAppControllerIndex()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/app/');

        $this->assertEquals($client->getResponse()->isOk());
        $this->assertCount(1, $crawler->filter('p:contains("Please choose an app from the following")'));
    }

    // This test fails
    public function testAppControllerForm()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/app/form');

        $this->assertTrue($client->getResponse()->isOk());
    }
}

PHPユニット構成

<?xml version="1.0" encoding="UTF-8"?>

<phpunit colors="true"
    bootstrap="vendor/autoload.php"
    backupGlobals="false"
    backupStaticAttributes="false"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnFailure="false"
    syntaxCheck="false"
>
    <testsuites>
        <testsuite name="Test Suite">
            <directory>tests/Acme</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">src/</directory>
        </whitelist>
    </filter>

    <php>
        <server name="HTTP_USER_AGENT" value="PHPUnit"/>
    </php>
</phpunit>

controllers.php で、フォームを含むコントローラーをマウントしました

use Acme\Controller\FacebookAppControllerProvider;

$app->mount('/app/', new FacebookAppControllerProvider());

このように見える

<?php

namespace Acme\Controller;

use Silex\Application;
use Silex\ControllerProviderInterface;
use Silex\Provider\FacebookServiceProvider;
use SlotMachine\Page as PageContainer;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Yaml\Yaml;

class FacebookAppControllerProvider implements ControllerProviderInterface
{
    public function connect(Application $app)
    {
        if (! $app['twig']->hasExtension('silex_asset_path')) {
            throw new \OutOfBoundsException(
                'The `silex_asset_path` Twig extension provided by this library has not been registered.'
            );
        }

        // creates a new controller based on the default route
        $controllers = $app['controllers_factory'];

        $app->register(new FacebookServiceProvider(), [
            'facebook.config' => [
                'appId'          => '1',
                'secret'         => '2',
                'sharedSession'  => true,
                'trustForwarded' => true,
                'fileUpload'     => false
            ],
            'facebook.permissions' => [ 'email' ],
        ]);

        $app['facebook_app.widget_data'] = [
            'foo' => [
                'name' => 'Foo'
            ],
            'bar' => [
                'name' => 'Bar'
            ]
        ];

        $controllers->match('/', function (Application $app) {
            return $app->render("facebook_app/index.html.twig", $app['facebook_app.widget_data']);
        })->method('POST|GET');

        $controllers->match('/app/{widget}/{tp}', function (Request $request, Application $app, $widget, $tp) {
            $slots = new PageContainer(Yaml::parse(BASEPATH.'/src/Acme/Resources/config/'.$widget.'.slots.yml'));

            // some default data for when the form is displayed the first time
            $formData = [
                'forename'  => 'First-Name',
                'surname'   => 'Last-Name',
                'telephone' => 'Telephone',
            ];

            $form = $app->form($formData)
                ->add('forename', 'text', [ 'label' => 'Name' ])
                ->add('surname',  'text', [ 'label' => false  ])
                ->add('telephone')
                ->getForm()
            ; //end

            if ('POST' == $request->getMethod()) {
                $form->bind($request);

                if ($form->isValid()) {
                    $data = $form->getData();

                    // do something with the data

                    // redirect somewhere
                    return $app->redirect('/');
                }
            }

            $pageData = [
                'slot' => $slots->all(),
                'template_number' => $tp,
                'widget' => [
                    'slug' => $widget,
                    'name' => $app['facebook_app.widget_data'][$widget]['name']
                ],
                'form' => $form->createView(),
            ];

            foreach ($pageData['slot'] as $slot => &$card) {
                $card = PageContainer::interpolate($card, [
                    'widget_name' => $pageData['widget']['name']
                ]);
            }

            $app['page_data'] = $pageData;

            return $app->render(sprintf('templates/%s/template_%d.html.twig', $widget, $tp), $app['page_data']);
        })
        ->method('POST|GET')
        ->assert('tp', '\d+')
        ->value('tp', 1)
        ; // end /app/{publication}/{tp} Controller

        return $controllers;
    }
}

app.php では、FormServiceProvider は、新しい Silex アプリケーションをインスタンス化した直後、および Twig 拡張機能を追加する前に登録されます。

$app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
    // add custom globals, filters, tags, ...
    $twig->addExtension(new Acme\Twig\SilexAssetPathExtension($app));

    return $twig;
}));
4

2 に答える 2

-2

2 つのソリューション:

  1. 分離されたプロセスでテストを実行します。

    /**
     * @runInSeparateProcess
     */
    public function testAppControllerForm()
    {
        $client = $this->createClient();
        $crawler = $client->request('GET', '/app/form');
    
        $this->assertTrue($client->getResponse()->isOk());
    }
    
  2. phpunit の出力を stderr にリダイレクトします。

    phpunit --stderr <options>
    
于 2013-07-12T08:56:39.833 に答える