Diffblue Cover AI Java:Difflane如何利用Diffblue Cover AI实现Java自动化的单元测试(Diffblue Cover快速入门)

Diffblue Cover AI实现Java自动化的单元测试工具

基本概念

什么是Diffblue Cover?

Diffblue Cover是一种自动化的单元测试编写工具。它分析您现有的Java应用程序,并编写反映当前行为的单元测试,从而增加测试范围并帮助您在将来的代码更改中查找回归。Cover在代码更改时通过更新测试来自动维护测试。Cover支持标准Java 8和11,Spring和Spring Boot。

Cover可以作为Windows和Linux的CLI工具使用,并且可以在您的Maven或Gradle环境中自行配置,可以100%自主运行。还有用于IntelliJ IDEA的Cover插件,用于交互式测试编写。

由VERTIV赞助

总部位于英国牛津大学的初创公司Diffblue对此深信不疑。周二,Diffblue宣 布其旗舰产品Diffblue Cover和Diffblue Cover: Community Edition全面上市,这是使用IntelliJ(最流行的企业Java IDE)为开发人员创建的免费版本。

Diffblue 官网

https://www.diffblue.com/products/
在这里插入图片描述

一、Diffblue Cover能做什么

Diffblue Cover分析您现有的Java程序并编写反映代码当前行为的单元回归测试。
当您的代码的行为发生变化时,Diffblue Cover的测试将提醒您。

在这里插入图片描述

二、它如何工作的

它是如何工作的?
Diffblue Cover是适用于Linux和Windows的软件,可在您的计算机上本地运行100%。

您可以在整个Java项目中运行它,也可以只运行一个类,也可以在两者之间运行任何东西。它从Maven或Gradle获取您的项目结构和依赖关系。Cover支持Spring Java应用程序,并编写使用标准Spring习语和模拟的测试。
在这里插入图片描述

三、如何使用

1、Diffblue Cover:下载链接https://www.diffblue.com/community-edition/download

在这里插入图片描述

2、关于Cover IntelliJ插件

有两个Diffblue IntelliJ插件-完整的Cover IntelliJ插件和Cover Community Edition IntelliJ插件。Cover Community Edition是免费的,可以用于开放源代码项目;Cover的完整(收费)版本可用于任何项目,并获得Diffblue的全面支持。

下面和知识库中的文档介绍了此版本,并提供了完整的支持。

要获得免费的Community Edition Cover IntelliJ插件,请转到下载 页面。下面和知识库中的文档涵盖了此版本,但也可能包含Community Edition中不可用的功能。社区支持可从社区论坛获得。

3、先决条件

IntelliJ版本2019.3或更高版本

Java 8或11源代码

基于Maven或Gradle的项目

2 GB最小存储器要求(修订本中的IntelliJ,选择Help然后Change Memory Settings)
您的项目必须编译并运行

Diffblue Cover将运行它为您的代码编写的测试,因此您的项目必须编译并运行,以使Cover正常工作。

您的项目配置(例如,pom.xml对于Maven项目)必须包括所有必需的依赖项,并且它们都必须已经构建或下载(例如,通过mvn clean install对Maven项目进行构建)。

JUnit始终是必需的依赖项。
在这里插入图片描述
如果它们是您项目的可传递依赖项,则可能需要下面列出的依赖项。

如果这些依赖关系中的一种是必需的,但是缺少,则会为某些类生成测试,而不会为其他类生成测试。

一条消息将出现在事件日志中,指示缺少依赖项。
在这里插入图片描述
请注意,您只能在一个项目上运行Cover IntelliJ插件的一个实例。不支持在同一项目上运行多个实例。

4、安装Cover IntelliJ插件

如果您不是直接从JetBrains市场安装,则将zip文件下载到合适的位置。

从IntelliJ IntelliJ IDEA -> Preferences(macOS)或File -> Settings(Windows / Linux)菜单中选择Plugins项目。

单击Installed窗口顶部选项卡右边的齿轮图标。从下拉菜单中选择Install Plugin from Disk…

导航到插件的位置,选择zip文件,然后单击Open。点击OK。

