lchrusciel/api-test-case

针对 JSON/XML API 的 TDD 测试的完美 PHPUnit 测试用例,适用于 Symfony。

v5.3.4 2024-07-29 13:11 UTC

README

Build Scrutinizer Code Quality

ApiTestCase 是一个 PHPUnit 测试用例,将使您作为 Symfony API 开发者的生活变得更加轻松。它扩展了基本的 Symfony WebTestCase 并添加了一些酷炫的功能。

感谢 PHP-Matcher,您可以根据其自述文件中的说明,“像黑手党一样编写预期的 JSON 响应”。我们绝对同意。

它还使用 Alice 以便轻松加载 Doctrine 固定值。

功能

  • 使用 Symfony 进行 API 开发的清晰的 TDD 工作流程;
  • 具有清晰错误信息的 JSON/XML 匹配;
  • 使用 Alice 加载固定值(可选);

安装

假设您已经全局安装了 Composer

composer require --dev lchrusciel/api-test-case

完成了!ApiTestCase 正在使用默认配置工作。

使用方法

我们为您的测试用例提供两个基类:JsonApiTestCase 和 XmlApiTestCase。根据您要创建的 API 格式选择一个。

JSON 示例

基本的 TDD 工作流程如下

  1. 编写一个发送请求的测试用例,并使用 assertResponse 断言方法检查响应内容是否与您的预期匹配。您需要一个响应文件的名称;
  2. 创建一个名为您在步骤 1 中选择的文件。并将预期的响应内容放在其中。例如,应将其放在 src/AppBundle/Tests/Responses/Expected/hello_world.json 中。
  3. 使其变红。
  4. 使其变绿。
  5. 重构。

让我们看一个简单的例子!编写以下测试

namespace AppBundle\Tests\Controller\HelloWorldTest;

use ApiTestCase\JsonApiTestCase;

class HelloWorldTest extends JsonApiTestCase
{
    public function testGetHelloWorldResponse()
    {
        $this->client->request('GET', '/');

        $response = $this->client->getResponse();

        $this->assertResponse($response, 'hello_world');
    }
}

现在定义预期的响应文件

{
    "message": "Hello ApiTestCase World!"
}

运行您的测试

vendor/bin/phpunit

您的测试应该因一些错误而失败,您可能缺少控制器和路由,所以请继续定义它们!一旦您实现了控制器并配置了适当的路由,您就可以再次运行测试。

如果响应内容与我们的预期匹配,控制台将显示一个简单的消息

OK (1 tests, 2 assertions)

否则,它将显示接收到的消息的差异

"Hello ApiTestCase World" does not match "Hello ApiTestCase World!".
@@ -1,4 +1,3 @@
 {
-    "message": "Hello ApiTestCase World!"
+    "message": "Hello ApiTestCase World"
 }
-

首先,函数 assertResponse 将检查响应代码(默认响应代码为 200),然后它将检查响应头是否包含 application/json 内容类型。最后,它将检查响应内容是否与预期匹配。有时您无法预测响应中的某些值,例如自动生成的日期或数据库中的 id。这里不需要魔法,因为 PHP-Matcher 提供了帮助。这些只是可用模式的一些示例

  • @string@
  • @integer@
  • @boolean@
  • @array@

更多信息请查看 PHP-Matcher 的文档

有了这些模式,您的预期响应将如下所示

{
    "message": "@string@"
}

有了这个,任何在 message 键下的字符串都将匹配该模式。更复杂的预期响应可能如下所示

[
    {
        "id": "@integer@",
        "name": "Star-Wars T-shirt",
        "sku": "SWTS",
        "price": 5500,
        "sizes": "@array@",
        "created_at": "@[email protected]()"
    },
    {
        "id": "@integer@",
        "name": "Han Solo Mug",
        "sku": "HSM",
        "price": 500,
        "sizes": "@array@",
        "created_at": "@[email protected]()"
    }
]

它将匹配以下产品列表

array(
    array(
        'id' => 1,
        'name' => 'Star-Wars T-shirt',
        'sku' => 'SWTS',
        'price' => 5500,
        'sizes' => array('S', 'M', 'L'),
        'created_at' => new \DateTime(),
    ),
    array(
        'id' => 2,
        'name' => 'Han Solo Mug',
        'sku' => 'HSM',
        'price' => 500,
        'sizes' => array('S', 'L'),
        'created_at' => new \DateTime(),
    ),
)

使用数据库固定值进行测试

