PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, March 9, 2022

[FIXED] CakePHP: write test for table on shell

 March 09, 2022     cakephp, cakephp-3.0, phpunit     No comments   

Issue

I'm writing a plugin for CakePHP that import/export databases. This plugin has a shell and its index() method lists the databases already exported:

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));
    }
}

Output with no database:

$ 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

Output with some databases:

$ 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 |
+-------------------------------------------+-----------+-------------+-----------+-----------------+

Now I need to write some tests.
I wrote the test for no database code:

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

My problem is to write a test of whether the table output (second example).

For now I only wrote this:

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();
}

Output:

$ 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.

So, how to write a test to check the table output? Where can I find an example?


Solution

It depends on how clean you want to do it. I would personally, for speed mainly, not use expectations for the output.

Instead I just collect the output in a "pseudo-mock" kind of container:

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(); This special ConsoleOutput will not write to stdout or stderr, but instead just internally collect it all for you to fetch it afterwards.

After running the command you can then just do

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

Check out the test cases in my tools plugin for details. The link also provides you the tooling you would need for the above example.



Answered By - mark
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing