【问题标题】:Which tests to make for this little method?为这个小方法做哪些测试?
【发布时间】:2010-12-03 20:01:12
【问题描述】:

我目前有以下方法:

public void SetNewRandomValue() {
   double newValue = numberGenerator.GenerateDouble(
                             genesValuesInterval.MinimumValue,
                             genesValuesInterval.MaximumValue
                             );

   this.value = newValue;
}

决定对该方法进行多少次测试(以及哪些测试)的指导方针应该是什么?我目前已经完成了以下一个(仅在实现该方法之后——即不是先测试):

var interval = new Interval(-10, 10);
var numberGeneratorMock = new Mock<INumberGenerator>(MockBehavior.Strict);
var numberGenerator = numberGeneratorMock.Object;

double expectedValue = 5.0;

numberGeneratorMock.Setup(ng => 
        ng.GenerateDouble(interval.MinimumValue, interval.MaximumValue))
        .Returns(expectedValue);

var gene = new Gene(numberGenerator, 0, new Interval(-10, 10));
gene.SetNewRandomValue();

Assert.AreEqual<double>(expectedValue, gene.Value);

这基本上只是测试一种情况。 Regression-testingwise 我会说我想不出一种方法来弄乱代码,将其变成故障代码并且仍然通过测试,也就是说,我认为该方法看起来不错。

您对此有何看法?你会如何处理这个小方法?

谢谢

【问题讨论】:

  • 我很担心将此作为解决方案发布,因为我绝不是单元测试之神。但是,如果您已经充分测试了您的数字生成器,以及您从genesValues 中检索的最小/最大值,那么我将就此停止。如果您知道这些工作,那么您要测试的只是 this.value 被设置。
  • Gene 构造函数中的第二个参数是什么?

标签: c# unit-testing testing


【解决方案1】:

如果代码覆盖率可用于您的测试框架,我会使用您使用的任何测试工具检查代码覆盖率。

我个人喜欢与Microsoft Testing ToolNUnit Testing Framework 一起工作。然后我可以右键单击我的测试项目和Test with NCover(在使用 NUnit 时),它将运行测试并告诉我每个对象和测试覆盖的代码百分比。

我是说,当您完成对代码覆盖率的检查(至少 98% 的代码覆盖率)时,您的代码很可能经过了良好的测试。

【讨论】:

  • 我不同意这一点。代码覆盖率非常非常具有误导性。您可以模拟所有调用,然后模拟 Assert.IsTrue(1 == 1),您将获得 100% 的代码覆盖率,无需实际测试。我同意你的观点,这是一个很好的理智检查,可以确保你击中了所有的垒,但它并不能保证你击中了它们:)
  • 就我个人而言,在我看来,我不会尝试敲击每一段代码并做出诸如Assert.IsTrue(1 == 1) 之类的虚假断言,这与Assert.Pass() 相同。这真的没有意义。当我使用代码覆盖率时,我会查看测试尚未命中的内容,并详细说明我能做的最好的测试,以确保我已经对其进行了良好的测试。无论如何,以你的论点,我不能比同意你更好。我没有这样看。 =)
【解决方案2】:

我建议您查看Pex - 它确实可以帮助生成您正在寻找的单元测试类型(即找出给定方法和返回值的不同潜在路径和结果)。

【讨论】:

    【解决方案3】:

    那个测试看起来不错。关于SetNewRandomValue,您唯一可以真正断言的是Value 成员是在之后分配的。您已经模拟了对 GenerateDouble 的调用,并验证了 Value 包含预期的数字,所以您应该没问题。

    【讨论】:

      【解决方案4】:

      NumberGenerator.GenerateDouble 返回指定间隔之外的值时,您还可以编写测试来记录(并验证)Gene.SetNewRandomValue 的预期行为。

      【讨论】:

        【解决方案5】:

        您绝对可以提出不进行单元测试的理由。恕我直言,代码检查是一种完全有效的测试方法。您通常不会测试属性 setter/getter 之类的东西,我认为这种方法很简单,可以避免出于同样的原因进行单元测试。

        也就是说,如果你真的想测试它,我会这样做:我会用几个值来测试它,而不仅仅是用 5 一次。(SetNewRandomValue 可以实现为this.value = 5;,它应该不通过。)我会用一个非整数测试它,以确认那里没有一个奇怪的整数转换。

        您可以测试它是否使用正确的参数调用 GenerateDouble,尽管这实际上是在测试实现细节。 (SetNewRandomValue 可以实现为numberGenerator.GenerateDouble(0, interval.max - interval.min) + interval.min;,这不会导致测试失败。)您可以使用真正的随机数生成器,并执行数千次 SetNewRandomValue,并测试这些值是否均匀分布在您的预期范围内。

        【讨论】:

          【解决方案6】:

          该方法做了三件事:
          genesValuesInterval.MinimumValue为第一个参数调用numberGenerator.GenerateDouble
          并以genesValuesInterval.MaximumValue 作为第二个参数,
          并将this.value 设置为该调用的结果。

          您的测试测试了其中的第三个,而不是前两个。您可以再编写两个测试来检查使用正确的第一个和第二个参数调用模拟。

          编辑(响应下面的 cmets): 如果此方法的预期行为是将 this.value 设置为先前指定范围内的随机双精度数,则上述三个测试很有用(假设 genesValuesInterval min 和 max 是先前指定的范围,并且您已经进行了测试断言 numberGenerator.GenerateDouble(min, max) 返回指定范围内的双精度。

          如果此方法的预期行为只是将this.value 设置为 (Double.MinValue, Double.MaxValue) 内的随机双精度,则前两个测试是不必要的,因为这只是一个实现细节。

          如果是整数

          【讨论】:

          • 前两个是实现细节。
          • @Jason:单元测试应该测试方法的实现细节。
          • 您不能假设 -10 和 10 是正确的参数。他们可以传递 0 和 20,然后从得到的双精度数中减去 10。
          • @Jackson Pope:不,他们不是,不是!他们假设测试方法的行为。重点是我可以更改实现细节,但只要我不更改行为,那么我仍然会有一个通过的单元测试。如果我的单元测试严重依赖于实现细节,那么即使我没有更改语义,每次重构时我都会有非常脆弱的测试失败。换句话说,单元测试是代码的客户,就像其他人是代码的客户一样。实施细节将对客户隐藏。客户只关心行为。
          • @Jackson Pope:单元测试不应该关心int Add(int m, int n) 是实现为Adder adder = new Adder(); int result = adder.Add(m, n); return result; 还是实现为return m + n;。这些是代码客户不应该关心的实现细节。他们只关心方法返回等于m + n 的数字的行为。
          【解决方案7】:

          要回答如何测试它,您应该能够描述所需的行为。

          查看您的代码,我假设“Gene.SetNewRandomValue”应该将self.Value 设置为属于传递给构造函数的间隔内的数字。

          我对@9​​87654322@ 类不是很熟悉,所以我可能不太了解,但您似乎没有对此进行测试。如果你的实现有这个错字怎么办?

          double newValue = numberGenerator.GenerateDouble( 
                                   genesValuesInterval.MinimumValue, 
                                   genesValuesInterval.MinimumValue 
                                   ); 
          

          你的测试还是不能通过吗?

          【讨论】:

            猜你喜欢
            • 2010-09-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多