我应该创建额外的函数来使我的代码可测试吗?

Should I create extra functions to make my code testable?

我正在创建一个应用程序,它根据 运行 的日期创建不同的报告。

因此,如果是星期一凌晨 1 点,它将创建一个每周报告,如果是该月的第一天凌晨 1 点 30 分,它将创建一个月度报告。

我最初的方法是使用一个 class。它有一个 属性 数组,将每个报告映射到一个函数。调用脚本调用 class 上的 运行() 方法,后者依次遍历数组并为每个报表调用函数。

我该如何测试?我想要一套像样的单元测试来涵盖计算。

是否为每个报表创建两个函数?一个从数据库中获取数据,另一个进行计算(可以通过参数进行测试)。虽然这似乎很啰嗦!我会有 24 个函数而不是 12 个。

对执行此操作的最佳方法感到困惑。

谢谢!

编辑:澄清一下,脚本是 运行 在上述特定时间由 cron 作业执行的。我已经使用反射测试了时间检查代码(它根据时间设置 运行 模式)。我正在考虑完全从 class 中取出日期,并让调用脚本定义哪些报告正在 运行.

虽然计算当前日期很简单,但我会将其从您的函数中分离出来,这样您就可以在不更改代码的情况下测试不同的日期值。

想到了 2 个选项。

  1. 让它成为函数的参数。因此,您可以通过使用不同的值调用您的函数来测试它。这样,就不必等到特定时间来测试您的代码。然后,通过使用不同的日期参数调用主代码来进行单元测试。

  1. 将日期逻辑作为一个单独的函数,这样您就可以单独测试该日期逻辑。然后,让您的函数调用日期逻辑代码。

在尝试测试您的代码时,您总是会发现自己处于这些类型的情况中: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 来完成,您也可以模拟它,或者使用其他一些技巧,例如命名空间覆盖。