问题
When testing controllers, I can legitimately achieve 100% code coverage, as shown here:
Example of Correct Report of 100% Code Coverage
Controller Code
<?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'));
}
}
Test Code
<?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']);
}
}
However, how can I be sure that I've achieved 100% code coverage in my views? For example:
Example of Incorrect Report of 100% Code Coverage
Controller Code
<?php
App::uses('AppController', 'Controller');
class UsersController extends AppController {
public function example($option = null) {
$this->set('option', $option);
}
}
View Code
<?php
if ($option == 'foo') {
$some_var = 'hello';
} elseif ($option == 'bar') {
$some_var = 'goodbye';
}
if (isset($some_var)) {
echo $some_var;
}
Test Code
<?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);
}
}
Notice that the above test code doesn't test the "/users/example/bar" URL, and thus the view's elseif
is never tested. So even though 100% of the controller's code was tested, I haven't actually achieved 100% code coverage (since less than 100% of the view's code was tested). What can I do about this?
回答1:
To answer the question in the title, CakePHP can use XDebug to pull out your test's code coverage. If I remember correctly, it embeds the code coverage render into the test suite.
As a general comment on the example you've given above, IMHO I would even go to the extent of testing the controller when no option is passed to ensure it responds in the manner expected, even if it throws an exception.
Update
My apologies for not reading @Nick's question properly.
To my knowledge, CakePHP doesn't pull up the code coverage of .ctp
files. That does not mean however the XDebug doesn't generate it and you can probably use your IDE (I use PhpStorm which has a tool) or the XDebug itself to pull back the code coverage directly. Granted, this doesn't make testing as smooth as using the test suite within CakePHP alone.
Alternatively, you can test against the rendered view. According to the documentation it is possible to specify the return type when testing actions. Therefore one possible solution would be compare either the view
or contents
against a pre-rendered file. There is a danger with this however because any invisible characters ('\n', '\r', '\t'
) may cause the assert to fail even though logically, the target and result markup are identical.
One example in the documentation shows how you can assert values using regex allowing you to inspect specific areas of the document for validity. You could also use PHP's DOM classes to traverse the document instead.
Good luck!
Update 21:21 09/05/2013
CakePHP's test suite is build upon PHP Unit which in turn, uses XDebug to generate code coverage. I had a look around the source and inspected the BaseCoverageReport
class and discovered that coverage is generated for any framework files used running the test, including the unit under test (e.g. your controller). This suggests to me that code coverage is not selectively turned on and that it is generated for all files including the view template. With that said, I failed to find the template as one of the files it had generated code coverage for. However, I did note that code coverage wasn't generated for the View
class which means that nothing is being rendered. It was at this point I was getting a little confused since I would imagine that something would have to be rendered in order to access the view
or contents
properties of the controller test case. On closer inspection, it turns out these values were empty so it seems something may be wrong with my setup.
What I suggest you do is get hold of an open source IDE which supports debugging like PHP Development Tools for Eclipse and stick a break-point in your code and follow the thread through the framework. This will give you greater insight into how views are rendered when testing controllers and if so, will help track down the code coverage. I personally would have thought code coverage for templates would be quite useful and I'm surprised that the functionality doesn't exist. If you do choose to modify the framework's source, it might be worth cloning CakePHP in GitHub and then add a pull request so they can merge in your changes into the main branch.
I'm sorry I couldn't be of any more help, I took my best shot at it!
来源:https://stackoverflow.com/questions/16465952/how-can-i-check-view-code-coverage-with-cakephp-tests