1

下面是我需要进行单元测试的代码。我会为 编写 2 个单元测试用例getFoo,一个为true(x==5),另一个为false(x==10)。我的问题是我是否需要为convertWrapper真假情况编写两个单元测试函数?在我看来,我应该确保将来有人不会导致 convertWrapper 发生变化,从而导致回归。但只是想知道在这种情况下什么被认为是一种广泛采用的做法。

public boolean getFoo(int x) {
    return x == 5;
}

public boolean convertWrapper(char ch) {
    int x = (int)ch;
    return getFoo(x);
}
4

5 回答 5

2

Ask yourself - what is the general contract of convertWrapper. If it's to return true for a particular input, and return false for any other input, then test that it does that. The fact that it is implemented via getFoo is irrelevant to how you'll unit test it.

If somebody in the future changes the implementation so that it still returns true or false for the same inputs as before, but doesn't use getFoo then that should NOT break the test.

Since getFoo is public, it should have its own tests.

于 2013-11-15T02:14:41.327 回答
2

最佳实践通常是编写单元测试。它们应该简单且易于维护。如果使用多个测试方法是最简单和最容易维护的,那就这样做。一般来说,我尽量不要在单元测试中编写太多的样板代码。

于 2013-11-15T02:10:49.580 回答
2

一种选择:确保 convertWrapper 调用并返回 getFoo 的结果,并对 getFoo 进行单元测试。

模拟有助于进行这样的集成测试。

于 2013-11-15T02:10:25.623 回答
1

Yes, you probably do want to write separate cases, because your opinion is generally correct and is precisely the type of situation proper testing is meant to avoid:

In my opinion I should, to ensure that in future someone does not cause a change in convertWrapper, resulting in regression.

Your unit tests should test the high-level functionality of your code. Your unit tests are unaware of implementation details, they only test that the terms of the "contract" are met. Since you have two public methods that, on a high level, do two separate things (we presume - your requirements weren't stated or documented), then you have two separate tests.

Eliminating one of the tests because you, as the developer, implicitly know that the implementations are the same suddenly brings information about implementation details into the testing realm, which is asking for problems and regressions in the future.

One option that Dave Newton pointed out in his answer is to write a unit test that essentially ensures that convertWrapper(ch) == getFoo((int)ch) for all relevant ch. That is a fine suggestion and may very well be appropriate, but only if the high level requirement of convertWrapper is that it "returns the same value as getFoo". Again, your tests should reflect your requirements.

Of course, that doesn't mean it's somehow against the law to eliminate the test. The devil won't necessarily lay claim to your soul if you do it (although sometimes I wish that was the usual consequence). If your application is rather simple, or if you are willing to accept the associated risks, then even a simple "@todo Test me" documentation marker may be enough to get by. It is sometimes OK to take shortcuts now and then but only if you truly understand and accept the implications -- only you can save you from yourself. :)

But, in the general case, yes, two tests. Then you can "fire-and-forget" your tests, and never have to remember that special exception to the rules you made in the future.

于 2013-11-15T02:12:37.233 回答
0

为什么你认为你只需要为 编写两个单元测试getFoo

当然,您知道该方法实际上只能采用两种方式之一,但调用者却不能。使用这种微不足道的方法可能看起来很荒谬,但是您需要根据该方法的合同来考虑。也许你需要用 5 进行测试,然后是 0,然后是一个负数,然后是一个非常高的正数,或者调用者希望你能够处理的任何其他奇怪的情况。

与 类似convertWrapper。您知道它调用getFoo并且getFoo实际上只有两条路径,但是您不能让自己这样想。

底线是您需要为您的方法定义契约并运行足够的测试,以确保您的公共方法满足该契约。

于 2013-11-15T02:24:20.367 回答