【问题标题】:How Can I Check View Code Coverage with CakePHP Tests?如何使用 CakePHP 测试检查代码覆盖率?
【发布时间】:2013-05-04 04:12:43
【问题描述】:

在测试控制器时,我可以合法地实现 100% 的代码覆盖率,如下所示:

100% 代码覆盖率的正确报告示例

控制器代码

<?php
App::uses('AppController', 'Controller');

class UsersController extends AppController {

    public function example($option = null) {
        if ($option == 'foo') {
            $some_var = 'hello';
        } elseif ($option == 'bar') {
            $some_var = 'goodbye';
        }

        $this->set(compact('option', 'some_var'));
    }
}

测试代码

<?php
App::uses('UsersController', 'Controller');

class UsersControllerTest extends ControllerTestCase {

    public function testExampleFoo() {
        $this->testAction('/users/example/foo');
        $this->assertEquals('hello', $this->vars['some_var']);
    }

    public function testExampleBar() {
        $this->testAction('/users/example/bar');
        $this->assertEquals('goodbye', $this->vars['some_var']);
    }
}

但是,我如何确定我的视图中实现了 100% 的代码覆盖率?例如:

100% 代码覆盖率错误报告示例

控制器代码

<?php
App::uses('AppController', 'Controller');

class UsersController extends AppController {

    public function example($option = null) {
        $this->set('option', $option);
    }
}

查看代码

<?php

if ($option == 'foo') {
    $some_var = 'hello';
} elseif ($option == 'bar') {
    $some_var = 'goodbye';
}

if (isset($some_var)) {
    echo $some_var;
}

测试代码

<?php
App::uses('UsersController', 'Controller');

class UsersControllerTest extends ControllerTestCase {

    public function testExampleFoo() {
        $result = $this->testAction('/users/example/foo', array('return' => 'view'));
        $this->assertEquals('hello', $result);
    }
}

请注意,上面的测试代码没有测试“/users/example/bar” URL,因此视图的elseif 从未被测试过。因此,即使 100% 的控制器代码经过测试,我实际上并没有达到 100% 的代码覆盖率(因为测试的视图代码不到 100%)。我该怎么办?

【问题讨论】:

  • 还请记住,这些是单元测试。您的控制器测试estExampleFoo() 旨在为 UsersController::example() 方法本身提供覆盖, 您的.ctp 文件。正如 Sam 所暗示的那样,测试您的 ctps 通常更多地属于“集成”测试的标题。由于您提到的原因,在您的视图中放置分支和逻辑在测试环境中通常是一个坏主意。相反,创建使用您的视图变量的助手并确定应该显示的内容。这样你的 Helper 就可以很容易地自行测试了。

标签: cakephp testing code-coverage


【解决方案1】:

要回答标题中的问题,CakePHP can use XDebug 以提取测试的代码覆盖率。如果我没记错的话,它会将代码覆盖率渲染嵌入到测试套件中。

作为对您上面给出的示例的一般评论,恕我直言,我什至会在没有传递任何选项时测试控制器以确保它以预期的方式响应,即使它抛出异常也是如此。

更新

对于没有正确阅读@Nick 的问题,我深表歉意。

据我所知,CakePHP 不会提高 .ctp 文件的代码覆盖率。这并不意味着 XDebug 不会生成它,您可能可以使用您的 IDE(我使用具有 tool 的 PhpStorm)或 XDebug 本身直接拉回代码覆盖率。当然,这并不能使测试像在 CakePHP 中单独使用测试套件那样顺利。

或者,您可以针对渲染的视图进行测试。根据documentation,可以在测试动作时指定返回类型。因此,一种可能的解决方案是将viewcontents 与预渲染文件进行比较。但是这样做存在危险,因为任何不可见的字符 ('\n', '\r', '\t') 都可能导致断言失败,即使在逻辑上,目标和结果标记是相同的。

documentation 中的一个示例显示了如何使用正则表达式断言值,从而允许您检查文档的特定区域的有效性。您也可以使用 PHP 的 DOM classes 来遍历文档。

祝你好运!

2013 年 9 月 5 日 21:21 更新

CakePHP 的测试套件建立在 PHP 单元之上,而 PHP 单元又使用 XDebug 生成代码覆盖率。我查看了源代码并检查了BaseCoverageReport 类,发现运行测试时使用的任何框架文件都生成了覆盖率,包括被测单元(例如您的控制器)。这向我表明,代码覆盖没有选择性地打开,它是为包括视图模板在内的所有文件生成的。话虽如此,我没有找到模板作为它为其生成代码覆盖率的文件之一。但是,我确实注意到没有为 View 类生成代码覆盖率,这意味着没有渲染任何内容。正是在这一点上,我有点困惑,因为我想必须渲染一些东西才能访问控制器测试用例的viewcontents 属性。仔细检查后发现这些值是空的,所以我的设置似乎有问题。

我建议你做的是获取一个支持调试的开源 IDE,比如PHP Development Tools for Eclipse,并在你的代码中设置一个断点,并通过框架跟踪线程。这将使您更深入地了解在测试控制器时视图是如何呈现的,如果是这样,将有助于跟踪代码覆盖率。我个人认为模板的代码覆盖率会非常有用,我很惊讶该功能不存在。如果您确实选择修改框架的源代码,则可能值得在 GitHub 中克隆 CakePHP,然后添加拉取请求,以便它们可以将您的更改合并到主分支中。

很抱歉我帮不上什么忙,我已经尽力了!

【讨论】:

  • 谢谢。标题中的问题专门指的是 view 代码,而不是控制器代码。我该怎么做?
  • 对不起@Nick,我没有正确阅读你的问题。我希望我的更新更准确地回答了您的问题。
  • 没问题。感谢更新!您说“这并不意味着 XDebug 不会生成它,您可能可以使用您的 IDE(我使用具有工具的 PhpStorm)或 XDebug 本身来直接拉回代码覆盖率。”。你介意详细说明一下吗?查看 .ctp 文件的代码覆盖率正是我想要做的。我使用 Sublime Text 2,所以我想我会使用您所说的“XDebug 本身”方法。我只是不知道该怎么做。
  • 嗨@Nick,我已经更新了我的答案,为您提供更多背景知识。我不认为我可以直接回答你的问题,但我代表你做了一些探索性的工作并报告了我的发现。祝你好运!
  • 感谢您的辛勤工作!对此,我真的非常感激。我投票给你。我会给其他人更多时间来回答这个问题。如果没有人能提供更好的答案,我会接受你的。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2014-05-18
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多