繁体   English   中英

单元测试我如何指出被测类的逻辑错误

[英]Unit Testing how I think to point logical mistake on class which is under test

我正在阅读《单元测试的艺术》一书,尝试理解基于状态的测试逻辑。在一个示例中,有一个计算器类,例如

public class Calculator
{
    private int sum=0;
    public void Add(int number)
    {
      sum+=number;
    }
    public int Sum()
    {
      int temp = sum;
      sum = 0;
      return temp;
    }
 }

该书显示了如何测试该值:

[TestFixture]
public class CalculatorTests
{
    private Calculator calc;

    [SetUp]
    public void Setup()
    {
        calc = new Calculator();
    }

    [Test]
    public void Sum_NoAddCalls_DefaultsToZero()
    {
        int lastSum = calc.Sum();
        Assert.AreEqual(0,lastSum);
    }

    [Test]
    public void Add_CalledOnce_SavesNumberForSum()
    {
        calc.Add(1);
        int lastSum = calc.Sum();
        Assert.AreEqual(1,lastSum);
    }

    [Test]
    public void Sum_AfterCall_ResetsToZero()
    {
        calc.Add(1);
        calc.Sum();
        int lastSum = calc.Sum();
        Assert.AreEqual(0, lastSum);
    }

}

因此,在此之前,一切都很好,但可以说,我正在写一个与该类一样多的计算器类,并且我制作了类似

public int Sum()
{

  return sum;

}


测试类

 [TestFixture]
public class CalculatorTests
{
    private Calculator calc;

    [SetUp]
    public void Setup()
    {
        calc = new Calculator();
    }

    [Test]
    public void Sum_NoAddCalls_DefaultsToZero()
    {
        int lastSum = calc.Sum();
        Assert.AreEqual(0,lastSum);
    }

    [Test]
    public void Add_CalledOnce_SavesNumberForSum()
    {
        calc.Add(1);
        int lastSum = calc.Sum();
        Assert.AreEqual(1,lastSum);
    }
}

可以说,当我编写代码以及为此编写单元测试时,我并没有很好地意识到如何捕捉以下错误? 因为错误是2加法之后的总和不会为零,如以下过程

add(1)
add(23)
sum()  is 24 now
add(11)
add(12)
sum()  => will be 47 but it has to be 23.

因此,当我编写单元测试时,我怎么想得到那个逻辑错误(如果我写它,NUnit会告诉我有一个错误),那么我会回来并指出要点,并且将更改计算器类

public int Sum() 
{ 
  int temp = sum; 
  sum = 0; 
  return temp; 
}


我希望你能理解我的意思。
谢谢。

基本上,您不能确定所有边缘情况。 但是,您可以指定要执行的代码并编写干净的代码。 如果一个计算器应该在求和之后重设它的和,那么这就是应该进行测试的“规范”的一部分,它是某人发明的“要求”,因此应该容易记住写下一个测试。

困难的是通过某种编码方式创建的所有极端情况。 我曾经进行过编程面试,在其中我会为候选代码编写单元测试。 我以为我有一套很好的测试来证明某些方法可行。 但是我很快发现,人们可以以难以引入边缘测试的方式编写代码(例如某些事情在第9次失败,并且似乎每次都应该起作用)。 因此,主要来说,如果您遵循TDD的建议,编写测试,编写使代码通过的代码,进行重构以使代码整洁,那么您就不会出错。

请记住,这不是魔术子弹,也不是允许您编写完美代码的魔术公式。 您仍然需要考虑考虑自己在做什么。

听起来您基本上已经有了一个测试用例:

[Test]
public void CallingSumResets()
{
    var calc = new Calculator();
    calc.Add(10);
    Assert.AreEqual(10, calc.Sum());
    Assert.AreEqual(0, calc.Sum());
}

它实际执行加法的测试将在其他测试中进行-这只是测试,在您首次调用Sum之后,它将重置内部状态。

该测试应失败:

   [Test]
    public void Sum_AfterCall_ResetsToZero()
    {
        calc.Add(1);
        calc.Sum();
        int lastSum = calc.Sum();
        Assert.AreEqual(0, lastSum);
    }

直到在调用Sum()之后更改代码以重置总和。 但是,我宁愿创建一个单独的方法Clear()而不是重设getter中的和。

TDD步骤

  1. 想想您希望计算器做什么。
  2. 为此编写一个测试。
  3. 编写代码以通过测试。

如果我理解正确,下面的示例代码就是您的实现,并且有一个错误; 它不会像正确的实现那样将总和值重置为零,从而产生错误。 您的问题是,如何为此编写单元测试?

public int Sum()
{

  return sum;

}

假设我已正确解释了您的问题,则只需编写一个测试即可检测第二次调用时该值是否为零:

add(11)
add(12)
sum() => ignore result
sum() => Should be zero

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM