Browse Source

Added initial ConsoleIntegrationTestCase

Jeremy Harris 8 years ago
parent
commit
899863584f

+ 168 - 0
src/TestSuite/ConsoleIntegrationTestCase.php

@@ -0,0 +1,168 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @since         3.5.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\TestSuite;
+
+use Cake\Console\ConsoleInput;
+use Cake\Console\ConsoleIo;
+use Cake\TestSuite\Stub\ConsoleOutput;
+
+/**
+ * A test case class intended to make integration tests of cake console commands
+ * easier.
+ */
+class ConsoleIntegrationTestCase extends TestCase
+{
+    /**
+     * Whether or not to use the CommandRunner
+     *
+     * @var bool
+     */
+    protected $_useCommandRunner = false;
+
+    /**
+     * Last exit code
+     *
+     * @var int
+     */
+    protected $_exitCode;
+
+    /**
+     * Console output stub
+     *
+     * @var ConsoleOutput
+     */
+    protected $_out;
+
+    /**
+     * Console error output stub
+     *
+     * @var ConsoleOutput
+     */
+    protected $_err;
+
+    /**
+     * Console input mock
+     *
+     * @var ConsoleInput
+     */
+    protected $_in;
+
+    /**
+     * Runs cli integration test
+     *
+     * @param string $command Command to run
+     * @return void
+     */
+    public function cli($command)
+    {
+        $dispatcher = $this->_makeDispatcher("bin/cake $command");
+        $this->_exitCode = $dispatcher->dispatch();
+    }
+
+    /**
+     * tearDown
+     *
+     * @return void
+     */
+    public function tearDown()
+    {
+        parent::tearDown();
+
+        $this->_exitCode = null;
+        $this->_io = null;
+        $this->_out = null;
+        $this->_err = null;
+        $this->_in = null;
+        $this->_useCommandRunner = false;
+    }
+
+    /**
+     * Set this test case to use the CommandRunner rather than the legacy
+     * ShellDispatcher
+     *
+     * @return void
+     */
+    public function enableCommandRunner()
+    {
+        $this->_useCommandRunner = true;
+    }
+
+    /**
+     * Asserts shell exited with the expected code
+     *
+     * @param int $expected Expected exit code
+     * @return void
+     */
+    public function assertExitCode($expected)
+    {
+        $this->assertSame($this->_exitCode, $expected);
+    }
+
+    /**
+     * Asserts `stdout` contains expected output
+     *
+     * @param string $expected Expected output
+     * @return void
+     */
+    public function assertOutputContains($expected)
+    {
+        $output = implode(PHP_EOL, $this->_out->messages());
+        $this->assertContains($expected, $output);
+    }
+
+    /**
+     * Builds the appropriate command dispatcher
+     *
+     * @param string $command Command
+     * @return LegacyShellDispatcher
+     */
+    protected function _makeDispatcher($command)
+    {
+        $args = $this->_commandStringToArgs($command);
+
+        if ($this->_useCommandRunner) {
+            // not implemented yet
+            return;
+        }
+
+        $this->_out = new ConsoleOutput();
+        $this->_err = new ConsoleOutput();
+        $this->_in = $this->getMockBuilder(ConsoleInput::class)
+            ->disableOriginalConstructor()
+            ->setMethods(['read'])
+            ->getMock();
+
+        $io = new ConsoleIo($this->_out, $this->_err, $this->_in);
+
+        return new LegacyShellDispatcher($args, true, $io);
+    }
+
+    /**
+     * Dispatches the command string to a script that returns the argv array
+     * parsed by PHP
+     *
+     * @param string $command Command string
+     * @return array
+     */
+    protected function _commandStringToArgs($command)
+    {
+        $argvScript = CORE_TESTS . 'argv.php';
+        $jsonArgv = shell_exec("$argvScript $command");
+
+        $argv = json_decode($jsonArgv);
+        array_shift($argv);
+
+        return $argv;
+    }
+}

+ 43 - 0
src/TestSuite/LegacyShellDispatcher.php

@@ -0,0 +1,43 @@
+<?php
+namespace Cake\TestSuite;
+
+use Cake\Console\ShellDispatcher;
+
+class LegacyShellDispatcher extends ShellDispatcher
+{
+    /**
+     * @var \Cake\Console\ConsoleIo
+     */
+    protected $_io;
+
+    /**
+     * Constructor
+     *
+     * @param array $args the argv from PHP
+     * @param bool $bootstrap Should the environment be bootstrapped.
+     * @param \Cake\Console\ConsoleIo $io The ConsoleIo class to use.
+     * @return void
+     */
+    public function __construct($args = [], $bootstrap = true, $io = null)
+    {
+        $this->_io = $io;
+
+        parent::__construct($args, $bootstrap);
+    }
+
+    /**
+     * Injects mock and stub io components into the shell
+     *
+     * @param string $className Class name
+     * @param string $shortName Short name
+     * @return \Cake\Console\Shell
+     */
+    protected function _createShell($className, $shortName)
+    {
+        list($plugin) = pluginSplit($shortName);
+        $instance = new $className($this->_io);
+        $instance->plugin = trim($plugin, '.');
+
+        return $instance;
+    }
+}

+ 51 - 0
tests/TestCase/TestSuite/ConsoleIntegrationTestCaseTest.php

@@ -0,0 +1,51 @@
+<?php
+namespace Cake\Test\TestCase\TestSuite;
+
+use Cake\Console\Shell;
+use Cake\TestSuite\ConsoleIntegrationTestCase;
+
+class ConsoleIntegrationTestCaseTest extends ConsoleIntegrationTestCase
+{
+
+    /**
+     * tests cli
+     *
+     * @return void
+     */
+    public function testCli()
+    {
+        $this->cli('');
+
+        $this->assertOutputContains('Welcome to CakePHP');
+        $this->assertExitCode(Shell::CODE_ERROR);
+    }
+
+    /**
+     * tests a valid core command
+     *
+     * @return void
+     */
+    public function testCliCoreCommand()
+    {
+        $this->cli('routes');
+
+        $this->assertOutputContains('Welcome to CakePHP');
+        $this->assertExitCode(Shell::CODE_SUCCESS);
+    }
+
+    /**
+     * tests _commandStringToArgs
+     *
+     * @return void
+     */
+    public function testCommandStringToArgs()
+    {
+        $result = $this->_commandStringToArgs('command --something=nothing --with-spaces="quote me on that"');
+        $expected = [
+            'command',
+            '--something=nothing',
+            '--with-spaces=quote me on that'
+        ];
+        $this->assertSame($expected, $result);
+    }
+}

+ 18 - 0
tests/argv.php

@@ -0,0 +1,18 @@
+#!/usr/bin/php -q
+<?php
+/**
+ * Return $argv array as it is parsed by PHP. Used for testing.
+ *
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.5.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+echo json_encode($argv);