在这里插入图片描述
当提示您这样做时,请单击到Restart IDE,然后单击确定OK。

5、汇入 CoreBanking

该CoreBanking应用程序是一个用于演示目的的简单银行应用程序,可以在https://github.com/diffblue/CoreBanking中找到。

在不加载项目的情况下启动IntelliJ以查看欢迎屏幕:
在这里插入图片描述
选择Get from Version Control选项。选择Git从版本控制下拉框。CoreBanking在存储库框中输入url,为项目选择合适的位置。然后,单击Clone。

在这里插入图片描述

使用Al, Diffblue可以以人 类可读的形式自动编写Java单元测试,覆盖率高达80%,随着代码的发展,即使在具有数百万行代码的应用程序上,它们也可以自动维护测试。

6、编写新测试

为了为当前未涵盖的类生成新的测试:

选择Project窗口。
选择CoreBanking-> src-> main-> java-> io.diffblue.corebanking-> account-> Account
右键单击并Write Tests从菜单中选择选项。
成功克隆后,展开下面的CoreBanking部分Project以查看源树。

在这里插入图片描述
该插件在分析代码和创建测试之前先构建项目。生成项目后,单击屏幕底部的进度栏以打开一个弹出窗口。

进度窗口将显示分析所经历的不同阶段。在分析代码时,可以查看当前进度,但是在较小的项目(例如)中CoreBanking,这是一个非常短的时间范围。

创建新测试后,它们将被自动集成到项目中src/test/java。

请注意,也可以Write Tests通过右键单击以下内容:

源代码编辑器中的各个类
源代码编辑器中的各个方法
源文件顶部的选项卡中的各个类 Project菜单中其类内的各个方法(如果Show Members右键单击Project菜单后已选择)

在IDE的其他地方(例如在测试类或非Java文件中),该Write Tests功能被禁用。

7、运行测试

在Diffblue Cover为您的项目编写测试之后,它们将自动集成到您的测试套件中。Diffblue Cover创建的测试使用JUnit测试框架,因此junit包含在的CoreBanking项目依赖项中pom.xml。

在项目浏览器中,从CoreBanking-> src-> test-> java-> io.diffblue.corebanking-> ->中选择新类AccountTest,然后右键单击并选择Run 'AccountTest'

在这里插入图片描述
然后将显示JUnit运行的结果:
在这里插入图片描述

四、封面示例测试

在本文中,我们将显示输入源和Cover生成的各种复杂性代码的测试,并附有详细的叙述,以帮助您进一步了解Cover生成的测试。

1、基本断言

这是一个带有简单getter的Spring Service源代码的简单示例。DCover可以通过内联写一个春天开机测试的服务提供商,吸气Arrange,Act和Assert。

1.1、来源
import org.springframework.stereotype.Service;

@Service
public class SimpleService
{
    
    
  public String getValue() {
    
    
    return "a really simple service";
  }
}
1.2、 Diffblue Cover产生的测试
@SpringBootTest
@RunWith(org.springframework.test.context.junit4.SpringRunner.class)
public class SimpleServiceDiffblueTest {
    
    
  @Autowired
  private SimpleService simpleService;
  @Test
  public void testGetValue() {
    
    
    // Arrange, Act and Assert
    assertEquals("a really simple service", this.simpleService.getValue());
  }
}

2、模拟

此类包含两个方法,用于从Amazon S3存储桶上传文件和从Amazon S3存储桶下载文件。由于Amazon S3存储桶是一种云存储机制,因此此类/方法的测试需要依赖项注入。downloadFileFromBucket通过声明所需的S3Object和使用该方法下载的S3Object,DCover可以模拟这些类型的依赖关系并测试方法。

2.1、来源
@Service
public class AmazonService {
    
    

  @Autowired
  private AmazonS3 s3client;

  public PutObjectResult uploadFileToBucket(String bucketName, String key, File file) {
    
    
    return s3client.putObject(bucketName, key, file);
  }