ApiTestCase 集成了 nelmio/alice。多亏了这个优秀的库,您可以在需要时轻松加载您的固定值。您必须定义您的固定值并将它们放置在适当的目录中。以下是如何定义固定值和使用案例的示例。有关如何定义固定值的更多信息,请查看 Alice 的文档

为了在 Doctrine 中使用 Alice,您需要启用两个额外的包

Symfony 4.0+

// config/bundles.php
return [
    // ...
    
    Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['test' => true],
    Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['test' => true],
];

现在,假设您在应用程序中有一个映射的 Doctrine 实体名为 Book

    class Book 
    {
        private $id;
        private $title;
        private $author;
    
        // ... 
    }

要加载测试的固定数据,您需要在 src/AppBundle/Tests/DataFixtures/ORM/books.yml 中定义一个简单的 YAML 文件

    ApiTestCase\Test\Entity\Book:
        book1:
            title: "Lord of The Rings"
            author: "J. R. R. Tolkien"
        book2:
            title: "Game of Thrones"
            price: "George R. R. Martin"

最后,要在一个测试中使用这些固定数据,只需调用适当的方法

    public function testBooksIndexAction()
    {
        // This method require subpath to locate specific fixture file in your DataFixtures/ORM directory.
        $this->loadFixturesFromFile('books.yml');  
      
        // There is another method that allows you to load fixtures from directory.
        $this->loadFixturesFromDirectory('big_library');
    }

配置参考

要自定义测试套件配置,可以在 phpunit.xml 中添加更多选项

<php>
    <server name="KERNEL_CLASS" value="Acme\Kernel" />
    <server name="EXPECTED_RESPONSE_DIR" value="/path/to/expected/responses/" />
    <server name="FIXTURES_DIR" value="/path/to/DataFixtures/ORM/" />
    <server name="OPEN_ERROR_IN_BROWSER" value="true/false" />
    <server name="OPEN_BROWSER_COMMAND" value="open %s" />
    <server name="IS_DOCTRINE_ORM_SUPPORTED" value="true/false" />
    <server name="TMP_DIR" value="/tmp/path/to/temporary/folder/" />
    <server name="ESCAPE_JSON" value="true/false" />
</php>
  • KERNEL_CLASS 允许您指定用于设置 Kernel 的确切类。
  • ERESPONSE_DIR 变量包含预期响应文件夹的路径。它在将 API 结果与现有 JSON 文件进行比较时使用。如果此值未设置,ApiTestCase 将尝试猜测响应的位置,在您的控制器测试类相对的 '../Responses' 文件夹中查找响应。
  • FIXTURES_DIR 变量包含包含您的数据固定数据的文件夹路径。默认情况下,如果此变量未设置,它将在您的测试类相对的 '../DataFixtures/ORM/' 中查找。ApiTestCase 如果文件夹不存在或没有要加载的文件,将抛出 RunTimeException。
  • OPEN_ERROR_IN_BROWSER 是一个标志,它打开在浏览器窗口中显示错误的选项。默认值是 false。
  • OPEN_BROWSER_COMMAND 是一个命令,它将在抛出异常时用于打开浏览器。
  • IS_DOCTRINE_ORM_SUPPORTED 是一个标志,它打开 doctrine 支持,包括便捷的数据固定加载器和数据库清理器。
  • TMP_DIR 变量包含临时文件夹的路径,其中将存储日志文件。
  • ESCAPE_JSON 是一个标志,它打开在比较预期数据之前对您的 JSON 输出进行转义(Unicode 字符和反斜杠)。默认值是 false。此标志仅存在于与 ApiTestCase 的早期版本向后兼容(当打开时)并将被删除。

示例项目

test/ 目录中,您可以找到一个示例 Symfony 项目,该项目包含使用此库所需的最小配置。

测试

为了运行我们的 PHPUnit 测试套件,请执行以下命令

composer install
test/app/console doctrine:database:create
test/app/console doctrine:schema:create
vendor/bin/phpunit

错误跟踪和建议

如果您发现了一个错误或有一个很好的改进想法,请在此存储库中打开一个问题

版本控制

版本将以 主要.次要.补丁 格式编号。

并遵循以下准则。

  • 破坏向后兼容性将增加主要版本。
  • 没有破坏向后兼容性的新添加内容将增加次要版本。
  • 错误修复和杂项更改将增加补丁版本。

有关 SemVer 的更多信息,请访问 semver.org 网站

MIT 许可证

许可证可以在这里找到。

作者

该库最初由以下人员创建

Lakion 公司,在 https://github.com/Lakion/ApiTestCase 存储库下。

查看贡献者列表