测试 CLI 命令
使用 MockInputOutput
在 4.5.0 版本加入.
MockInputOutput
MockInputOutput 提供了一种简单的方法来编写需要用户输入的命令的测试,例如 CLI::prompt()
、CLI::wait()
和 CLI::input()
。
你可以在测试执行期间用 MockInputOutput
替换 InputOutput
类来捕获输入和输出。
备注
当你使用 MockInputOutput
时,你不需要使用
StreamFilterTrait、CITestStreamFilter 和
PhpStreamWrapper。
辅助方法
getOutput(?int $index = null): string
获取输出。
如果你像
$io->getOutput()
这样调用它,它会返回整个输出字符串。如果你指定
0
或一个正数,它会返回输出数组项。每个项都有一个CLI::fwrite()
调用的输出。如果你指定一个负数
-n
,它会返回输出数组的倒数第n
项。
getOutputs(): array
返回输出数组。每个项都有一个 CLI::fwrite()
调用的输出。
如何使用
CLI::setInputOutput()
可以将MockInputOutput
实例设置到CLI
类。CLI::resetInputOutput()
重置CLI
类中的InputOutput
实例。MockInputOutput::setInputs()
设置用户输入数组。MockInputOutput::getOutput()
获取命令输出。
以下测试代码用于测试命令 spark db:table
:
<?php
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\Mock\MockInputOutput;
final class DbTableTest extends CIUnitTestCase
{
use DatabaseTestTrait;
protected $migrateOnce = true;
public function testDbTable(): void
{
// Set MockInputOutput to CLI.
$io = new MockInputOutput();
CLI::setInputOutput($io);
// User will input "a" (invalid value) and "0".
$io->setInputs(['a', '0']);
command('db:table');
// Get the whole output string.
$output = $io->getOutput();
$expected = 'Which table do you want to see? [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]: a';
$this->assertStringContainsString($expected, $output);
$expected = 'Data of Table "db_migrations":';
$this->assertStringContainsString($expected, $output);
// Remove MockInputOutput.
CLI::resetInputOutput();
}
}
不使用 MockInputOutput
测试 CLI 输出
StreamFilterTrait
在 4.3.0 版本加入.
StreamFilterTrait 提供了这些辅助方法的替代方案。
你可能需要测试一些难以测试的东西。有时,捕获一个流,比如 PHP 自己的 STDOUT 或 STDERR,可能会有所帮助。StreamFilterTrait
帮助你捕获所选流的输出。
如何使用
StreamFilterTrait::getStreamFilterBuffer()
从缓冲区获取捕获的数据。StreamFilterTrait::resetStreamFilterBuffer()
重置捕获的数据。
在你的一个测试用例中演示这一点的示例:
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\StreamFilterTrait;
final class SomeTest extends CIUnitTestCase
{
use StreamFilterTrait;
public function testSomeOutput(): void
{
CLI::write('first.');
$this->assertSame("\nfirst.\n", $this->getStreamFilterBuffer());
$this->resetStreamFilterBuffer();
CLI::write('second.');
$this->assertSame("second.\n", $this->getStreamFilterBuffer());
}
}
StreamFilterTrait
有一个自动调用的配置器。
参见 Testing Traits。
如果你在测试中重写了 setUp()
或 tearDown()
方法,那么你必须分别调用 parent::setUp()
和 parent::tearDown()
方法来配置 StreamFilterTrait
。
CITestStreamFilter
CITestStreamFilter 用于手动/单次使用。
如果你只需要在一个测试中捕获流,那么可以手动向流添加过滤器,而不是使用 StreamFilterTrait trait。
如何使用
CITestStreamFilter::registration()
过滤器注册。CITestStreamFilter::addOutputFilter()
向输出流添加过滤器。CITestStreamFilter::addErrorFilter()
向错误流添加过滤器。CITestStreamFilter::removeOutputFilter()
从输出流中移除过滤器。CITestStreamFilter::removeErrorFilter()
从错误流中移除过滤器。
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\Filters\CITestStreamFilter;
final class SomeTest extends CIUnitTestCase
{
public function testSomeOutput(): void
{
CITestStreamFilter::registration();
CITestStreamFilter::addOutputFilter();
CLI::write('first.');
CITestStreamFilter::removeOutputFilter();
}
}
测试 CLI 输入
PhpStreamWrapper
在 4.3.0 版本加入.
PhpStreamWrapper 提供了一种方法来编写需要用户输入的方法的测试,例如 CLI::prompt()
、CLI::wait()
和 CLI::input()
。
备注
PhpStreamWrapper 是一个流包装类。 如果你不了解 PHP 的流包装器, 请参见 PHP 手册中的 The streamWrapper class。
如何使用
PhpStreamWrapper::register()
将PhpStreamWrapper
注册到php
协议。PhpStreamWrapper::restore()
将 php 协议包装器恢复为 PHP 内置包装器。PhpStreamWrapper::setContent()
设置输入数据。
重要
PhpStreamWrapper 仅用于测试 php://stdin
。
但是当你注册它时,它会处理所有 php 协议 流,
例如 php://stdout
、php://stderr
、php://memory
。
因此强烈建议仅在需要时注册/注销 PhpStreamWrapper
。否则,它在注册时会干扰其他内置的 php 流。
在你的一个测试用例中演示这一点的示例:
<?php
namespace Tests;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\PhpStreamWrapper;
final class SomeTest extends CIUnitTestCase
{
public function testPrompt(): void
{
// Register the PhpStreamWrapper.
PhpStreamWrapper::register();
// Set the user input to 'red'. It will be provided as `php://stdin` output.
$expected = 'red';
PhpStreamWrapper::setContent($expected);
$output = CLI::prompt('What is your favorite color?');
$this->assertSame($expected, $output);
// Restore php protocol wrapper.
PhpStreamWrapper::restore();
}
}