  public S3Object downloadFileFromBucket(String bucketName, String key) {
    
    
    return s3client.getObject(bucketName, key);
  }
}
2.2 、Diffblue Cover生成的测试
@SpringBootTest
public class AmazonServiceDiffblueTest {
    
    
  @MockBean
  private AmazonS3Client amazonS3Client;
  @Autowired
  private AmazonService amazonService;
  @Test
  public void testUploadFileToBucket() {
    
    
    // Arrange
    PutObjectResult putObjectResult = new PutObjectResult();
    putObjectResult.setContentMd5("file-hash");
    when(this.amazonS3Client.putObject(or(isA(String.class), isNull()), or(isA(String.class), isNull()),
        or(isA(File.class), isNull()))).thenReturn(putObjectResult);

    // Act and Assert
    assertSame(putObjectResult, this.amazonService.uploadFileToBucket("foo", "foo",
        Paths.get(System.getProperty("java.io.tmpdir"), "test.txt").toFile()));
  }
  @Test
  public void testDownloadFileFromBucket() throws UnsupportedEncodingException {
    
    
    // Arrange
    StringInputStream objectContent = new StringInputStream("file-name");
    S3Object s3Object = new S3Object();
    s3Object.setObjectContent(objectContent);
    when(this.amazonS3Client.getObject(or(isA(String.class), isNull()), or(isA(String.class), isNull())))
        .thenReturn(s3Object);

    // Act and Assert
    assertSame(s3Object, this.amazonService.downloadFileFromBucket("foo", "foo"));
  }
}

3、与操作系统无关的断言

本示例以其他格式返回时间。DCover编写一个测试以声明不依赖于操作系统或本地时区的日期和时间。

3.1、来源
public class TimeInAliceWonderland {
    
    

  private static final String DODO_DATETIME_FORMAT = "ss:mm:HH dd-MMM-yyyy";

  public static String reformatDodoDateTime(Date humanDate) {
    
    
    Map<String, DateFormat> dateFormatMap = new HashMap<>();
    dateFormatMap.put(DODO_DATETIME_FORMAT, new SimpleDateFormat(DODO_DATETIME_FORMAT));
    return dateFormatMap.get(DODO_DATETIME_FORMAT).format(humanDate);
  }
}
3.2、 Diffblue Cover产生的测试
@Test
  public void testReformatDodoDateTime() {
    
    
    LocalDateTime atStartOfDayResult = LocalDate.of(1970, 1, 1).atStartOfDay();
    assertEquals("00:00:00 01-Jan-1970", TimeInAliceWonderland
        .reformatDodoDateTime(
            Date.from(atStartOfDayResult.atZone(ZoneId.systemDefault()).toInstant())));
  }

4、包含逻辑的例子

在此示例中,DCover编写了两个测试以覆盖通过条件的每个路径-一个将余额加10并断言新余额应为20的测试,以及另一个关闭帐户的测试。

4.1、资料来源
public class Account {
    
    
  private final long accountNumber;
  private final Client client;
  private long currentBalance;
  private String accountName;
  private AccountState accountState;

  public Account(final long accountNumber, final Client client, final long amount) {
    
    
    this.accountNumber = accountNumber;
    this.client = client;
    currentBalance = amount;
    accountName = "Current";
    accountState = AccountState.OPEN;
  }

  public long getCurrentBalance() {
    
    
    return currentBalance;
  }

  public void addToBalance(final long amount) throws AccountException {
    
    
    if (getAccountState() != AccountState.OPEN) {
    
    
      throw new AccountException("Cannot add to balance, account is closed.");
    }
    currentBalance += amount;
  }
4.2 Diffblue Cover产生的测试

 @Test
  public void testAddToBalance() throws AccountException {
    
    
    // Arrange
    Account account = new Account(1234567890L, new Client("Carlos Welch"), 10L);

    // Act
    account.addToBalance(10L);

    // Assert
    assertEquals(20L, account.getCurrentBalance());
  }

5、复杂逻辑的例子

此示例代码具有3个分支-DCover覆盖了100%的分支,并使用现有的枚举值针对三种情况创建了三个测试。

5.1、资料来源
public class VirtualSnackCupboard {
    
    

