java 如果测试中的语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15154125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:39:44  来源:igfitidea点击:

If statements in tests

javaunit-testing

提问by Raidmaster

I have a Parametrized test class with bunch of unit tests that generally control the creation of custom email messages. Right now class has a lot of test which depend on factor(s) used in parametrized class, the flow of the tests is the same for every test. The example of a test:

我有一个参数化测试类,其中包含一堆通常控制自定义电子邮件创建的单元测试。现在类有很多测试取决于参数化类中使用的因素,每个测试的测试流程都是相同的。一个测试的例子:

@Test
public void testRecipientsCount() {
    assertEquals(3, recipientsCount);
}

I had to add extra funcionality to my email class that adds some extra internal emails to the list of recipients, and that only happens for some of the cases and that leads to my problem.

我不得不为我的电子邮件类添加额外的功能,将一些额外的内部电子邮件添加到收件人列表中,而这只发生在某些情况下,这会导致我的问题。

Lets say I want to assert the amount of messages created. For the old test it was the same for each case, but now its different depending on cases. The most intuitive way for me was to add if statements:

假设我想断言创建的消息数量。对于旧测试,每个案例都是相同的,但现在根据案例不同。对我来说最直观的方法是添加 if 语句:

@Test
public void testRecipientsCount(){
    if(something) {
        assertEquals(3, recipientsCount);
    }
    else {
        assertEquals(4, recipientsCount);
    }
}
...

but my more experienced co-worker says we should avoid ifs in test classes (and I kinda agree on that).

但我更有经验的同事说我们应该避免在测试课程中出现 ifs(我有点同意这一点)。

I thought that splitting test on two test classess may work, but that would lead to redundant code in both classes (I still have to check if non-iternal messages were created, their size, content etc.), and a few lines added for one of them.

我认为对两个测试类进行拆分测试可能可行,但这会导致两个类中的代码冗余(我仍然必须检查是否创建了非内部消息、它们的大小、内容等),并为其中之一。

My question is: how do I do this so I don't use if's or loads of redundant code (not using parametrized class would produce even more redundant code)?

我的问题是:我该怎么做才能不使用 if 或大量冗余代码(不使用参数化类会产生更多冗余代码)?

采纳答案by Stefan Beike

In my opinion a Junit should be read like a protocol. That means you can write redundant code to make the test case better readable. Write a testcase for each possible if-statement in your business logic as well as the negative cases. Thats the only way to get a 100% test coverage. I use the structure:

在我看来,Junit 应该像协议一样被阅读。这意味着您可以编写冗余代码以提高测试用例的可读性。为业务逻辑中每个可能的 if 语句以及否定案例编写一个测试用例。那是获得 100% 测试覆盖率的唯一方法。我使用的结构:

- testdata preparation
- executing logic
- check results
- clear data

Furthermore you should write complex asserts of big objects in own abstract classes:

此外,您应该在自己的抽象类中编写大对象的复杂断言:

abstract class YourBusinessObjectAssert{
  public static void assertYourBussinessObjectIsValid(YourBusinessObject pYourBusinessObject,       Collection<YourBusinessObject> pAllYourBusinessObject) {
for (YourBusinessObject lYourBusinessObject : pAllYourBusinessObject) {
  if (lYourBusinessObject.isTechnicalEqual(pYourBusinessObject)) {
    return;
  }
}
assertFalse("Could not find requested YourBusinessObject in List<YourBusinessObject>!", true);
}
}

it will reduce the complexity of your code and you're making it available to other developers.

它将降低您的代码的复杂性,并且您可以将其提供给其他开发人员。

回答by Don Roby

I'm not sure if it's possible to cleanly do what you're after in a parametrized test. If you need different test case behavior based on which parameter for some features, you might just be better off testing those features separately - in different test classes that are not parametrized.

我不确定在参数化测试中是否可以干净利落地做你想要的。如果您需要基于某些功能的参数的不同测试用例行为,您可能最好单独测试这些功能 - 在未参数化的不同测试类中。

If you really do want to keep everything in the parametrized test classes, I would be inclined to make a helper function so that your example test at least reads as a simple assertion:

如果您真的想将所有内容保留在参数化测试类中,我会倾向于创建一个辅助函数,以便您的示例测试至少读取为一个简单的断言:

@Test
public void testRecipientsCount(){
    assertEquals(expectedCount(something), recipientsCount)
}

private int expectedCount(boolean which) {
    if (something){
       return 3;
    }
    else {
       return 4;
    }
}

回答by Sean Landsman

A unit test should, in my opinion, test only one thing if possible. As such I'd say that if you need an if statement then you probably need more than one unit test - one for each block in the if/else code.

在我看来,单元测试应该尽可能只测试一件事。因此,我会说,如果您需要一个 if 语句,那么您可能需要多个单元测试——一个用于 if/else 代码中的每个块。

If possible I'd say a test should read like a story - my preferred layout (and its not my idea :-) - its fairly widely used) is:

如果可能的话,我想说一个测试应该读起来像一个故事——我喜欢的布局(而不是我的想法:-)——它的使用相当广泛)是:

- given:  do setup etc
- when:  the place you actually execute/call the thing under test
- expect: verify the result

Another advantage of a unit test testing only one thing is that when a failure occurs its unambiguous what the cause was - if you have a long test with many possible outcomes it becomes much harder to reason why a test has failed.

单元测试只测试一件事的另一个优点是,当失败发生时,它的原因是明确的——如果你有一个有很多可能结果的长时间测试,那么解释测试失败的原因变得更加困难。

回答by Magnilex

Why not have a private method that tests the things that are common for each method? Something like (but probably with some input parameter for the testCommonStuff()method):

为什么没有一个私有方法来测试每个方法的共同点呢?类似于(但可能带有该testCommonStuff()方法的一些输入参数):

@Test
public void testRecipientsCountA(){
   testCommonStuff();
   // Assert stuff for test A
}

@Test
public void testRecipientsCountB(){
   testCommonStuff();
   // Assert stuff for test B
}

private void testCommonStuff() {
   // Assert common stuff
}

This way you don't get redundant code and you can split your test into smaller tests. Also you make your tests less error prone IF they should actually test the same things. You will still know which test that failed, so traceability should be no problem.

这样你就不会得到多余的代码,你可以把你的测试分成更小的测试。此外,如果您的测试实际上应该测试相同的内容,那么您可以使测试更不容易出错。您仍然会知道哪个测试失败了,因此可追溯性应该没有问题。