tarantool/phpunit-extras

为 PHPUnit 提供一组辅助工具,以简化 Tarantool 库的测试。

v0.2.1 2022-10-21 20:37 UTC

This package is auto-updated.

Last update: 2024-09-22 00:46:09 UTC


README

Quality Assurance Telegram

PHPUnit 提供一组辅助工具,以简化 Tarantool 库的测试。它基于 rybakit/phpunit-extras,请参阅此包获取更多文档。

目录

安装

composer require --dev tarantool/phpunit-extras

注解

除了由包 rybakit/phpunit-extras 提供的注解外,该库还附带针对 Tarantool 特定的注解。最简单的方法是通过从 Tarantool\PhpUnit\TestCase 继承您的测试类来启用它们。

use Tarantool\Client\Client;
use Tarantool\PhpUnit\TestCase;

final class MyTest extends TestCase
{
    protected function getClient() : Client
    {
        // TODO: Implement getClient() method.
    }
    
    // ...
}

另一种选择是注册一个名为 AnnotationExtension 的扩展。

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
    bootstrap="vendor/autoload.php"
>
    <!-- ... -->

    <extensions>
        <extension class="Tarantool\PhpUnit\Annotation\AnnotationExtension" />
    </extensions>
</phpunit>

默认情况下,该扩展假定您将要连接的 Tarantool 服务器位于 127.0.0.1:3301。您可以通过指定 DSN 字符串 或一个 选项数组 作为扩展配置值来自定义默认设置。

<extension class="Tarantool\PhpUnit\Annotation\AnnotationExtension">
    <arguments>
        <string>tcp://127.0.0.1:3301/?socket_timeout=10</string>
    </arguments>
</extension>

或者

<extension class="Tarantool\PhpUnit\Annotation\AnnotationExtension">
    <arguments>
        <array>
            <element key="uri">
                <string>tcp://127.0.0.1:3301</string>
            </element>
            <element key="socket_timeout">
                <integer>10</integer>
            </element>
        </array>
    </arguments>
</extension>

此外,配置值可以解析环境变量,这在您需要与 Tarantool 实例文件或任何其他脚本共享相同设置时可能很有用。

<extension class="Tarantool\PhpUnit\Annotation\AnnotationExtension">
    <arguments>
        <string>tcp://%env(TARANTOOL_HOST)%:%env(TARANTOOL_PORT)%</string>
    </arguments>
</extension>

一旦配置了注解,您就可以开始使用它们了。

处理器

Lua

允许在运行测试之前执行 Lua 代码。

示例

/**
 * @lua tube:put('kick_me')
 * @lua tube:bury(0)
 */
public function testKickReleasesBuriedTask() : void
{
    // ...
}

Sql

允许在运行测试之前执行 SQL 语句(需要 Tarantool 2.0+)。

示例

/**
 * @sql DROP TABLE IF EXISTS foobar
 * @sql CREATE TABLE foobar (id INTEGER PRIMARY KEY, name VARCHAR(50))
 * @sql INSERT INTO foobar VALUES (1, 'A'), (2, 'B')
 */ 
public function testExecuteQueryFetchesAllRows() : void
{
    // ...
}

要求

要求允许根据先决条件跳过测试。

LuaCondition

格式

@requires luaCondition <condition>

其中 <condition> 是一个任意 Lua 表达式,应该评估为布尔值。

示例

/**
 * @requires luaCondition box.session.user() ~= 'guest'
 */
public function testChangeUserPassword() : void
{
    // ...
}

TarantoolVersion

格式

@requires Tarantool <version-constraint>

其中 <version-constraint> 是类似 Composer 的版本约束。有关支持的格式详细信息,请参阅 Composer 的 文档

示例

/**
 * @requires Tarantool ^2.3.2 
 */
public function testPrepareCreatesPreparedStatement() : void
{
    // ...
}

如果您对如何创建和注册自己的注解和要求感兴趣,请参阅 rybakit/phpunit-extrasREADME

期望

请求

要测试您的代码是否发送(或未发送)某些请求,以下方法可用

  • TestCase::expect<REQUEST_NAME>RequestToBeCalled(int $count) : void
  • TestCase::expect<REQUEST_NAME>RequestToBeCalledAtLeast(int $count) : void
  • TestCase::expect<REQUEST_NAME>RequestToBeCalledAtMost(int $count) : void
  • TestCase::expect<REQUEST_NAME>RequestToBeCalledOnce() : void
  • TestCase::expect<REQUEST_NAME>RequestToBeCalledAtLeastOnce() : void
  • TestCase::expect<REQUEST_NAME>RequestToBeCalledAtMostOnce() : void
  • TestCase::expect<REQUEST_NAME>RequestToBeNeverCalled() : void
  • TestCase::expectNoRequestToBeCalled() : void

