symfony:需要进程分离的php单元测试



我正试图为Symfony系统添加登录过程的phpunit功能测试。登录过程很简单,但我在建立一个客户端时遇到了问题,该客户端不会遇到下面描述的许多问题之一,而且我已经没有解决方法了。我对这篇文章的篇幅感到抱歉。如有任何建议,我们将不胜感激。

详细信息
调试系统的正常登录中的序列是:

http://localhost:8000/login GET -> html form for login
http://localhost:8000/login_check POST(_username,_password) -> redirect
http://localhost:8000/useridx/NN (same as redirect)

我的测试类扩展了WebTestCase,并包含相应的公共函数:

testGetLoginPage(): tests page returned from /login, returns $context (with $client)
testLoginCheck($context): posts the login data, validates the redirect page, and returns $context (with $client)
testUserIndex($context): validates the page returned by following the redirect

当我运行测试时,testGetLoginPage成功了,然后testLogiCheck得到了一个带有符号堆栈跟踪的返回页,该跟踪指示:

<title>    Failed to start the session because headers have already been sent by &quot;/home1/xxxxx-app/vendor/phpunit/phpunit/src/Util/Printer.php&quot; at line 133. (500 Internal Server Error)</title>

Printer.php中的行为:

print $buffer;

经过一些研究,我发现有评论表明,我可以通过为testLogiCheck:声明这一点来避免这个问题

/**
* @runInSeparateProcess 
*/

声明之后,testLogiCheck获得了正确的页面(重定向)到/useridx/NN。然后,我试图遵循testUserIndex中的重定向,但响应返回了第一个登录页面的副本,并带有拒绝访问的指示,即使登录测试成功了。

我的下一个想法是,我还需要为testUserIndex声明@runInSeparateProcess,但结果是一样的。我猜这导致了Print.php的一个进程,testLogiCheck的第二个进程,以及testUserIndex的第三个进程。我最终找到了另一个应用于我的测试班的指令:

/**
* @runTestsInSeparateProcesses
*/

我从函数中删除了@runInSeparateProcess指令。这一直很有效,直到其中一个测试断言失败,这时我得到了一个长符号异常和堆栈跟踪,指示:

Caused by
exception 'ErrorException' with message 'Class __PHP_Incomplete_Class has no unserializer' in /home1/xxxxx-app/vendor/phpunit/phpunit/src/Util/PHP.php:107

通过故意一次失败断言一个断言,我发现不完整的类断言总是由第一个失败的断言触发的。

与@preserveGlobalState相关的注释表明,为了解决父进程和子进程之间的序列化程序/反序列化程序问题,可以禁用它,但为类设置它会导致一个新问题:

RuntimeException: You must override the KernelTestCase::createKernel() method.

我还尝试了模拟身份验证,这样我就可以使用以下方法进行剩余的测试(需要身份验证):

http://symfony.com/doc/current/testing/simulating_authentication.html
http://symfony.com/doc/current/testing/http_authentication.html

但它总是让我重定向回登录页面。

我认为在这一点上最好停下来寻求帮助,然后再使用不同的测试系统。这是如此初级的测试,我似乎在玩打地鼠游戏。

我发现了一些似乎有效的东西,但它可能不是"symfony方式"。。。

  • 不要为测试类设置@runTestsInParateProcesses。

  • 将login/check合并到一个测试中(如Massimiliano所建议的),这是类中的第一个测试,并设置了"@runInSeparateProcess"。然后$client=static::createClient()$context["client"]=$client;return$context;

  • 在所有后续测试中,$client=$context["client"];在输入时,并返回$context不要为剩余的测试设置@runInSeparateProcess。使用这种方法可以根据需要包含尽可能多的testXxx函数。客户端已经登录,因此权限没有问题。

  • 我曾尝试在app/config/security.yml中添加一个安全/防火墙/测试/http_basic规则,但它不适用于我的系统进行授权的方式,所有后续测试都因权限问题而失败。

  • 当测试作为"bin/phpunit-c app src/BundleXxx/Tests/Controller/TheTest.PHP"运行时,"Class __PHP_Incomplete_Class has no unserializer"异常仍然是一个问题,但当它作为"bin/phpunit-c pp"的一部分运行时,则不会发生。我可以接受这一点,我已经添加了相应的文档。

最新更新