lark/resttest

0.26.0 2023-05-19 14:56 UTC

This package is auto-updated.

Last update: 2024-09-19 17:59:14 UTC


README

RestTest 是一个用于测试 REST API 端点的测试库。

安装

composer require lark/resttest

设置测试目录

创建一个测试目录,例如 ./tests/Rest,并添加一个运行测试文件,例如 ./tests/Rest/run.php

<?php
use LarkRestTest\RestTest;

require_once '../../app/bootstrap.php';

// setup autoloading for tests/Rest dir
// this can also be done in composer.json using require-dev
$loader = new Composer\Autoload\ClassLoader;
$loader->addPsr4('Tests\\', dirname(__DIR__, 1));
$loader->register();

// handle options, like debugging
$argv = $_SERVER['argv'] ?? [];
$isDebug = false;
if (in_array('--debug', $argv) || in_array('-d', $argv))
{
    $isDebug = true;
}

// run tests using base namespace and directory
RestTest::run('Tests\Rest', __DIR__, $isDebug);

创建测试类

可以在 ./tests/Rest 目录中创建测试类,并且必须以 Test.php 结尾。创建一个第一个测试类,例如 ./tests/Rest/UserTest.php

namespace Tests\Rest;
use LarkRestTest\RestTest;

class UserTest extends RestTest
{
    public function __construct()
    {
        // HTTP client must be initialized with a base URL before
        // any client methods can be called
        $this->client('https://');
    }

    /**
     * Create users
     * @test
     */
    public function create(): void
    {
        // send request:
        // POST /users
        // [{"name":"test"},{"name":"test2"}]
        $this->clientPost('/users', [
            ['name' => 'test'],
            ['name' => 'test2']
        ]);

        // must be response status code 200
        $this->expectCodeOk();

        // body must be the same as this
        // because "id" will be unknown use "$$VAR" to allow any value
        $this->expectBodySame([
            ['id' => '$$VAR', 'name' => 'test'],
            ['id' => '$$VAR', 'name' => 'test2']
        ]);

        // save IDs for later tests
        $this->ids('user');
    }

    /**
     * Delete user
     * @test
     * @depends create
     */
    public function deleteOne(): void
    {
        // get ID from earlier save in create method
        $id = $this->id('user');
        // also can use $this->id('user', 1); to get ID at exact index

        $this->clientDelete('/users/' . $id);

        $this->expectCodeOk();
        $this->expectBodySame(['affected' => 1]);
    }
}

每个测试类方法必须是测试,必须在 docblock 中有 @test,否则在运行测试时将被忽略。

如果方法依赖于另一个方法或多个方法,应该在方法的 docblock 中使用 @depends [METHODNAME] 注释,例如 @depends create

如果类依赖于另一个类,应在类的 docblock 中使用 @depends [CLASSNAME] 注释,例如 @depends \Tests\Rest\UserTest

所有以 Test.php 结尾的类都将被视为测试。要排除以 Test.php 结尾的类文件从测试中,请在类的 docblock 中使用 @ignore

清理函数

测试方法可以返回一个 callable,用作清理函数,将在测试方法调用后被调用,例如

    /**
     * Delete user
     * @test
     * @depends create
     */
    public function deleteOne(): callable
    {
        // ...

        return function() {
            // do cleanup here
        };
    }

比较响应体

有时响应体对象数组可能是随机排序的,这可能导致使用 RestTest::expectBodySame 时测试失败。例如

    /**
     * Update users
     * @test
     * @depends create
     */
    public function update(): void
    {
        $this->clientPatch('/users', [
            [
                'id' => $this->id('user', 1),
                'name' => 'test5'
            ],
            [
                'id' => $this->id('user', 2),
                'name' => 'test6'
            ]
        ]);

        // this will possibly fail depending on the order of objects
        // returned in the response body
        $this->expectBodySame([
            [
                'id' => $this->id('user', 1),
                'name' => 'test5'
            ],
            [
                'id' => $this->id('user', 2),
                'name' => 'test6'
            ]
        ])
    }

为了解决这个问题,可以使用 RestTest::expectBodySameSorted 方法来自动按特定字段(默认为 id)对预期数组对象和响应体对象数组进行排序。

运行测试

要运行测试,请转到包含运行测试文件的测试目录,例如 ./tests/Rest,并执行运行文件

$ php run.php

Running tests...
------------------------------------------------------------------------------------------
  Base namespace: Tests\Rest
  Base directory: /myproject/tests/Rest
  Test classes: 1
------------------------------------------------------------------------------------------
001) 200 Tests\Rest\UserTest::create    # Create users [0.0475s]
002) 200 Tests\Rest\UserTest::deleteOne    # Delete user [0.0312s]
------------------------------------------------------------------------------------------
 OK  (Tests: 2, Assertions: 4) in 0.0874s