自定义PHPUnit约束已停止工作
我自己创建了一个自定义PHPUnit约束,并将其连接到一个漂亮的自定义PHPUnit约束已停止工作,php,phpunit,Php,Phpunit,我自己创建了一个自定义PHPUnit约束,并将其连接到一个漂亮的assert…函数 我将它插入我的基本TestCase,它是assertLastError函数: /** * abstract, base test-case class. */ abstract class TestCase extends \PHPUnit_Framework_TestCase { /** * assert lint of a php file */ protected f
assert…
函数
我将它插入我的基本TestCase
,它是assertLastError
函数:
/**
* abstract, base test-case class.
*/
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* assert lint of a php file
*/
protected function assertLint($filename, $message = '') {
self::assertThat($filename, new ConstraintLint, $message);
}
/**
* assert the last error
*/
protected function assertLastError($error, $file, $message = '') {
self::assertThat($file, new ConstraintLastError($error), $message);
}
/**
* assert XML DTD validity
*/
protected function assertXmlStringValidatesDtdUri($xml, $dtd, $message = '') {
self::assertThat($dtd, new ConstraintXmlStringValidatesDtdUri($xml), $message);
}
...
到目前为止,我已经调试了约束,我看到调用了evaluate
方法并返回FALSE
,但是testrunner没有向我报告失败
约束条件:
/**
* ConstraintLastError
*
* For asserting the last error message in a file.
*
* To test trigger_error().
*
* Example:
*
* $this->assertLastError('Error Message', 'basenameOfFile.php');
*
*/
class ConstraintLastError extends \PHPUnit_Framework_Constraint {
private $file;
private $error;
public function __construct($error) {
$this->error = $error;
}
/**
* Evaluates the constraint for parameter $file. Returns TRUE if the
* constraint is met, FALSE otherwise.
*
* @param string $file Value or object to evaluate.
* @return bool
*/
public function evaluate($file)
{
$this->file = $file;
$error = $this->error;
$lastError = error_get_last();
if (NULL === $lastError)
return false;
$last_message = $lastError['message'];
$last_file = $lastError['file'];
$result = ($error == $last_message && basename($file) == basename($last_file));
var_dump($result, $error, $last_message, $file, $last_file);
return $result;
}
/**
* @param mixed $other
* @param string $description
* @param boolean $not
*/
protected function customFailureDescription($other, $description, $not)
{
return sprintf('Failed asserting that the last error %s', basename($other), $not ? '' : 'no ', implode("\n - ", $this->lines));
}
/**
* Returns a string representation of the constraint.
*
* @return string
*/
public function toString()
{
return sprintf('was %s in file %s.', $this->error, $this->file);
}
}
我不知道为什么会停止工作,测试用例刚刚干净地完成,我可以在输出中看到错误消息,包括stacktrace(xdebug处于打开状态),并且var\u dump
告诉我结果是FALSE
。以下是测试:
public function testGetType()
{
...
$fragment->setParsed(array());
\PHPUnit_Framework_Error_Warning::$enabled = FALSE;
$actual = $fragment->getType();
\PHPUnit_Framework_Error_Warning::$enabled = TRUE;
$this->assertLastError('Invalid State Error FAIL', 'Fragment.php');
}
这是我刚刚编写的一个新测试,我在其他地方也有相同的断言,它们不再有效
PHPUnit 3.6.7我现在可以解决这个问题了。这与我升级了PHPUnit有关,API略有变化。我再次将
PHPUnit\u Framework\u Constraint
作为我自己约束的模式,阅读其中的注释会有所帮助
evaluate
函数现在不同了,我现在将求值逻辑移到了一个私有函数中,并从evaluate
切换到matches
。它与返回值一起工作<代码>求值在默认情况下不再使用返回值,但期望引发异常。为了从中充分受益,您还可以实例化一些比较器对象,但这超出了我的理解,您可以在asserEquals
约束中找到更多关于该对象的信息
class ConstraintLastError extends \PHPUnit_Framework_Constraint {
...
/**
* Evaluates the constraint for parameter $file. Returns TRUE if the
* constraint is met, FALSE otherwise.
*
* This method can be overridden to implement the evaluation algorithm.
*
* @param mixed $other Value or object to evaluate.
* @return bool
*/
public function matches($file)
{
return $this->compareAgainstLast($file, $this->error);
}
/**
*
* @param string $file
* @param string $error
* @return bool
*/
private function compareAgainstLast($file, $error)
{
if (!$last = error_get_last())
{
$last = array('message' => '(none)', 'file' => '');
}
$this->lastError = $last['message'];
$this->lastFile = $last['file'];
return $error === $this->lastError && basename($file) === basename($this->lastFile);
}
/**
* @param string $file
*/
protected function failureDescription($file)
{
return sprintf('the last error is "%s" in %s, was "%s" in %s'
, $this->error, basename($file)
, $this->lastError, basename($this->lastFile)
);
}
...
现在它就像一个符咒:
1) FragmentTest::testGetType
Failed asserting that the last error is "Suboptimal State Error" in Fragment.php, was "Invalid State Error" in Fragment.php.
其他人也有类似的问题,但另一种解决方案切换到
fail
,您也可以调用它,因为它是在基类中实现的。您是否在代码中设置了自定义错误处理程序(set\u error\u handler)?xdebug工作时是否启用?没有自定义错误处理程序(在我的代码中)。我不记得xdebug工作时是否启用了它。我手动停用了早期PHPUnit版本的xdebug停用,默认情况下,我的dev xdebug处于启用状态。所以,xdebug很可能是在它工作时启用的,但我不清楚。不知怎么的,我觉得我是在为不测试我的约束而付出代价。你确定错误是在第一时间触发的吗?如果不禁用PHPUnit的警告到异常转换,会发生什么?如果启用它,PHPUnit会报告错误。失败!测试:4,断言:5,错误:1。禁用:OK(4个测试,6个断言)-断言被计数,但即使evaluate返回FALSE也会通过。我想知道如何使用远程/单步调试器跟踪PHPUnit会话。看起来不错。->顺便说一句,fail也用于phpunits自身的一些约束条件:-比较器对于直接获取PHPs=
行为非常有用(请参见:),但在您的情况下不需要。谢谢分享:)@edorian:谢谢你的反馈。你认为向PHPUnit提出这样的主张值得吗?(我已经对其进行了一些修改,使其更加有用,例如,文件名可选,更加关注实际的错误消息)。我不认为soa会让PHPUnit\u Framework\u Error\u警告::$enabled on and*@expectedException PHPUnit\u Framework\u Error\u Warnings*@ExpectedExceptionMessage MyExceptedErrorMessage
是这些情况下的建议目的,而给用户另一个选项并不值得额外的复杂性,因为没有多少人真正需要它。我可以肯定地看到您的用例,但我不认为它适用于许多人。但可能是错的。。总是要为每个人做出判断:)也许某个时候应该进行一次民意调查,并提出建议:)