优秀的Java程序测试是什么样的?

  作为测试驱动设计和开发的忠实粉丝,我相信创造良好的测试是我们作为 Java 开发人员可以做的最重要的事情之一。我们写测试出于许多原因:

塑造系统的设计。我们知道输入和输出应该是什么样的,但是我们需要创建什么对象来做到这一点呢?代码应该塑造成什么样的“形状”?编写测试可以让我们知道应该创建什么样的代码。

为了确保初始和持续的正确性。让我们的应用程序如期望地那样运作并且始终如一地精确很重要。测试应该竭力确保做到这一点。

文档。测试是系统的文档,因为它会说明它应该做什么以及应该怎么做。

  那么“好的测试”到底是什么样子的呢?

优秀的Java程序测试是什么样的?

  给测试命名

  测试的名字至关重要,特别是从文档角度来看的话。我们应该能够大声读出测试的名字就像一组需求一样。事实上,有一个伟大的 IntelliJ 插件,叫 Enso,它会将你的测试名转变为恰好位于每个类旁边的语句,这样你就可以明明白白地看到你在做什么。

  不要以“test”开始命名测试的名称。这是来自于 JUnit 初期的后遗症,当需要它执行的时候。你的 Test 类将在 Test 文件夹中,在一个最后有 Test 这个单词的类中。会有一个@Test 的注解。我们知道这是一个测试。

  你也应该避免以“should”或“will”开头。这些都是干扰词。既然你已经为这个功能写了一个测试,那我们就知道它“should 或 will”工作(如果不能工作的话,那我们知道我们需要修复它)。

优秀的Java程序测试是什么样的?

  将测试名称当作一个要求。 下面是一些例子

addingNumbersWillSumValuesTogether () explodesOnNegativeID () notifiesListenersOnUpdates ()

  不要害怕表达出来。如果你的测试名称确实需要很长的一串单词,那就这么做,只要它能清楚说明将发生什么事情。

  测试代码

  测试将分为 3 个部分:设置,操作,断言。

  设置

  对你的测试设置代码应该只与在测试中被断言的值相关。如果你有多余的设置代码,那就会搞不清楚它是什么,并且与测试不相关。

  这可以通过多种方式实现:

将通用设置移动到使用@Before 注解的具体设置方法。

将重复的设置代码移动到辅助方法

使用 Maker 来创建复杂的测试对象,并只设置测试中相关的值。

  我重申一下:每个测试的设置部分应该只有与最后被断言的值相关的代码。

  不好的例子:

@Test public void returnsBooksWherePartialTitleMatchesInAnyCast (){ Bookstore bookstore = new Bookstore (); Book harryPotterOne = new Book ("Harry Potter and The Philosopher Stone"); bookstore.add (harryPotterOne); bookstore.add (new Book ("Guardians of the Galaxy")); Book harryPotterTwo = new Book ("The Truth about HARRY POTTER"); bookstore.add (harryPotterTwo); List<Book> results = bookstore.findByTitle ("RY pot"); assertThat (results.size (), is(2)); assertThat (results, containsInAnyOrder (harryPotterOne, harryPotterTwo)); }

  书店的初始化发生在测试中,书本的创建也是。这让测试显得混乱不堪,让人搞不清楚发生了什么事情。

  好的例子:

private Bookstore bookstore = new Bookstore (); private Book aHarryPotterBook = new Book ("Harry Potter and The Philosopher Stone"); private Book anotherHarryPotterBook = new Book ("The Truth about HARRY POTTER"); private Book aBook = new Book ("Guardians of the Galaxy"); @Test public void returnsBooksWherePartialTitleMatchesInAnyCast (){ bookstore.add (aHarryPotterBook); bookstore.add (aBook); bookstore.add (anotherHarryPotterBook); List<Book> results = bookstore.findByTitle ("RY pot"); assertThat (results.size (), is(2)); assertThat (results, containsInAnyOrder (aHarryPotterBook, anotherHarryPotterBook)); }

  初始化发生在字段中,这样在测试中发生了什么一清二楚。

  操作

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/bf4de450f36a46099bf86463cad0f4bc.html