用于自动生成 Java 单元测试的最好的、最好是免费/开源的工具是什么?我知道,单元测试不能真正起到与记录和驱动系统设计的普通 TDD 单元测试相同的目的。但是,如果您拥有庞大的遗留代码库并想知道您需要进行的更改是否会产生不需要的、晦涩的副作用,那么自动生成的单元测试可能会很有用。
5 回答
不是免费的。不是开源的。但我发现 AgitarOne Agitator ( http://www.agitar.com/solutions/products/agitarone.html ) 非常适合自动生成单元测试并寻找不需要的晦涩副作用
这很有趣,但是这样生成的单元测试实际上很有用。如果您正在处理遗留应用程序,通常很难编写正确的、最先进的单元测试。
这样生成的测试(当然,如果您有生成它们的方法)可以确保代码的行为在您的更改期间保持不变,这可以帮助您重构代码并编写更好的测试。
现在关于生成自身。我不知道任何魔术工具,但您可能想搜索 JUnit 功能,以在 javadocs 中包含一些方法测试。这将允许您编写一些简单的测试。是的,它实际上具有一定的价值。
其次,您可以手动编写“大”测试。当然,这些本身并不是单元测试(没有隔离、潜在的副作用等),但可能是很好的第一步。特别是如果您没有时间和遗留应用程序。
奖金提示!有一本很棒的书“有效地使用遗留代码”,其中包含 Java 示例,包括在这种情况下使用的技术。不幸的是,您必须手动执行某些操作,但无论如何您都必须在某个步骤中执行此操作。
老实说,我可能不会这样做。单元测试是孤立的,你实际上不会知道你是否有“不想要的、晦涩的副作用”,因为一切都与导致副作用的其他事物隔离开来。因此,您需要集成或系统测试,而这不是您可以自动化的。
构建一些高级的、端到端的系统测试,给你一定程度的信心,然后使用覆盖测试来找出你错过了什么,缺点是当错误出现时,很难指出他们的确切原因,但好处是你更有可能看到错误。
一旦发现错误,就为它们编写单元测试。随着您的前进,您可以将 TDD 用于要重构的位。
我知道这可能不是您想听到的答案,但是我已经测试了很多很多年,这是一种可靠的方法(尽管我几乎不会将其称为唯一方法:)
Eclipse 的 Coview 插件 (http://www.codign.com/products.html) 看起来恰到好处。我有兴趣生成涵盖代码中所有路径的测试,这似乎可以做到。它还会生成模拟,这应该可以节省我大量的时间。
Diffblue Cover 是一款可以做到这一点的产品,并且有一个免费的社区版,它是一个 IntelliJ 插件,在这里:https ://www.diffblue.com/community-edition/download/
它通过使用强化学习来搜索可能有用的测试空间,并努力编写类似人类的测试。它会自动创建模拟并具有完整的 Spring/SpringBoot 支持。
这是它编写的 Spring PetClinic 中所有者控制器的示例测试:
@Test
public void testInitUpdateOwnerForm() throws Exception {
// Arrange
Owner owner = new Owner();
owner.setLastName("Doe");
owner.setId(1);
owner.setCity("Oxford");
owner.setPetsInternal(new HashSet<Pet>());
owner.setAddress("42 Main St");
owner.setFirstName("Jane");
owner.setTelephone("4105551212");
when(this.ownerRepository.findById((Integer) any())).thenReturn(owner);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/owners/{ownerId}/edit", 123456789);
// Act and Assert
MockMvcBuilders.standaloneSetup(this.ownerController)
.build()
.perform(requestBuilder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.model().size(1))
.andExpect(MockMvcResultMatchers.model().attributeExists("owner"))
.andExpect(MockMvcResultMatchers.view().name("owners/createOrUpdateOwnerForm"))
.andExpect(MockMvcResultMatchers.forwardedUrl("owners/createOrUpdateOwnerForm"));
}