其中 <REQUEST_NAME> 是请求的名称,例如 CallInsert 等。这些方法是 Tarantool\PhpUnit\TestCase 类的一部分,但也可以通过特质启用。

use PHPUnit\Framework\TestCase;
use PHPUnitExtras\Expectation\Expectations as BaseExpectations;
use Tarantool\Client\Client;
use Tarantool\PhpUnit\Expectation\RequestExpectations;

final class MyTest extends TestCase
{
    use BaseExpectations;
    use RequestExpectations;

    protected function getClient() : Client
    {
        // TODO: Implement getClient() method.
    }

    /**
     * @after
     */
    protected function verifyTestCaseExpectations() : void
    {
        $this->verifyExpectations();
    }

    // ...
}

示例

public function testGetSpaceIsCached() : void
{
    $this->client->flushSpaces();

    $this->expectSelectRequestToBeCalledOnce();
    $this->client->getSpace('test_space');
    $this->client->getSpace('test_space');
}

预编译语句

为了断言预编译语句的分配,请使用 Tarantool\PhpUnit\Expectation\PreparedStatementExpectations 特性,它包含以下方法

  • expectPreparedStatementToBe<TYPE>(int $count) : void
  • expectPreparedStatementToBe<TYPE>AtLeast(int $count) : void
  • expectPreparedStatementToBe<TYPE>AtMost(int $count) : void
  • expectPreparedStatementToBe<TYPE>Once() : void
  • expectPreparedStatementToBeNever<TYPE>() : void
  • expectPreparedStatementToBe<TYPE>AtLeastOnce() : void
  • expectPreparedStatementToBe<TYPE>AtMostOnce() : void

其中 <TYPE> 可以是 AllocatedDeallocated

示例

public function testCloseDeallocatesPreparedStatement() : void
{
    $stmt = $this->client->prepare('SELECT ?');

    $this->expectPreparedStatementToBeDeallocatedOnce();
    $stmt->close();
}

要一次性启用所有上述期望方法,请使用 Tarantool\PhpUnit\Expectation\Expectations 特性,或者扩展 Tarantool\PhpUnit\TestCase 类。

模拟

该库提供了一些辅助类,用于为 Tarantool 客户端 创建测试替身,以避免向 Tarantool 服务器发送真实请求。为了方便创建此类对象,请在测试类中添加特性 TestDoubleClient

use PHPUnit\Framework\TestCase;
use Tarantool\PhpUnit\Client\TestDoubleClient;

final class MyTest extends TestCase
{
    use TestDoubleClient;

    // ...
}

如果您的测试用例扩展了 Tarantool\PhpUnit\TestCase 类,则此步骤不是必需的,因为特性已包含在该类中。

可以通过以下方式创建一个模拟客户端对象

public function testFoo() : void
{
    $dummyClient = $this->createDummyClient();

    // ...
}

要模拟特定场景,例如建立与服务器的连接或从服务器按特定顺序返回特定响应,请使用 TestDoubleClientBuilder 类的功能。例如,要模拟 PING 请求

use Tarantool\Client\Request\PingRequest;
use Tarantool\PhpUnit\TestCase;

final class MyTest extends TestCase
{
    public function testFoo() : void
    {
        $mockClient = $this->getTestDoubleClientBuilder()
            ->shouldSend(new PingRequest())
            ->build();

        // ...
    }

    // ...
}

另一个示例,发送两个 EVALUATE 请求并返回每个请求的不同响应

use Tarantool\Client\RequestTypes;
use Tarantool\PhpUnit\Client\TestDoubleFactory;
use Tarantool\PhpUnit\TestCase;

final class MyTest extends TestCase
{
    public function testFoo() : void
    {
        $mockClient = $this->getTestDoubleClientBuilder()
            ->shouldSend(
                RequestTypes::EVALUATE, 
                RequestTypes::EVALUATE
            )->willReceive(
                TestDoubleFactory::createResponseFromData([2]),
                TestDoubleFactory::createResponseFromData([3])
            )->build();
    
        // ...
    }

    // ...
}

上述示例可以简化为

$mockClient = $this->getTestDoubleClientBuilder()
    ->shouldHandle(
        RequestTypes::EVALUATE,
        TestDoubleFactory::createResponseFromData([2]),
        TestDoubleFactory::createResponseFromData([3])
    )->build();

此外,构建器允许设置自定义的 ConnectionPacker 实例

$stubClient = $this->getMockClientBuilder()
    ->willUseConnection($myConnection)
    ->willUsePacker($myPacker)
    ->build();

测试

在运行测试之前,必须安装开发依赖项

composer install

然后,运行所有测试

vendor/bin/phpunit
vendor/bin/phpunit -c phpunit-extension.xml

许可证

该库采用 MIT 许可证发布。有关详细信息,请参阅捆绑的 LICENSE 文件。