简体   繁体   English

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

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

I m reading Art of Unit testing book and I try to understand state based testing logic.In an example of subject there was a calculator class like 我正在阅读《单元测试的艺术》一书,尝试理解基于状态的测试逻辑。在一个示例中,有一个计算器类,例如

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

and book shows how can we test this as: 该书显示了如何测试该值:

[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);
    }

}

So until this, everything is great but, lets say I m writing a calculator class as much as that class, and i made method like 因此,在此之前,一切都很好,但可以说,我正在写一个与该类一样多的计算器类,并且我制作了类似

public int Sum()
{

  return sum;

}

and
Test class like 测试类

 [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);
    }
}

Let say I didnt good realize when i writing code and when i write unit test for that How I catch that following bug? 可以说,当我编写代码以及为此编写单元测试时,我并没有很好地意识到如何捕捉以下错误? Because bug is that sum will not be zero after 2 add method like following processes 因为错误是2加法之后的总和不会为零,如以下过程

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

So how i think to get that logical mistake when i write unit test.(if i write it NUnit will tell me there is a mistake) then i come back and will see the point and I will change calculator class like 因此,当我编写单元测试时,我怎么想得到那个逻辑错误(如果我写它,NUnit会告诉我有一个错误),那么我会回来并指出要点,并且将更改计算器类

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


I hope you understand what i try to say. 我希望你能理解我的意思。
Thanks. 谢谢。

Basically you can't find all the edge cases for sure. 基本上,您不能确定所有边缘情况。 However, you can specify what you intend the code to do and write clean code. 但是,您可以指定要执行的代码并编写干净的代码。 If a calculator is supposed to reset its sum after asking for its sum, then that's part of the 'spec' that there should be a test for, its a 'requirement' invented by someone, so that should be easy to remember to write a test for. 如果一个计算器应该在求和之后重设它的和,那么这就是应该进行测试的“规范”的一部分,它是某人发明的“要求”,因此应该容易记住写下一个测试。

The harder thing is all the edge cases created by the way something is coded. 困难的是通过某种编码方式创建的所有极端情况。 I used to do coding interviews where I would write unit tests for candidates code. 我曾经进行过编程面试,在其中我会为候选代码编写单元测试。 I thought I had a good suite of tests to prove something worked. 我以为我有一套很好的测试来证明某些方法可行。 But I quickly found, that people can code things in ways that introduce hard to test for edge cases ( like something will fail on the 9th time it does something that seems like it should work every single time ). 但是我很快发现,人们可以以难以引入边缘测试的方式编写代码(例如某些事情在第9次失败,并且似乎每次都应该起作用)。 So mainly, if you follow the advice of TDD, write a test, write the code to make it pass, refactor to make the code clean, you won't go too far wrong. 因此,主要来说,如果您遵循TDD的建议,编写测试,编写使代码通过的代码,进行重构以使代码整洁,那么您就不会出错。

and remember, this is not a magic bullet, this isn't some magic formula which allows you to write perfect code. 请记住,这不是魔术子弹,也不是允许您编写完美代码的魔术公式。 You still need to think think think about what you are doing. 您仍然需要考虑考虑自己在做什么。

It sounds like you've basically already got a test case: 听起来您基本上已经有了一个测试用例:

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

The test that it's actually performing addition would be done in other tests - this is just testing that after you call Sum the first time, it resets the internal state. 它实际执行加法的测试将在其他测试中进行-这只是测试,在您首次调用Sum之后,它将重置内部状态。

This test should fail: 该测试应失败:

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

until you changed your code to reset the sum after Sum() is called. 直到在调用Sum()之后更改代码以重置总和。 However, I would prefer to create a separate method Clear() rather than reset the sum in your getter. 但是,我宁愿创建一个单独的方法Clear()而不是重设getter中的和。

TDD steps TDD步骤

  1. Think what you want the Calculator to do. 想想您希望计算器做什么。
  2. Write a test for it. 为此编写一个测试。
  3. Write code to pass test. 编写代码以通过测试。

If I understand you correctly, the sample code below is your implementation, and has a bug; 如果我理解正确,下面的示例代码就是您的实现,并且有一个错误; It does not reset the sum value to zero as the correct implementation does, giving an error. 它不会像正确的实现那样将总和值重置为零,从而产生错误。 Your question is, how to write a unit test for this? 您的问题是,如何为此编写单元测试?

public int Sum()
{

  return sum;

}

Assuming I've interpreted your question correctly, you should simply write a test that detects whether the value is zero when invoked a second time: 假设我已正确解释了您的问题,则只需编写一个测试即可检测第二次调用时该值是否为零:

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