自动生成单元 - 测试遗留Java代码

时间:2008-09-17 08:35:01

标签: java unit-testing legacy

什么是自动生成Java单元测试的最佳,最好是免费/开源工具?我知道,单元测试实际上不能用于记录和驱动系统设计的普通TDD单元测试。但是,如果您拥有庞大的遗留代码库并想知道您需要进行的更改是否会产生不必要的,模糊的副作用,则自动生成的单元测试会非常有用。

5 个答案:

答案 0 :(得分:4)

不自由。不是开源。但我发现AgitarOne Agitator(http://www.agitar.com/solutions/products/agitarone.html)非常适合自动生成单元测试并寻找不必要的模糊副作用

答案 1 :(得分:3)

说实话,我可能不会这样做。单元测试是孤立的,你实际上不会知道你是否有“不必要的,模糊的副作用”,因为所有东西都会与引起副作用的其他东西隔离开来。因此,您需要集成或系统测试, 不能自动化。

构建一些高级的端到端系统测试,让您有一定程度的信心,然后使用覆盖测试来找出您错过的内容,不利的一面是,当错误出现时,它将是更难指出他们的确切原因,但好处是你更容易看到错误。

找到错误后,只为它们编写单元测试。当您继续前进时,您可以将TDD用于要重构的位。

我知道这可能不是你想听到的答案,但我已经测试了许多年,这是一个坚实的方法(虽然我很难称之为唯一的方法:)

答案 2 :(得分:3)

有趣的是,但是这样的生成的单元测试实际上很有用。如果您正在处理遗留应用程序,那么通常很难编写正确的,最先进的单元测试。

这样生成的测试(如果你有办法生成它们的话)可以确保代码的行为在你的更改期间保持不变,这可以帮助你重构代码并编写更好的测试

现在关于自我生成。我不知道任何魔术工具,但您可能想要搜索JUnit功能,包括在方法的javadocs中包含一些测试。这将允许您编写一些简单的测试。是的,它实际上有一些价值。

其次,你可以手工编写“大”测试。当然,这些不是单元测试本身(没有隔离,潜在的副作用等),但可能是良好的第一步。特别是如果你没有时间和遗留应用程序。

奖金提示!有一本很好的书“使用遗留代码有效地工作”,其中包含Java中的示例,包括在这种情况下使用的技术。不幸的是,你必须手动做一些事情,但无论如何你都必须这样做。

答案 3 :(得分:3)

Eclipse的Coview插件(http://www.codign.com/products.html)看起来就像是工作。我有兴趣生成涵盖代码中所有路径的测试,而这似乎就是这样做的。它还会产生嘲笑,这应该可以节省大量的时间。

答案 4 :(得分:1)

Diffblue Cover是执行此操作的产品,并且有一个免费的Community Edition,它是IntelliJ插件,在这里:https://plugins.jetbrains.com/plugin/14946-diffblue-cover-community-edition--unit-test-generator

它通过强化学习来搜索可能有用的测试的空间,并努力编写类似于人类的测试。它会自动创建模拟并具有完整的Spring / SpringBoot支持。

这是在Spring PetClinic中针对所有者控制器编写的示例测试:

@Test
public void testInitUpdateOwnerForm() throws Exception {
    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(or(isA(Integer.class), isNull()))).thenReturn(owner);
    MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/owners/{ownerId}/edit", 123456789);
    ResultActions actualPerformResult = this.mockMvc.perform(requestBuilder);
    ResultActions resultActions = actualPerformResult.andExpect(MockMvcResultMatchers.status().isOk());
    ResultActions resultActions1 = resultActions.andExpect(MockMvcResultMatchers.model().size(1));
    resultActions1.andExpect(MockMvcResultMatchers.model().attributeExists("owner"));
}