【问题标题】:Auto-generating Unit-Tests for legacy Java-code [closed]为遗留 Java 代码自动生成单元测试 [关闭]
【发布时间】:2010-09-10 00:25:24
【问题描述】:

用于自动生成 Java 单元测试的最好的、最好是免费/开源的工具是什么?我知道,单元测试不能真正起到与记录和驱动系统设计的普通 TDD 单元测试相同的目的。但是,如果您拥有庞大的遗留代码库并想知道您需要进行的更改是否会产生不希望的、晦涩的副作用,那么自动生成的单元测试可能会很有用。

【问题讨论】:

    标签: java unit-testing legacy


    【解决方案1】:

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

    【讨论】:

    • 我很想看到像 Agitar 这样的开源实现 - 这是开源应该非常适合的东西。
    【解决方案2】:

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

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

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

    其次,您可以手动编写“大”测试。当然,这些本身不会是单元测试(没有隔离、潜在的副作用等),但可能是很好的第一步。尤其是在您没有时间和遗留应用程序的情况下。

    额外提示! 有一本很棒的书“有效地使用遗留代码”,其中包含 Java 示例,包括在这种情况下使用的技术。不幸的是,您必须手动执行某些操作,但无论如何您都必须在某个步骤中执行此操作。

    【讨论】:

      【解决方案3】:

      说实话,我可能不会这样做。单元测试是孤立的,你实际上不会知道你是否有“不需要的、晦涩的副作用”,因为一切都与导致副作用的其他事物隔离开来。因此,您需要集成或系统测试,而 不是您可以自动化的。

      构建一些高级的端到端系统测试,让您有一定的信心,然后使用覆盖测试找出您遗漏了什么,缺点是当错误出现时,它会很难指出它们的确切原因,但好处是您更有可能看到这些错误。

      一旦发现错误,就为它们编写单元测试。随着您的前进,您可以将 TDD 用于要重构的位。

      我知道这可能不是您想听到的答案,但我已经测试了很多很多年,这是一种可靠的方法(尽管我很难称它为唯一的方法:)

      【讨论】:

      【解决方案4】:

      用于 Eclipse 的 Coview 插件 (http://www.codign.com/products.html) 看起来恰到好处。我有兴趣生成涵盖代码中所有路径的测试,这似乎可以做到。它还会生成模拟,这应该可以节省我大量的时间。

      【讨论】:

        【解决方案5】:

        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"));
        }
        

        【讨论】:

          猜你喜欢
          • 2010-12-05
          • 2014-03-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多