imatic/testing

使Symfony扩展包的测试更容易的库

v6.0.4 2023-03-27 14:01 UTC

README

Build Status
License: MIT

测试

这个库使得设置测试包括对可重用扩展包的项目测试变得简单。它将创建所有必需的文件,以便您可以开始编写测试和可视化扩展包的组件,而无需将其包含在某个应用程序中(因为这个库会在扩展包的测试命名空间中创建这样的应用程序)。

内容

初始化测试项目

  • phpunit.xml.dist添加到您的存储库以配置phpunit
  • 设置KERNEL_DIR服务器变量,以便phpunit可以找到symfony内核(示例值需要根据扩展包名称进行修改)
<!-- phpunit.xml.dist -->
<phpunit>
    <php>
        <server name="KERNEL_DIR" value="Imatic\Bundle\TestsTemplateBundle\Tests\Fixtures\TestProject\TestKernel"/>
    </php>
</phpunit>
  • 将imatic-testing添加到您的开发依赖中
$ composer require --dev 'imatic/testing'
$ ./vendor/bin/testingbundle-init
  • 上述命令应创建类似以下目录结构:
Tests
    Fixtures
        TestProject
            config
                config.yml
                routing.yml
            XYZBundle (same name as tested bundle)
                AppXYZBundle.php
            web
                app.php
            console
            TestKernel.php
            WebTestCase.php
    Functional
    Integration
    Unit
    bootstrap.php
  • 上述目录结构是基于TestsTemplate目录中的模板创建的。

PHPUnit

额外约束

所有在symfony功能测试中可用的额外约束都自动包含在我们的WebTestCase中。如果您有自己的WebTestCase实现,您可以使用我们的特性WebTestCaseExtension将我们的额外约束包含到您的WebTestCase中。

ResponseHasCode

此约束可用于断言symfony功能测试中的状态码。使用方法

<?php

use Imatic\Testing\Test\WebTestCase;

class ExampleTestCase extends WebTestCase
{
    public function testHomepageReturnsOk()
    {
        $client = static::createClient();
        $client->request('GET', '/');

        $this->assertResponseHasCode(200, $client->getResponse());
    }
}
  • 与使用$client->getResponse()->getStatusCode()断言200相比的优势在于,特殊的断言会为您提供有关出错原因的信息,而不仅仅是错误代码(例如500)。

使用

现在,如果您已全部配置完毕,您就可以开始编写测试或在浏览器中检查您的测试项目。为了在浏览器中检查您的测试项目。

在浏览器中检查你的测试项目

  • 转到测试项目的根目录并运行Web服务器

使用PHP内置的Web服务器

$ cd Tests/Fixtures/TestProject/
$ ./console server:run --docroot=web
  • 现在打开浏览器,访问最后一条命令报告的URL(可能是http://127.0.0.1:8000/app.php
  • 您现在可能会看到异常,可能是因为您还没有为项目配置任何路由
  • 有关该命令的更多详细信息,请参阅symfony文档

使用其他Web服务器

使用symfony控制台

  • 当我们在讨论测试项目目录结构时,你可能已经注意到了,你也可以使用 symfony 控制台 - 这样你就可以运行测试项目所使用的 bundle 或多个 bundle 提供的所有命令
  • 请参考 symfony 文档 了解如何使用控制台命令(注意,在我们的情况下,运行控制台的可执行文件称为 console,并放置在测试项目的根目录中

编写与数据库交互的测试

  • 如果你将我们的 WebTestCase 作为测试的父类,那么每个测试都会在事务中运行,因此你所有对数据库的修改都会丢失(因此测试运行前数据库处于原始状态)
  • 请查看下面的注释测试了解其工作原理
<?php

namespace Imatic\Bundle\DataBundle\Tests\Integration\Data\Command;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Imatic\Bundle\DataBundle\Data\Command\Command;
use Imatic\Bundle\DataBundle\Data\Command\CommandExecutor;
use Imatic\Bundle\DataBundle\Tests\Fixtures\TestProject\ImaticDataBundle\Entity\User;
use Imatic\Bundle\DataBundle\Tests\Fixtures\TestProject\WebTestCase;

// this is our test class wich extends ``WebTestCase`` which ensures
// that each test runs in the same environment (has predictable db state)
class CommandExecutorTest extends WebTestCase
{
    public function testGivenCommandShouldBeSuccessfullyExecuted()
    {
        /* @var $user User */
        $user = $this->getUserRepository()->findOneByName('Adam');

        // here we make sure that the user is not activated
        // so that we can test activating functionality
        $this->assertTrue($user->isActivated());

        $command = new Command('user.deactivate', ['id' => $user->getId()]);
        // here we execute command which activates the user
        // and stores the information into database
        $result = $this->getCommandExecutor()->execute($command);
        $this->assertTrue($result->isSuccessful());

        // here we check that user was activated
        $this->assertFalse($user->isActivated());

        // after this test finishes, user is deactivated because the transaction
        // is rollbacked
    }

    /**
     * @return EntityRepository
     */
    public function getUserRepository()
    {
        return $this->getEntityManager()->getRepository('AppImaticDataBundle:User');
    }

    /**
     * @return EntityManager
     */
    public function getEntityManager()
    {
        return $this->container->get('doctrine.orm.entity_manager');
    }

    /**
     * @return CommandExecutor
     */
    private function getCommandExecutor()
    {
        return $this->container->get('imatic_data.command_executor');
    }
}
  • 由于我们使用的 doctrine 连接包装器,你可以编写 symfony 功能性测试,并且在每次测试后,事务仍然会被回滚(没有使用包装器是无法实现的
    • 你可以在我们的 配置模板 中看到这个连接包装器
doctrine:
    dbal:
        connections:
            default:
                wrapper_class: "Imatic\\Testing\\Doctrine\\DBAL\\PersistedConnection"
  • 如果你需要加载任何 fixtures,你需要引入 DoctrineFixturesBundle 并指定任何 fixture。当 DoctrineFixturesBundle 启用时,我们的 WebTestCase 会自动加载 fixtures。
  • 在运行测试之前会重新加载数据库和 fixtures,如果你想要禁用这种行为,请在测试配置中更改环境变量 TESTING_DATA_INIT
<!-- phpunit.xml.dist -->
<phpunit>
    <php>
        <env name="TESTING_DATA_INIT" value="0" />
    </php>
</phpunit>

测试项目配置

  • 如果你需要更改配置,只需编辑生成的配置文件,你可以在 config/config.yml 中找到它(相对于测试项目根目录)