4

I want to write unit tests for a CakePHP shell that I'm creating, but they aren't mentioned in the testing documentation or bake:

---------------------------------------------------------------
Bake Tests
Path: /home/brad/sites/farmlogs/app/Test/
---------------------------------------------------------------
---------------------------------------------------------------
Select an object type:
---------------------------------------------------------------
1. Model
2. Controller
3. Component
4. Behavior
5. Helper
Enter the type of object to bake a test for or (q)uit (1/2/3/4/5/q) 

Since CakePHP doesn't appear to have a default shell testing setup, what should the structure of my basic shell tests look like?

2 Answers 2

5

Judging from examples in Mark Story's AssetCompress and the CakeDC's Migrations, just mimic the directory structure for other tests:

Test/
  Case/
    Console/
      Command/
        Task/
          MyShellTaskTest.php
        MyShellTest.php

Your tests can just extend the CakeTestCase object, just like any other generic test:

class MyShellTest extends CakeTestCase {
}

If needed, you can override the base shell, just like you would do with a Controller test:

class TestMyShell extends MyShell {
}

Nothing all that special, just stick with the conventions.

Sign up to request clarification or add additional context in comments.

Comments

1

I think app/lib/lib/Cake/Console/Command/TestShellTest.php can be a reference.

1、create file in app/Test/Case/Console/Command/yourfile.php, state your classes using App::uses('your class', 'relative path').
for example:

App::uses('yourShellClass', 'Console/Command');
App::uses('ShellDispatcher', 'Console');
App::uses('Shell', 'Console');

2、write a mock class B from your shell class A, whose function use data returns in class A. for example:

 class TestYourShellClass extends YourShellClass {
         public function F1 ($parms){
               //if you need use database here, you can 
               //$this->yourModel = ClassRegistry::init('yourModel');
               return $this->_F1($parms);      
         }

    }

3、write test class of class A, you need to init it in startup. for example:

 class YourShellClassTest extends CakeTestCase {
        public function setUp()
        {
            parent::setUp();
            $out = $this->getMock('ConsoleOutput', [], [], '', false);
            $in = $this->getMock('ConsoleInput', [], [], '', false);
            $this->Shell = $this->getMock(
                // this is your class B, which mocks class A.
                'TestYourShellClass',
                ['in', 'out', 'hr', 'help', 'error', 'err', '_stop', 'initialize', '_run', 'clear'],
                [$out, $out, $in]
            );
            $this->Shell->OptionParser = $this->getMock('ConsoleOptionParser', [], [null, false]);
        }

        /**
         *  tear down method.
         *  
         *  @return void
         */
        public function tearDown()
        {
            parent::tearDown();
            unset($this->Dispatch, $this->Shell);
        }       
   }

4、 the test function can be like this.

 /**
 *  test _F1.
 *  
 *  @return void
 */
public function testF1()
{
    $this->Shell->startup();
    $return = $this->Shell->F1();
    $expectedSellerCount = 14;
    $this->assertSame($expectedSellerCount, $return);
}

and then you can view result in http://yourdomain/test.php

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.