简体   繁体   English

我应该测试那些方法不会抛出异常吗?

[英]Should I test that methods don't throw exceptions?

I'm making my first baby steps with unit testing and have written (among others) these two methods: 我正在进行单元测试的第一步,并编写了(以及其他)这两种方法:

    [TestCase]
    public void InsertionSortedSet_AddValues_NoException()
    {
        var test = new InsertionSortedSet<int>();

        test.Add(5);
        test.Add(2);
        test.Add(7);
        test.Add(4);
        test.Add(9);
    }

    [TestCase]
    public void InsertionSortedSet_AddValues_CorrectCount()
    {
        var test = new InsertionSortedSet<int>();

        test.Add(5);
        test.Add(2);
        test.Add(7);
        test.Add(4);
        test.Add(9);

        Assert.IsTrue(test.Count == 5);
    }

Is the NoException method really needed? 真的需要NoException方法吗? If an exception is going to be thrown it'll be thrown in the CorrectCount method too. 如果要抛出异常,它也将被抛出CorrectCount方法。

I'm leaning towards keep it as 2 test cases (maybe refactor the repeated code as another method) because a test should only test for a single thing, but maybe my interpretation is wrong. 我倾向于将它保留为2个测试用例(可能将重复的代码重构为另一种方法)因为测试应该仅测试单个事物,但也许我的解释是错误的。

To put it in the most simple words, IMO testing what method does not do might be very slippery, as you can come up with more and more scenarios when you think about it. 用最简单的话来说,IMO测试哪种方法不会做得很滑,因为你可以在想到它时提出越来越多的场景。 Going other way around tho, asserting that your code does stuff you intended it to do is pretty much purpose of unit testing. 反过来说,断言你的代码完成你打算做的事情就是单元测试的目的。


There are two simple questions which usually help me spotting suspicious test and dealing with figuring out whether test makes any sense: 有两个简单的问题,通常可以帮助我发现可疑的测试并解决测试是否有任何意义:

  • what part of desired functionality is test exercising? 所需功能的哪一部分是测试锻炼?
  • what simple change can I make in tested class to break test? 我可以在测试类中进行哪些简单的更改来打破测试?

Note that it's extremely easy to deal with those questions having second test ( _CorrectCount ) in mind. 请注意,处理那些考虑了第二次测试( _CorrectCount )的问题非常容易 We haven't really seen Add method code, but we can most likely produce decent guess what could be changed to break that test. 我们还没有真正看到Add方法代码,但我们很可能会产生不错的猜测,可以改变什么来打破这个测试。 Tested functionality is even more obvious. 经过测试的功能更加明显。 Answers are intuitive and appear fast (which is good!). 答案很直观,看起来很快(这很好!)。

Now let's try to answer those questions for the first test ( _NoException ). 现在让我们尝试回答第一个测试的问题( _NoException )。 It immediately raises new questions ( Is working code an actual functionality? Isn't it obvious? Isn't that implied? Isn't that what we always strive for? Why there is no assertion at the end? How can I make it fail? ). 它立即提出了新的问题( 工作代码是否是一个实际的功能?是不是很明显?这不是暗示吗?这不是我们一直在努力的吗?为什么最后没有断言?我怎么能让它失败? ? )。 For the second question it's even worse - breaking that test would probably require explicitly throwing exception... which we all agree is not the way to go. 对于第二个问题,情况更糟 - 打破那个测试可能需要明确地抛出异常......我们都同意这不是要走的路。

Conclusion 结论

Is simple. 很简单。 Second test is perfect example of well-written unit test . 第二次测试是精心编写的单元测试的完美示例。 It's short, it tests single thing, it can be easily figured out. 它很简单,它测试单一的东西,它可以很容易想出来。 First test is not . 第一次测试不是 Even tho it is just as short and (what seems to be) simple, it introduces new questions (while it really should answer already stated ones - Does Add actually add? Yes. ) - and as a result brings unnecessary complexity. 即使它只是简短而且(似乎是)简单,它引入了新的问题(虽然它确实应该回答已经说明的问题 - Add实际上是否Add ?是的。 ) - 结果带来了不必要的复杂性。

It makes much more sense to make a method that tests that the method under test throws exceptions when you expect it to. 更有意义的是,制作一个方法来测试被测方法在您期望它时会抛出异常。 The first test you have asserts no behavior that the second test doesn't already cover. 您所做的第一个测试没有断言第二个测试没有涵盖的行为。

I always test for both working and non-working cases. 我总是测试工作和非工作案例。 This way, you validate that the code works, returning the correct results, as well as handles errors in an expected manner. 这样,您可以验证代码是否有效,返回正确的结果,以及以预期的方式处理错误。

Imo, if you're sure on InsertionSortedSet list working (I'm not sure where it comes from), I would skip testing InsertionSortedSet_AddValues_NoException as you intend to do, if it so necessary. Imo,如果你确定在InsertionSortedSet列表工作(我不知道它来自哪里),我会跳过测试InsertionSortedSet_AddValues_NoException ,如果有必要的话。

For sure it's better to test as much as possible. 当然,最好尽可能多地进行测试。

There is no 100% correct answer here. 这里没有100%正确答案。

On the one hand you are right, a single test should test for a single thing. 一方面你是对的,一个测试应该测试一件事。
This is specially true in cases where one of the tests might change in the future, and then you will not be able know for sure if you are checking for the other test to pass. 在其中一个测试将来可能会发生变化的情况下尤其如此,然后您将无法确定是否要检查其他测试是否通过。

On the other hand, you are creating redundancy, as both test actually check for the same thing. 另一方面,您正在创建冗余,因为两个测试实际上都检查了相同的事情。
This redundancy is bad only in cases where your tests take too much time to run, but since (as it seems) you have only a few tests, this should not be a problem. 这种冗余只有在您的测试需要花费太多时间才能运行的情况下才会出现问题,但由于(看起来像)您只进行了一些测试,因此这不应该是一个问题。

There is no assertion nor expected exception in the first test, I think it should be refactored. 在第一次测试中没有断言或预期的异常,我认为它应该被重构。

IMO, one test should check for the incorrect behavior (expecting an error to be thrown) and the other for the correct behavior (no exception, good value returned). IMO,一个测试应该检查不正确的行为(期望抛出错误),另一个测试应该检查正确的行为(没有异常,返回好的值)。

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

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