PHPunit - 测试用户错误状态(不是异常)的最佳实践
PHPunit - best practices for testing user error states (not exceptions)
我有一个相当粗糙的 PHP 应用程序,我正在重构并添加 phpunit 测试。应用程序中的一种常见情况是用户针对错误配置发出警告消息(应用程序接收配置文件并生成图像和 HTML 作为输出)。
所以我在应用程序中散布了一堆代码,例如:
wm_warn("You can't make a contrast with 'none' - guessing black. [WMWARN43]\n");
其中 wm_warn 根据上下文写入 stderr 或日志文件。
如何使用 phpunit 测试这些警告?
重要的是 - 这不是致命错误,因此不可能 (AFAIK) 将其替换为异常并使用 phpunit 的 "expected exception" 功能。
这是 wm_warn 模拟的用例吗?还是捕获标准错误?或者使用不同的日志记录方法使测试更容易(例如 log4php)?
模拟可能是正确的解决方案,PHPUnit 手册这样描述模拟:
The practice of replacing an object with a test double that verifies
expectations, for instance asserting that a method has been called, is
referred to as mocking.
因此您可以观察到 wm_warn
已被调用,但未执行(没有任何内容进入日志)。
您可以在 PHPUnit Test Doubles 主题下阅读更多关于 Simple Mocking 的信息,该主题显示了一个示例(上面的引用也被讨论)。您可能面临的一个问题是您可以模拟对象但不能直接模拟函数 - 这取决于您的应用程序的硬性 :)
模拟(或者更确切地说是间谍)将是前进的方向。它可能难以实施,具体取决于应用程序(你说它相当粗糙)
函数是如何加载的?如果可以拦截包含包含 wp_warn 函数的相关文件的调用,则可以将其更改为使用您自己的模拟版本,然后可以将调用它的参数(即错误)记录到(呃,不寒而栗)测试用例可以访问的全局变量:
//...
if (defined('TEST_ENVIRONMENT')) {
require_once 'wp_warn-test.php';
} else {
require_once 'wp_warn.php';
}
//...
在wp_warn-test.php:
function wp_warn($error)
{
$_GLOBALS['SPY_WP_WARN_ERRORS'][] = $error;
}
并在测试中:
$this->assertContains("You can't make a contrast with 'none' - guessing black. [WMWARN43]\n", $_GLOBALS['SPY_WP_WARN_ERRORS']);
它非常丑陋,尤其是在使用全局变量时,但是如果这意味着你成功地进行了测试,那么它会给你未来更多的机会来重构它并找到更优雅的解决方案。
我有一个相当粗糙的 PHP 应用程序,我正在重构并添加 phpunit 测试。应用程序中的一种常见情况是用户针对错误配置发出警告消息(应用程序接收配置文件并生成图像和 HTML 作为输出)。
所以我在应用程序中散布了一堆代码,例如:
wm_warn("You can't make a contrast with 'none' - guessing black. [WMWARN43]\n");
其中 wm_warn 根据上下文写入 stderr 或日志文件。
如何使用 phpunit 测试这些警告?
重要的是 - 这不是致命错误,因此不可能 (AFAIK) 将其替换为异常并使用 phpunit 的 "expected exception" 功能。
这是 wm_warn 模拟的用例吗?还是捕获标准错误?或者使用不同的日志记录方法使测试更容易(例如 log4php)?
模拟可能是正确的解决方案,PHPUnit 手册这样描述模拟:
The practice of replacing an object with a test double that verifies expectations, for instance asserting that a method has been called, is referred to as mocking.
因此您可以观察到 wm_warn
已被调用,但未执行(没有任何内容进入日志)。
您可以在 PHPUnit Test Doubles 主题下阅读更多关于 Simple Mocking 的信息,该主题显示了一个示例(上面的引用也被讨论)。您可能面临的一个问题是您可以模拟对象但不能直接模拟函数 - 这取决于您的应用程序的硬性 :)
模拟(或者更确切地说是间谍)将是前进的方向。它可能难以实施,具体取决于应用程序(你说它相当粗糙)
函数是如何加载的?如果可以拦截包含包含 wp_warn 函数的相关文件的调用,则可以将其更改为使用您自己的模拟版本,然后可以将调用它的参数(即错误)记录到(呃,不寒而栗)测试用例可以访问的全局变量:
//...
if (defined('TEST_ENVIRONMENT')) {
require_once 'wp_warn-test.php';
} else {
require_once 'wp_warn.php';
}
//...
在wp_warn-test.php:
function wp_warn($error)
{
$_GLOBALS['SPY_WP_WARN_ERRORS'][] = $error;
}
并在测试中:
$this->assertContains("You can't make a contrast with 'none' - guessing black. [WMWARN43]\n", $_GLOBALS['SPY_WP_WARN_ERRORS']);
它非常丑陋,尤其是在使用全局变量时,但是如果这意味着你成功地进行了测试,那么它会给你未来更多的机会来重构它并找到更优雅的解决方案。