我可以创建一个客户端并将其重用于我的所有功能测试吗?


Can I create one Client and reuse it for all my functional tests?

tl;dr:这会阻止我的测试正常工作吗?

我正在尝试为我的Symfony项目编写功能测试,并从The Symfony Book中的示例开始工作。到目前为止,测试类的每个方法都以相同的代码行开始:

namespace Tests'AppBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Test'WebTestCase;
class SomeControllerTest extends WebTestCase
{
    public function testSomethingOnRouteX()
    {
        $client = static::createClient();
        // set up and assert
    }
    public function testSomethingElseOnRouteX()
    {
        $client = static::createClient();
        // different set up and assert
    }
}

我想删除这个多余的代码,但我不确定我是否应该这样做。

我在创建客户端的位置添加了一个构造函数。

public function __construct()
{
    parent::__construct();
    $this->client = static::createClient();
}

然后在各种测试方法中,我可以只使用$this->client而无需重复创建它。到目前为止,这似乎有效(我还没有很多测试。但是我对这个框架和这种类型的测试足够陌生,我不确定它是否会导致问题。

建议的

方法是使用 setUp() 方法或 @before 钩子。两者都在每个测试方法之前调用,因此您很安全,因为状态不会在测试用例之间共享。在每个测试用例运行后,也会自动为您完成清理(在 WebTestCase 类中实现)。

namespace Tests'AppBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Test'WebTestCase;
use Symfony'Bundle'FrameworkBundle'Client;
class SomeControllerTest extends WebTestCase
{
    /**
     * @var Client
     */
    private $client;
    protected setUp()
    {
        $this->client = self::createClient();
    }
    public function testSomethingOnRouteX()
    {
        // set up and assert
        $this->client->request('GET', '/something');
    }
    public function testSomethingElseOnRouteX()
    {
        // different set up and assert
        $this->client->request('GET', '/something-else');
    }
}

或者,要setUp()您可以使用@before钩子:

namespace Tests'AppBundle'Controller;
use Symfony'Bundle'FrameworkBundle'Test'WebTestCase;
use Symfony'Bundle'FrameworkBundle'Client;
class SomeControllerTest extends WebTestCase
{
    /**
     * @var Client
     */
    private $client;
    /**
     * @before
     */
    protected function setUp()
    {
        $this->client = self::createClient();
    }
    // ...
}

如果你尝试一下,你可能应该改用setUp方法。重用客户端可能会引入副作用,这是您尽量避免的。如果测试开始随机失败,则可能需要尝试返回到为每个测试创建新客户端。我不推荐它,但更多的是来自直觉而不是实际的糟糕经历。它应该在大多数情况下工作正常,但是当您突然重用客户端时,例如设置不同的标头并且它不起作用,您会头疼。

我认为不会有巨大的性能提升,因为无论如何 ui 测试都很慢,所以尝试尽可能少的测试用例可能是一种更好的方法(如果你不明白我的意思,请寻找测试金字塔)如果这是你的目标。

它可能有效,也可能不起作用,具体取决于您正在测试的内容。

新客户端就像全新的浏览器安装。未设置 Cookie、未设置历史记录、无actual页面等。

例如,如果您正在测试身份验证,那么如果testCanNotAccessInternalResourceIfNotLoggedIn使用仍在登录的客户端,因为这testLogInWithCorrectCredentialsWorks之前运行并因此失败,那将是非常糟糕的。当然,您可以确保在访问资源之前注销用户,但仅创建一个干净的新浏览器实例是最简单且最不容易出错的方法。