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

发布于 2024-07-04 06:31:13 字数 1560 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云不回头 2024-07-11 06:31:13

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

构建一些高级的端到端系统测试,这会给您一定程度的信心,然后使用覆盖率测试来找出您错过的内容,缺点是当错误出现时,将很难指出其确切原因,但好处是您更有可能看到这些错误。

一旦发现错误,就为它们编写单元测试。 随着您的前进,您可以使用 TDD 来重构您想要重构的部分。

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

To be honest, I probably wouldn't do this. Unit tests are isolated and you won't actually know if you have "unwanted, obscure side-effects" because everything is walled off from the other things that cause the side effects. As a result, you need integration or system testing and that is not something you can automate.

Build a few high-level, end-to-end system tests which give you a degree of confidence and then use coverage testing to find out what you've missed, The downside is that when bugs crop up, it will be harder to point to their exact cause, but the upside is that you'll be far more likely to see the bugs.

Once you find bugs, write unit tests just for them. As you move forward, you can use TDD for the bits you want to refactor.

I know this probably wasn't the answer you want to hear, but I've been testing for many, many years and this is a solid approach (though I would hardly call it the only approach :)

可爱暴击 2024-07-11 06:31:13

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

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

现在关于生成自身。 我不知道有什么神奇的工具,但您可能想搜索有关在方法的 javadoc 中包含一些测试的 JUnit 功能。 这将允许您编写一些简单的测试。 是的,它实际上有一定的价值。

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

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

It is interesting, but such generated unit tests can actually be useful. If you're working on a legacy application, it will be often hard to write correct, state-of-the-art unit tests.

Such generated tests (if you have a way of generating them of course) can then make sure that behavior of code stays intact during your changes, which then can help you refactor the code and write better tests.

Now about generating itself. I don't know about any magic tool, but you may want to search for JUnit functionality about including some tests in javadocs for methods. This would allow you to write some simple tests. And yes, it's actually of some value.

Second, you can just write "big" tests by hand. Of course, these wouldn't be unit tests per se (no isolation, potential side-effects, etc), but could be good first step. Especially if you have little time and a legacy application.

Bonus Tip! There is an excellent book "Working effectively with legacy code" with examples in Java, including techniques right to use in such situations. Unfortunately you would have to do some things manually, but you would have to do that at some step anyway.

网白 2024-07-11 06:31:13

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

Not free. Not opensource. But I have found AgitarOne Agitator (http://www.agitar.com/solutions/products/agitarone.html) to be REALLY good for automatically generating unit tests AND looking for unwanted obscure side effects

娇俏 2024-07-11 06:31:13

Eclipse 的 Coview 插件 (http://www.codign.com/products.html) 看起来正是这个工作。 我有兴趣生成覆盖代码中所有路径的测试,这似乎可以做到这一点。 它还生成模拟,这应该节省我大量的时间。

Coview plugin for Eclipse (http://www.codign.com/products.html) looks just the job. I'm interested in generating tests that cover all the paths in the code, and this seems to do it. It also generates the mocks which should save me tons of time.

就是爱搞怪 2024-07-11 06:31:13

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

Diffblue Cover is a product that does this, and there is a free Community Edition that's an IntelliJ plugin, here: https://www.diffblue.com/community-edition/download/

It works by using reinforcement learning to search the space of potentially useful tests, and strives to write human-like tests. It automatically creates mocks and has full Spring/SpringBoot support.

Here's an example test for the owner controller in Spring PetClinic that it wrote:

@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"));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文