我应该创建额外的函数来使我的代码可测试吗?
Should I create extra functions to make my code testable?
我正在创建一个应用程序,它根据 运行 的日期创建不同的报告。
因此,如果是星期一凌晨 1 点,它将创建一个每周报告,如果是该月的第一天凌晨 1 点 30 分,它将创建一个月度报告。
我最初的方法是使用一个 class。它有一个 属性 数组,将每个报告映射到一个函数。调用脚本调用 class 上的 运行() 方法,后者依次遍历数组并为每个报表调用函数。
我该如何测试?我想要一套像样的单元测试来涵盖计算。
是否为每个报表创建两个函数?一个从数据库中获取数据,另一个进行计算(可以通过参数进行测试)。虽然这似乎很啰嗦!我会有 24 个函数而不是 12 个。
对执行此操作的最佳方法感到困惑。
谢谢!
编辑:澄清一下,脚本是 运行 在上述特定时间由 cron 作业执行的。我已经使用反射测试了时间检查代码(它根据时间设置 运行 模式)。我正在考虑完全从 class 中取出日期,并让调用脚本定义哪些报告正在 运行.
虽然计算当前日期很简单,但我会将其从您的函数中分离出来,这样您就可以在不更改代码的情况下测试不同的日期值。
想到了 2 个选项。
- 让它成为函数的参数。因此,您可以通过使用不同的值调用您的函数来测试它。这样,就不必等到特定时间来测试您的代码。然后,通过使用不同的日期参数调用主代码来进行单元测试。
或
- 将日期逻辑作为一个单独的函数,这样您就可以单独测试该日期逻辑。然后,让您的函数调用日期逻辑代码。
在尝试测试您的代码时,您总是会发现自己处于这些类型的情况中:class 有很多我想测试的私有函数。
你所说的 "extra" 功能,它们不是。只是如果你想能够测试一些代码,它通常必须可以从测试中访问,并且可能以单独的形式 class.
这是我要遵循的结构:
class ReportGenerator
{
private $calculator;
public function __construct(ReportCalculator $calculator)
{
$this->calculator = $calculator;
}
public function generate()
{
$calculation_method = $this->computeCalculationMethod();
return $this->calculator->$calculation_method();
}
private function computeCalculationMethod()
{
switch ($week_day) {
...
}
return $method;
}
}
class ReportCalculator
{
public function calculation1()
{
}
public function calculationN()
{
}
}
所以计算是使用可以轻松测试的 class 完成的。
为了测试每个工作日是否调用了正确的方法,您在测试中创建 ReportGenerator 时注入了一个 ReportCalculator 的模拟 class 并检查是否对每个案例进行了正确的调用.
您还必须控制测试中的当前工作日。这可以通过使用 DateProvider class 来完成,您也可以模拟它,或者使用其他一些技巧,例如命名空间覆盖。
我正在创建一个应用程序,它根据 运行 的日期创建不同的报告。
因此,如果是星期一凌晨 1 点,它将创建一个每周报告,如果是该月的第一天凌晨 1 点 30 分,它将创建一个月度报告。
我最初的方法是使用一个 class。它有一个 属性 数组,将每个报告映射到一个函数。调用脚本调用 class 上的 运行() 方法,后者依次遍历数组并为每个报表调用函数。
我该如何测试?我想要一套像样的单元测试来涵盖计算。
是否为每个报表创建两个函数?一个从数据库中获取数据,另一个进行计算(可以通过参数进行测试)。虽然这似乎很啰嗦!我会有 24 个函数而不是 12 个。
对执行此操作的最佳方法感到困惑。
谢谢!
编辑:澄清一下,脚本是 运行 在上述特定时间由 cron 作业执行的。我已经使用反射测试了时间检查代码(它根据时间设置 运行 模式)。我正在考虑完全从 class 中取出日期,并让调用脚本定义哪些报告正在 运行.
虽然计算当前日期很简单,但我会将其从您的函数中分离出来,这样您就可以在不更改代码的情况下测试不同的日期值。
想到了 2 个选项。
- 让它成为函数的参数。因此,您可以通过使用不同的值调用您的函数来测试它。这样,就不必等到特定时间来测试您的代码。然后,通过使用不同的日期参数调用主代码来进行单元测试。
或
- 将日期逻辑作为一个单独的函数,这样您就可以单独测试该日期逻辑。然后,让您的函数调用日期逻辑代码。
在尝试测试您的代码时,您总是会发现自己处于这些类型的情况中:class 有很多我想测试的私有函数。
你所说的 "extra" 功能,它们不是。只是如果你想能够测试一些代码,它通常必须可以从测试中访问,并且可能以单独的形式 class.
这是我要遵循的结构:
class ReportGenerator
{
private $calculator;
public function __construct(ReportCalculator $calculator)
{
$this->calculator = $calculator;
}
public function generate()
{
$calculation_method = $this->computeCalculationMethod();
return $this->calculator->$calculation_method();
}
private function computeCalculationMethod()
{
switch ($week_day) {
...
}
return $method;
}
}
class ReportCalculator
{
public function calculation1()
{
}
public function calculationN()
{
}
}
所以计算是使用可以轻松测试的 class 完成的。
为了测试每个工作日是否调用了正确的方法,您在测试中创建 ReportGenerator 时注入了一个 ReportCalculator 的模拟 class 并检查是否对每个案例进行了正确的调用.
您还必须控制测试中的当前工作日。这可以通过使用 DateProvider class 来完成,您也可以模拟它,或者使用其他一些技巧,例如命名空间覆盖。