我应该为每个功能/方法编写多少单元测试?

最后发布: 2008-09-21 06:58:48


问题

您是否为每个功能/方法编写一个测试,在测试中进行多次检查,或者对每个检查进行测试?

unit-testing
回答

One test per check and super descriptive names, per instance: 每个检查一次测试和超级描述性名称,每个实例:

@Test
public void userCannotVoteDownWhenScoreIsLessThanOneHundred() {
 ...
}

Both only one assertion and using good names gives me a better report when a test fails. 当测试失败时,只有一个断言和使用好名称会给我一个更好的报告。 They scream to me: "You broke THAT rule!". 他们对我尖叫:“你打破了这条规则!”。


回答

I have a test per capability the function is offering. 我有每能力测试功能是提供。 Each test may have several assertions, however. 但是,每个测试可能有几个断言。 The name of the testcase indicates the capability being tested. 测试用例的名称表示正在测试的功能。

Generally, for one function, I have several "sunny day" tests and one or a few "rainy day" scenario, depending of its complexity. 通常,对于一个功能,我有几个“晴天”测试和一个或几个“下雨天”场景,这取决于其复杂性。


回答

BDD (Behavior Driven Development) BDD(行为驱动开发)

Though I'm still learning, it's basically TDD organized/focused around how your software will actually be used... NOT how it will be developed/built. 虽然我还在学习,但它基本上是TDD组织/关注如何实际使用您的软件...而不是如何开发/构建它。

Wikipedia General Info 维基百科 综合信息

BTW as far as whether to do multiple asserts per test method I would recommend trying it both ways. BTW至于每个测试方法是否要执行多个断言,我建议尝试两种方式。 Sometimes you'll see where one strategy left you in a bind and it'll start making sense why you normally just use one assert per method. 有时你会看到一个策略在绑定中留下你的位置,它会开始有意义,为什么你通常只使用一个断言每个方法。


回答