  public static Snack whatCanISnackNow(int oClock) {
    
    
    if (oClock == 10) {
    
    
      return Snack.CHOCOLATE;
    } else if (oClock == 15) {
    
    
      return Snack.CAKES;
    } else {
    
    
      return Snack.VEGGIE;
    }
  }
  enum Snack {
    
    VEGGIE, CHOCOLATE, CAKES}
}
5.2、 Diffblue Cover生成的测试
  public void testPickSnack() {
    
    
    assertEquals(VirtualSnackCupboard.Snack.CHOCOLATE, VirtualSnackCupboard.whatCanISnackNow(10));
    assertEquals(VirtualSnackCupboard.Snack.CAKES, VirtualSnackCupboard.whatCanISnackNow(15));
    assertEquals(VirtualSnackCupboard.Snack.VEGGIE, VirtualSnackCupboard.whatCanISnackNow(0));

可以看出,Diffblue Cover可以针对多种代码场景生成测试-我们鼓励您尝试Cover Cover CLI和Cover IntelliJ插件,以了解更多信息。

五、更多内容请看官方文档:https://docs.diffblue.com/getting-started/cover-intellij-plugin/

哦,它的执行速度比人类快10到100倍。不错。

正如Diffblue首席执行官Mathew Lodge在一次采访中指出的那样,具有讽刺意味的是,鉴于我们如何使用AI来自动化和颠覆零售,旅行等许多其他行业,软件行业拥抱Al改善软件开发有多晚,运输,制造等。

Lodge说,Diffblue的研究人员利用了AlphaGo的机器学习策略,AlphaGo是Alphabet耔 公司DeepMind的软件程序,击败了Go的世界冠军。

当公司开始使用Java解决方案(迄今为止,这是全球2000年最受欢迎的语言,

公司在生产力工具上投入大量资金)时,其技术也可以用于对大多数编程语言(例如Python, JavaScript和C#)进行自动化测试。等等。
高盛(年度IT预算大于许多国家的GDP)是首批推出Diffblue解决方案的客户。

在一个具有重要后端系统的模块上 使用Diffblue的Al,高盛能够在不到24小时的时间内将现有的单元测试覆盖率从36%扩展到72%,这一壮举如果需要手动完成,将需要超过八天的开发时间。节省开发人员时间?90%。

Lodge认为系统变得如此复杂和庞大,以至于软件供应链的大部分构建,交付和维护工作,都比机器要好于人工。

从这个角度来看,他与Tyler Jewell-起加入, Tyler Jewell是一-位投资人,他撰写了- -些有关开发人员工具的最佳分析。

根据Jewell的说法:

由于工具和编程语言的碎片化,API的泛滥,微服务以及将大数据,分析,ML和反应性用户体验分层到项目中,软件系统变得更加复杂。

随着复杂性的增加,持续交付缩短了反馈循环,同时为开发人员提供了每次更改的更深入的见解。

与人相比,机器具有更好的装备,可以根据持续的反馈采取行动,并建议对极其复杂的系统
进行更改。

正如Jewell继续所说的那样,“数字服务的需求已经超过 了构建它们的工程师的供应,为可以提高开发人员生产力的供应商创造了机会。”

机器人交响曲并非只有Diffblue将此视为巨大的市场机会。在新出现的DevOps趋势的推动下,开发人员,运营和安全解决方案越来越多地转向预生产阶段,
并进一步移交给在编排之前构建模块的开发人员手中(例如,请参见Cyral的安全性, Vercel适用于JavaScript和React前端框架,Diffblue适用于单元测试自动化。

这种更大的变化与行业在数字化转型和云原生的新世界中对容器(通常是云)的采用相一致。当然,许多全球SaaS_上市公司在全球大流行中报告了惊人的季度收益和增长,这表明该类别的赢家将来会是什么样。

如今,SaaS 云公共市场EV /未来12个月收入中位数的比率达到惊人的15倍。2020年全球信息技术产业将达到5.2万亿美元,其中624B美元是软件。开发人员推动了软件市场份额的不断增长。

自主软件开发将是计算未来的重要组成部分。

Diffblue仅仅是 软件产业AI中断的开始。

猜你喜欢

转载自blog.csdn.net/qq_44757034/article/details/112796273