如何让代码覆盖率达到100%
How to made the code coverage to 100%
最近开始写PHPUnit测试。这是我的模型代码。(我使用的是 CodeIgniter 3)。
Account_model.php
class Account_model extends CI_Model
{
...
public function select_by_seq($seq = '', $select_columns = [])
{
try {
$bind = [':a_seq' => $seq];
// check $select_colums is exist in table
if ($this->check_column($select_columns) === false)
{
throw new Exception('columns illegal', 201);
}
...
$sql = "select ....
from {$this->db->dbprefix('account')}
where a_seq = :a_seq";
$query = $this->db->query($sql, $bind);
// ===== this always not runing. =====
if ($query === false)
{
// ===== this always not runing. =====
throw new Exception('sql errors', 301);
}
else
{
return $query->result_array();
}
}
catch (Exception $error)
{
// set error log
$this->set_error_log($error->getCode() . $error->getMessage());
}
return false;
}
}
这是我的测试Account_model_test.php
class Account_model_test extends TestCase
{
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
$CI =& get_instance();
}
public function setUp()
{
$this->resetInstance();
loader('model', 'account_model');
$this->obj = $this->CI->account_model;
}
public function test_select_by_seq()
{
$result = $this->obj->select_by_seq(
$seq = '20160830'
);
$this->assertCount(1, $result);
}
public function test_select_by_seq_with_illegal_column()
{
$result = $this->obj->select_by_seq(
$seq = '20160830',
$select_columns = ['illegal']
);
$this->assertFalse($result);
}
...
}
因为SQL是我自己写的。我发现我的 PHPUnit 测试无法覆盖这个 if ($query === false)
。然后我的代码覆盖率没有达到 100%。这个问题让我觉得100%对单元测试很重要?或者我必须修改我的模型代码?谢谢你的帮助。
始终保持 100% 的代码覆盖率很好。但是就像你说的那样,有些情况很难做到这一点。因此,对于大多数项目来说,代码覆盖率大于 70% 是相当不错的。有关项目中所需的最低代码覆盖率,请参阅 this link。但是你应该尝试将你的业务逻辑提取到它自己的 class (Repository) 中并对其进行单元测试。
如果您也向我们展示您的测试文件就更好了,这样我们就可以更清楚地了解您已经拥有的内容。
在不知道的情况下,我可以建议使用 Mock of query function,这样它就可以 return false
作为结果。您可以找到更多关于模拟 here
也如前所述:您不应该关注 100% 的代码覆盖率。
The @codeCoverageIgnore
, @codeCoverageIgnoreStart
and @codeCoverageIgnoreEnd
annotations can be used to exclude lines of code from the coverage analysis. -- PHPUnit Manual
PHPUnit 中有示例 documentation。
简而言之,将要被代码覆盖率忽略的代码包裹在*Start
*End
注解中:
if (false) {
// @codeCoverageIgnoreStart
print '*';
// @codeCoverageIgnoreEnd
}
另见 What is a reasonable code coverage % for unit tests (and why)?。
最近开始写PHPUnit测试。这是我的模型代码。(我使用的是 CodeIgniter 3)。
Account_model.php
class Account_model extends CI_Model
{
...
public function select_by_seq($seq = '', $select_columns = [])
{
try {
$bind = [':a_seq' => $seq];
// check $select_colums is exist in table
if ($this->check_column($select_columns) === false)
{
throw new Exception('columns illegal', 201);
}
...
$sql = "select ....
from {$this->db->dbprefix('account')}
where a_seq = :a_seq";
$query = $this->db->query($sql, $bind);
// ===== this always not runing. =====
if ($query === false)
{
// ===== this always not runing. =====
throw new Exception('sql errors', 301);
}
else
{
return $query->result_array();
}
}
catch (Exception $error)
{
// set error log
$this->set_error_log($error->getCode() . $error->getMessage());
}
return false;
}
}
这是我的测试Account_model_test.php
class Account_model_test extends TestCase
{
public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
$CI =& get_instance();
}
public function setUp()
{
$this->resetInstance();
loader('model', 'account_model');
$this->obj = $this->CI->account_model;
}
public function test_select_by_seq()
{
$result = $this->obj->select_by_seq(
$seq = '20160830'
);
$this->assertCount(1, $result);
}
public function test_select_by_seq_with_illegal_column()
{
$result = $this->obj->select_by_seq(
$seq = '20160830',
$select_columns = ['illegal']
);
$this->assertFalse($result);
}
...
}
因为SQL是我自己写的。我发现我的 PHPUnit 测试无法覆盖这个 if ($query === false)
。然后我的代码覆盖率没有达到 100%。这个问题让我觉得100%对单元测试很重要?或者我必须修改我的模型代码?谢谢你的帮助。
始终保持 100% 的代码覆盖率很好。但是就像你说的那样,有些情况很难做到这一点。因此,对于大多数项目来说,代码覆盖率大于 70% 是相当不错的。有关项目中所需的最低代码覆盖率,请参阅 this link。但是你应该尝试将你的业务逻辑提取到它自己的 class (Repository) 中并对其进行单元测试。
如果您也向我们展示您的测试文件就更好了,这样我们就可以更清楚地了解您已经拥有的内容。
在不知道的情况下,我可以建议使用 Mock of query function,这样它就可以 return false
作为结果。您可以找到更多关于模拟 here
也如前所述:您不应该关注 100% 的代码覆盖率。
The
@codeCoverageIgnore
,@codeCoverageIgnoreStart
and@codeCoverageIgnoreEnd
annotations can be used to exclude lines of code from the coverage analysis. -- PHPUnit Manual
PHPUnit 中有示例 documentation。
简而言之,将要被代码覆盖率忽略的代码包裹在*Start
*End
注解中:
if (false) {
// @codeCoverageIgnoreStart
print '*';
// @codeCoverageIgnoreEnd
}
另见 What is a reasonable code coverage % for unit tests (and why)?。