美文网首页
CakePHP的测试方法

CakePHP的测试方法

作者: esrever | 来源:发表于2017-02-14 11:07 被阅读134次

    CakePHP的测试方法

    CakePHP 测试的文档

    注意

    1. PHPUnit 4 与 CakePHP 的单元测试不兼容
    2. 在 app/Config/core.php 文件中的调试(debug)级别至少是 1。当调试级别是 0 时,无法通过 web 运行器访问测试。在运行任何测试之前,应当确保 添加 $test 数据库配置。该配置被 CakePHP 用于测试夹具(fixture)的表和数据
    3. 当使用 PHPUnit 3.6+ 时,所有的输出都会被吞没。如果使用 CLI,可以添加 --debug 修饰符;如果使用 web 运行器来显示输出,可以添加 &debug=1 到网址中
    4. 在命令行运行使用会话的测试时,需要加上 --stderr 标志。不这么做会导致会话无法 工作。PHPUnit 默认会输出测试进程到标准输出(stdout),这会使 PHP 以为头部信息 已经发送,从而阻止会话启动。把 PHPUnit 输出切换到 stderr,就避免了这个问题

    步骤

    1. 安装PHPUnit
      使用composer安装方法,"phpunit/phpunit": "3.7.32"
    2. (可选)测试数据库的设置,在database.php中添加$test变量
    3. webroot目录有test.php的前提下,可以直接访问localhost/appname/webroot/test.php,如有配置虚拟域名,可能是xx.com/test.php
    4. 测试用例存放目录在/Test/Case中,文件名有要求:必须以Test.php结尾,如UserTest.php,含有测试的类应当扩展 CakeTestCase,ControllerTestCase 或 PHPUnit_Framework_TestCase,所以类名(与文件名对应)示例class UserTest extends CakeTestCase,方法名要求是以test开头,如public function testPublished()
    5. 可以使用web访问的方式测试,也可以用命令行,./Console/cake test app Model/Post,这里的cake命令是在Console目录下的,与执行shell脚本的命令一样,test和app两个参数不需要改变,Model/Post指向的是/Test/Case/Model/PostTest.php
    6. 以下一则测试的例子:
          <?php
              App::uses('Ad', 'Model');
              class AdTest extends CakeTestCase
              {
                  protected $Ad;
      
                  public function setUp() {
                      parent::setUp();
                      $this->Article = ClassRegistry::init('Article');
                  }
      
                  public function testA() {
                      $this->assertEquals(1, 1);
                  }
      
                  public function testB() {
                      $ads = $this->Ad->getRunningAds();
                      var_dump($ads);
                      $this->assertEquals($ads[4397]['banner'][0]['axid'], 4397);
                  }
      
                  public function testC() {
                      $ads = $this->Ad->getRunningAds();
                      var_dump($ads);
                      $this->assertEquals($ads[4397]['banner'][0]['axid'], 4398);
                  }
              }
              /*
                  测试用例有一些生命周期回调函数,可以在测试时使用:
      
                  setUp 在每个测试方法之前调用。应当用来创建要测试的对象,为测试初始化任何 数据。记得一定要调用 parent::setUp()。
                  tearDown 在每个测试方法之后调用。应当用来在测试完成之后进行清理。记得一定 要调用 parent::tearDown()。
                  setupBeforeClass 在一个用例中的测试方法开始之前只调用一次。该方法必须是 静态的。
                  tearDownAfterClass 在一个用例中的测试方法完成之后只调用一次。该方法必须是 静态的。
              */
      
    7. 覆盖率检测:使用xdebug工具,PHPUnit会结合工具检测出测试代码的盲区(无关代码不会影响覆盖率的计算,如测试的是方法A,在运行的过程中没有经过方法B,并不会影响覆盖率;但是方法A中的if语句,只走了其中一个条件,则会提示未覆盖)
      xdebug安装方法
      php-xdebug扩展:composer安装方法"ext-xdebug": ">=2.0.5"

    测试模型

        App::uses('Article', 'Model');
    
        class ArticleTest extends CakeTestCase {
            public $fixtures = array('app.article');
    
            public function setUp() {
                parent::setUp();
                // 在为测试设置模型时,使用 ClassRegistry::init('YourModelName')的原因是它知道要使用测试数据库连接(如果不使用测试数据库和夹具,直接new也可以)
                $this->Article = ClassRegistry::init('Article');
            }
    
            public function testPublished() {
                // Article模型中有一个published方法
                $result = $this->Article->published(array('id', 'title'));
                $expected = array(
                    array('Article' => array('id' => 1, 'title' => 'First Article')),
                    array('Article' => array('id' => 2, 'title' => 'Second Article')),
                    array('Article' => array('id' => 3, 'title' => 'Third Article'))
                );
    
                $this->assertEquals($expected, $result);
            }
        }
    

    测试控制器

    CakePHP 提供了特别的 ControllerTestCase 类。用该类作为控制器测试 用例的基类,让你可以使用 testAction() 方法,使测试用例更简单。 ControllerTestCase 让你容易地模拟组件和模型,以及象 redirect() 这样可能更难测试的方法

        class ArticlesControllerTest extends ControllerTestCase {
            public $fixtures = array('app.article');
    
            public function testIndex() {
                $result = $this->testAction('/articles/index');
                debug($result);
            }
    
            public function testIndexShort() {
                $result = $this->testAction('/articles/index/short');
                debug($result);
            }
    
            public function testIndexShortGetRenderedHtml() {
                $result = $this->testAction(
                   '/articles/index/short',
                    array('return' => 'contents')
                );
                debug($result);
            }
    
            public function testIndexShortGetViewVars() {
                $result = $this->testAction(
                    '/articles/index/short',
                    array('return' => 'vars')
                );
                debug($result);
            }
    
            public function testIndexPostData() {
                $data = array(
                    'Article' => array(
                        'user_id' => 1,
                        'published' => 1,
                        'slug' => 'new-article',
                        'title' => 'New Article',
                        'body' => 'New Body'
                    )
                );
                $result = $this->testAction(
                    '/articles/index',
                    array('data' => $data, 'method' => 'post')
                );
                debug($result);
            }
        }
    

    testAction 方法的 第一个参数应当总是要测试的网址(URL)。CakePHP 会创建一个请求,调度(dispatch) 控制器和动作

    在测试包含 redirect() 方法和其它在重定向(redirect)之后的代码,通常更好的 做法是在重定向时返回。这是因为,redirect() 方法在测试中是模拟的,并不像正常 状态是存在的。它不会使代码退出,而是继续运行重定向之后的代码

        App::uses('AppController', 'Controller');
    
        class ArticlesController extends AppController {
            public function add() {
                if ($this->request->is('post')) {
                    if ($this->Article->save($this->request->data)) {
                        // 如果没有return,测试代码会继续执行下去
                        return $this->redirect(array('action' => 'index'));
                    }
                }
                // 更多代码
            }
        }
    

    第二个参数是传递的请求数据和方法

        public function testAdding() {
            $data = array(
                'Post' => array(
                    'title' => 'New post',
                    'body' => 'Secret sauce'
                )
            );
            // 默认是post,如果get方法,则特别指定
            $this->testAction('/posts/add', array('data' => $data, 'method' => 'get'));
            // 一些断言(*assertion*)。
        }
    

    选择返回类型

    • vars 得到设置的视图(view)变量。
    • view 得到渲染的不含布局(layout)的视图。
    • contents 得到渲染的包含布局(layout)的视图。
    • result 得到控制器动作的返回值。可用于测试 requestAction 方法。

    默认值为 result。只要返回类型不是 result,也可以在测试用例中用属性访问 其它返回类型:

        public function testIndex() {
            $this->testAction('/posts/index');
            $this->assertInternalType('array', $this->vars['posts']);
        }
    

    测试返回 JSON 响应的控制器

        class MarkersControllerTest extends ControllerTestCase {
            public function testIndex() {
                $result = $this->testAction('/markers/index.json');
                $result = json_decode($result, true);
                $expected = array(
                    'Marker' => array('id' => 1, 'lng' => 66, 'lat' => 45),
                );
                $this->assertEquals($expected, $result);
            }
        }
    

    测试视图

    通常大部分应用程序不会直接测试它们的 HTML 代码。这么做经常会导致脆弱、难以维护的 测试套件,容易遭到破坏。在使用 ControllerTestCase 编写功能性测试时, 可以设置 return 选项为 ‘view’ 来检视渲染的视图内容

    创建测试套件

    如果你想要几个测试一起运行,可以创建测试套件。一个测试套件由多个测试用例组成

    如果想要为所有的模型测试创建测试套件,可以创建app/Test/Case/AllModelTest.php

        class AllModelTest extends CakeTestSuite {
            public static function suite() {
                $suite = new CakeTestSuite('All model tests');
                $suite->addTestDirectory(TESTS . 'Case/Model');
                return $suite;
            }
        }
    

    以上代码会把目录 /app/Test/Case/Model/ 中所有的测试用例组织在一起。要添加 单个文件,使用 $suite->addTestFile($filename); 方法

    递归添加一个目录中的所有测试或测试套件:$suite->addTestDirectoryRecursive(TESTS . 'Case/Model');$suite->addTestDirectoryRecursive(TESTS . 'Case');

    相关文章

      网友评论

          本文标题:CakePHP的测试方法

          本文链接:https://www.haomeiwen.com/subject/ocjxwttx.html