CakePHP:在 shell 上为 table 编写测试

CakePHP: write test for table on shell

我正在为 import/export 数据库的 CakePHP 编写一个插件。这个插件有一个 shell 并且它的 index() 方法列出了已经导出的数据库:

public function index()
{
    //Gets alla files
    $files = BackupManager::index();
    $this->out(__d('mysql_backup', 'Backup files found: {0}', count($files)));
    if (!empty($files)) {
        //Parses files
        $files = array_map(function ($file) {
            if (isset($file->compression) && !$file->compression) {
                $file->compression = __d('mysql_backup', 'none');
            }
            $file->size = Number::toReadableSize($file->size);
            return array_values((array)$file);
        }, $files);
        //Table headers
        $headers = [
            __d('mysql_backup', 'Filename'),
            __d('mysql_backup', 'Extension'),
            __d('mysql_backup', 'Compression'),
            __d('mysql_backup', 'Size'),
            __d('mysql_backup', 'Datetime'),
        ];
        $this->helper('table')->output(array_merge([$headers], $files));
    }
}

没有数据库的输出:

$ bin/cake backup

Welcome to CakePHP v3.3.8 Console
---------------------------------------------------------------
App : src
Path: /home/mirko/Server/mirkopagliai/src/
PHP : 7.0.12-1
---------------------------------------------------------------
Backup files found: 0

一些数据库的输出:

$ bin/cake backup

Welcome to CakePHP v3.3.8 Console
---------------------------------------------------------------
App : src
Path: /home/mirko/Server/mirkopagliai/src/
PHP : 7.0.12-1
---------------------------------------------------------------
Backup files found: 2
+-------------------------------------------+-----------+-------------+-----------+-----------------+
| Filename                                  | Extension | Compression | Size      | Datetime        |
+-------------------------------------------+-----------+-------------+-----------+-----------------+
| backup_mirkopagliai_20161113110419.sql.gz | sql.gz    | gzip        | 51,05 KB  | 13/11/16, 11:04 |
| backup_mirkopagliai_20161113110414.sql    | sql       | none        | 150,93 KB | 13/11/16, 11:04 |
+-------------------------------------------+-----------+-------------+-----------+-----------------+

现在我需要写一些测试。
我写了没有数据库代码的测试:

public function testIndexNoBackups()
{
    $this->io->expects($this->once())
        ->method('out')
        ->with('Backup files found: 0', 1);
    $this->BackupShell->index();
}

我的问题是写一个测试是否table输出(第二个例子)。

目前我只写了这个:

public function testIndex()
{
    //Creates a database
    (new BackupExport())->export();

    $this->io->expects($this->once())
        ->method('out')
        ->with('Backup files found: 1', 1);

    $this->BackupShell->index();
}

输出:

$ phpunit tests/TestCase/Shell/BackupShellTest.php --filter testIndex
PHPUnit 5.4.6 by Sebastian Bergmann and contributors.

E.                                                                  2 / 2 (100%)

Time: 114 ms, Memory: 6.00MB

There was 1 error:

1) MysqlBackup\Test\TestCase\Shell\BackupShellTest::testIndex
Error: Call to a member function output() on null

/home/mirko/Libs/Plugins/cakephp-mysql-backup/src/Shell/BackupShell.php:110
/home/mirko/Libs/Plugins/cakephp-mysql-backup/tests/TestCase/Shell/BackupShellTest.php:191

ERRORS!
Tests: 2, Assertions: 1, Errors: 1.

那么,如何编写测试来检查 table 输出?我在哪里可以找到示例?

这取决于您想要清洁的程度。 我个人主要是为了速度,不会对输出使用期望值。

相反,我只是将输出收集在 "pseudo-mock" 类容器中:

php ... use Tools\TestSuite\ConsoleOutput; ... $this->out = new ConsoleOutput(); $this->err = new ConsoleOutput(); $io = new ConsoleIo($this->out, $this->err); $this->Shell = $this->getMockBuilder(InflectShell::class) ->setMethods(['in', '_stop']) ->setConstructorArgs([$io]) ->getMock(); 这个特殊的 ConsoleOutput 不会写入 stdout 或 stderr,而是仅在内部收集所有内容供您之后获取。

在 运行 命令之后,您就可以执行

php $output = $this->out->output(); $expected = 'foo-bar'; $this->assertContains($expected, $output);

查看 test cases in my tools plugin 了解详情。 link 还为您提供了上述示例所需的工具。

感谢@mark。我的解决方案:

...
use Cake\TestSuite\Stub\ConsoleOutput;
use Cake\Console\ConsoleIo;
...

class BackupShellTest extends TestCase
{    
    public function setUp()
    {
        parent::setUp();

        $this->out = new ConsoleOutput();        

        $this->Shell = $this->getMockBuilder('MysqlBackup\Shell\BackupShell')
            ->setMethods(['in', 'err', '_stop', 'clear'])
            ->setConstructorArgs([new ConsoleIo($this->out)])
            ->getMock();
    }

    public function testIndex()
    {
        $this->Shell->index();
        $output = $this->out->messages();

        //Some tests on $output HERE
    }
}

$outputdebug() 示例:

########## DEBUG ##########
[
        (int) 0 => 'Backup files found: 3',
        (int) 1 => '+----------------+-----------+-------------+-----------+--------------------+',
        (int) 2 => '| <info>Filename</info>       | <info>Extension</info> | <info>Compression</info> | <info>Size</info>      | <info>Datetime</info>           |',
        (int) 3 => '+----------------+-----------+-------------+-----------+--------------------+',
        (int) 4 => '| backup.sql.gz  | sql.gz    | gzip        | 443 Bytes | 11/15/16, 11:45 AM |',
        (int) 5 => '| backup.sql.bz2 | sql.bz2   | bzip2       | 523 Bytes | 11/15/16, 11:45 AM |',
        (int) 6 => '| backup.sql     | sql       | none        | 1.23 KB   | 11/15/16, 11:45 AM |',
        (int) 7 => '+----------------+-----------+-------------+-----------+--------------------+'
]
###########################