I think that the rule of single assertion is a little too strict. 我认为单一断言的规则有点过于严格。 In my unit tests, I try to follow the rule of single group of assertions -- you can use more than one assertion in one test method, as long as you do the checks one after another (you don't change the state of tested class between the assertions). 在我的单元测试中,我尝试遵循单组断言的规则 - 你可以在一个测试方法中使用多个断言,只要你一个接一个地进行检查(你不改变测试的状态)断言之间的类)。

So, in Python, I believe a test like this is correct : 所以,在Python中,我相信像这样的测试是正确的

def testGetCountReturnsCountAndEnd(self):
    count, endReached = self.handler.getCount()
    self.assertEqual(count, 0)
    self.assertTrue(endReached)

but this one should be split into two test methods: 但是这一次应分为两种测试方法:

def testGetCountReturnsOneAfterPut(self):
    self.assertEqual(self.handler.getCount(), 0)
    self.handler.put('foo')
    self.assertEqual(self.handler.getCount(), 1)

Of course, in case of long and frequently used groups of assertions, I like to create custom assertion methods -- these are especially useful for comparing complex objects. 当然,在长期和经常使用的断言组的情况下,我喜欢创建自定义断言方法 - 这些方法对于比较复杂对象特别有用。


回答

A test case for each check. 每个检查的测试用例。 It's more granular. 它更精细。 It makes it much easier to see what specific test case failed. 它使得查看特定测试用例失败变得更加容易。


回答

I write at least one test per method, and somtimes more if the method requires some different setUp to test the good cases and the bad cases. 我为每个方法编写至少一个测试,并且如果该方法需要一些不同的setUp来测试好的情况和坏的情况,则会更多。

But you should NEVER test more than one method in one unit test. 但你千万不要测试超过一个单元测试的一种方法。 It reduce the amount of work and error in fixing your test in case your API changes. 如果您的API发生变化,它可以减少修复测试的工作量和错误。


回答

I would suggest a test case for every check. 我建议每个检查都有一个测试用例。 The more you keep atomic, the better your results are! 你保持原子越多,你的结果就越好!

Keeping multiple checks in a single tests will help you generate report for how much functionality needs to be corrected. 在单个测试中保留多个检查将帮助您生成需要纠正多少功能的报告。

Keeping atomic test case will show you the overall quality ! 保持原子测试案例将向您展示整体质量!


回答

In general one testcase per check. 通常每次检查一个测试用例。 When tests are grouped around a particular function it makes refactoring (eg removing or splitting) that function more difficult because the tests also need a lot of changes. 当测试围绕特定函数进行分组时,它会使重构(例如删除或拆分)更加困难,因为测试也需要进行大量更改。 It is much better to write the tests for each type of behaviour that you want from the class. 为类中所需的每种行为编写测试要好得多。 Sometimes when testing a particular behaviour it makes sense to have multiple checks per test case. 有时,在测试特定行为时,每个测试用例进行多次检查是有意义的。 However, as the tests become more complicated it makes them harder to change when something in the class changes. 然而,随着测试变得越来越复杂,当类中的某些东西发生变化时,它们就更难以改变。


回答

In Java/Eclipse/JUnit I use two source directories (src and test) with the same tree. 在Java / Eclipse / JUnit中,我使用两个源目录(src和test)和同一棵树。 If I have a src/com/mycompany/whatever/TestMePlease with methods worth testing (eg deleteAll(List<?> stuff) throws MyException ) I create a test/com/mycompany/whatever/TestMePleaseTest with methods to test differente use case/scenarios: 如果我有一个src / com / mycompany / whatever / TestMePlease与值得测试的方法(例如deleteAll(List <?> stuff)抛出MyException )我创建一个test / com / mycompany / whatever / TestMePleaseTest,用方法来测试不同的用例/场景:

@Test
public void deleteAllWithNullInput() { ... }

@Test(expect="MyException.class") // not sure about actual syntax here :-P
public void deleteAllWithEmptyInput() { ... }

@Test
public void deleteAllWithSingleLineInput() { ... }

@Test
public void deleteAllWithMultipleLinesInput() { ... }

Having different checks is simpler to handle for me. 有不同的检查对我来说更容易处理。

Nonetheless, since every test should be consistent, if I want my initial data set to stay unaltered I sometimes have, for example, to create stuff and delete it in the same check to insure every other test find the data set pristine: 尽管如此,由于每个测试都应该是一致的,如果我希望我的初始数据集保持不变,我有时会在同一个检查中创建并删除它,以确保每个其他测试都能找到原始的数据集:

@Test
public void insertAndDelete() { 
    assertTrue(/*stuff does not exist yet*/);
    createStuff();
    assertTrue(/*stuff does exist now*/);
    deleteStuff();
    assertTrue(/*stuff does not exist anymore*/);
}

Don't know if there are smarter ways to do that, to tell you the truth... 不知道是否有更明智的方法可以做到这一点,说实话......


回答

I like to have a test per check in a method and have a meaningfull name for the test-method. 我喜欢在方法中进行每次检查的测试,并为测试方法提供有意义的名称。 For instance: 例如:

testAddUser_shouldThrowIllegalArgumentExceptionWhenUserIsNull testAddUser_shouldThrowIllegalArgumentExceptionWhenUserIsNull


回答

A testcase per check. 每个检查一个测试用例。 If you name the method appropriately, it can provide valuable hint towards the problem when one of these tests cause a regression failure. 如果您恰当地命名方法,当其中一个测试导致回归失败时,它可以为问题提供有价值的提示。


回答

I try to separate out Database tests and Business Logic Tests (using BDD as others here recommend), running the Database ones first ensures your Database is in a good state before asking your application to play with it. 我尝试将数据库测试和业务逻辑测试分开(使用BDD,就像其他人推荐的那样),首先运行数据库测试确保数据库处于良好状态,然后再请求应用程序使用它。

There's a good podcast show with Andy Leonard on what it involves and how to do it , and if you'd like a bit more information, I've written a blog post on the subject (shameless plug ;o) 有一个很好的播客节目与安迪伦纳德谈及它涉及的内容和如何做 ,如果你想了解更多的信息,我写了一篇关于这个主题博客文章 (无耻的插件; o)