JavaParser抽取测试用例对应的被测方法

news2024/11/27 4:29:40

背景介绍

博主目前要做的工作需要将一个java项目的所有RD手写的测试用例和被测方法对应起来,最后将得到的结果存入一个json文件。

本教程以项目GitHub - binance/binance-connector-java 为例。

结果展示

最终会得到一个 funcTestMap.json,里面存放着focal func(被测方法)和对应的test case.

实现原理

1. 解析被测项目的src\main目录下的源码,将每一个java源文件中的方法声明(MethodDeclaration)存进一个map,其中key是方法名,value是完整方法题。

2. 解析被测项目的src\test\java\unit目录下的测试文件,对于每一个测试文件中的方法声明,如果方法名以"test"开头,则认为是测试用例,进入下一步。

3. 解析每一个测试用例,获取该测试用例的调用的所有方法MethodCallExpr,如果该方法存在第一步所得到的map当中,则认为该方法是测试用例的被测方法,和测试用例一起存入结果json数组中。

局限性

没有考虑到overload的情况。由于是根据方法名称而不是名称+参数类型作为方法的标识符。在存入阶段,遇到重载的方法,后面进的会覆盖掉之前的;在召回阶段,仅仅使用方法名称来查找方法体,有一定的几率找到错误的被测方法。

完整代码

项目结构如下

JsonCreator.java

package org.example;

import com.github.javaparser.ast.body.MethodDeclaration;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Map;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;

public class JsonCreator {
    public static void createAndSaveJson1(Map<String, MethodDeclaration> map, String saveJsonPath) {
        JsonArray jsonArray = new JsonArray();
        for (Map.Entry<String, MethodDeclaration> entry : map.entrySet()) {
            JsonObject keyValue = new JsonObject();
            keyValue.addProperty("key", entry.getKey());
            keyValue.addProperty("value", String.valueOf(entry.getValue()));
            jsonArray.add(keyValue);
        }

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String jsonOutput = gson.toJson(jsonArray);

        try {
            Files.write(Paths.get(saveJsonPath), jsonOutput.getBytes(StandardCharsets.UTF_8));
            System.out.println("JSON file saved successfully to " + saveJsonPath);
        } catch (Exception e) {
            System.err.println("Error writing JSON to file: " + e.getMessage());
        }
    }

    public static void createAndSaveJson2(Map<MethodDeclaration, MethodDeclaration> map, String saveJsonPath) {
        JsonArray jsonArray = new JsonArray();
        for (Map.Entry<MethodDeclaration, MethodDeclaration> entry : map.entrySet()) {
            JsonObject keyValue = new JsonObject();
            keyValue.addProperty("focal func", String.valueOf(entry.getKey()));
            keyValue.addProperty("test case", String.valueOf(entry.getValue()));
            jsonArray.add(keyValue);
        }

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String jsonOutput = gson.toJson(jsonArray);

        try {
            Files.write(Paths.get(saveJsonPath), jsonOutput.getBytes(StandardCharsets.UTF_8));
            System.out.println("JSON file saved successfully to " + saveJsonPath);
        } catch (Exception e) {
            System.err.println("Error writing JSON to file: " + e.getMessage());
        }
    }

}


TestMethodAnalyzer.java

package org.example;

import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.comments.JavadocComment;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.utils.SourceRoot;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestMethodAnalyzer {

    private static final Map<String, MethodDeclaration> methodMap = new HashMap<>();
    private static final Map<MethodDeclaration, MethodDeclaration> funcTestMap = new HashMap<>();

    public static void main(String[] args) throws IOException {
        // Load and index all Java files from the main source directory
        SourceRoot mainSourceRoot = new SourceRoot(Paths.get("C:\\dataset\\binance-connector-java\\src\\main"));
        mainSourceRoot.tryToParseParallelized().forEach(TestMethodAnalyzer::indexMethodDeclarations);

        System.out.println("The size of the map is: " + methodMap.size());
        String saveJsonPath1 = "C:\\codes\\Java\\extract_func_test_pair\\src\\main\\java\\org\\methodMap.json";
        JsonCreator.createAndSaveJson1(methodMap,saveJsonPath1);

        // Now parse the test files
        SourceRoot testSourceRoot = new SourceRoot(Paths.get("C:\\dataset\\binance-connector-java\\src\\test\\java\\unit"));
        testSourceRoot.tryToParseParallelized().forEach(TestMethodAnalyzer::analyzeTestClass);

        System.out.println("The size of the map is: " + funcTestMap.size());
        String saveJsonPath2 = "C:\\codes\\Java\\extract_func_test_pair\\src\\main\\java\\org\\funcTestMap.json";
        JsonCreator.createAndSaveJson2(funcTestMap,saveJsonPath2);
    }

    private static void indexMethodDeclarations(ParseResult<CompilationUnit> result) {
        result.ifSuccessful(cu -> cu.findAll(MethodDeclaration.class).forEach(md -> {
            md.setJavadocComment((JavadocComment) null);
            methodMap.put(md.getNameAsString(), md);
        }));
    }

    public static void analyzeTestClass(ParseResult<CompilationUnit> result) {
        result.ifSuccessful(cu -> {
            cu.accept(new VoidVisitorAdapter<Void>() {
                @Override
                public void visit(MethodDeclaration md, Void arg) {
                    super.visit(md, arg);
                    if (md.getNameAsString().startsWith("test")) {
                        analyzeTestMethods(md);
                    }
                }
            }, null);
        });
    }

    private static void analyzeTestMethods(MethodDeclaration md) {
        List<MethodCallExpr> methodCalls = md.findAll(MethodCallExpr.class);
        for (MethodCallExpr call : methodCalls) {
            MethodDeclaration method = methodMap.get(call.getNameAsString());

            if (method != null) {
                System.out.println("Test Method: ");
                System.out.println(md);
                System.out.println("Calls Method body:");
                method.setJavadocComment((JavadocComment)null);
                System.out.println(method);
                System.out.println("---------------------------------------");

                funcTestMap.put(method,md);
            }
        }


    }

}

maven依赖

只有两个(位于pom.xml)

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>
    <dependency>
        <groupId>com.github.javaparser</groupId>
        <artifactId>javaparser-symbol-solver-core</artifactId>
        <version>3.26.0</version>
    </dependency>
</dependencies>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1874991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习实验第T2周:彩色图片分类

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](https://mp.weixin.qq.com/s/0dvHCaOoFnW8SCp3JpzKxg) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](https://mtyjkh.blog.csdn.net/)** 目录 一、前言 目标 二、我的环境&#…

煤安防爆手机在煤矿井下使用时需要符合什么标准

煤安防爆手机在煤矿井下使用时&#xff0c;需符合严格的防爆安全标准&#xff0c;如煤安MA防爆合格证&#xff0c;以确保在易燃易爆环境中安全无虞。同时&#xff0c;手机还需具备防尘防水、抗冲击等环境适应性要求&#xff0c;以及优异的通信性能&#xff0c;以满足煤矿工作的…

python 获取遮挡窗口界面并操作窗口

有时候我们需要程序自动化帮我们处理一些事情,这时候我们会想到使用按键精灵等一些可以模拟人工操作的软件代替我们劳动,但是,这种操作有个前提就是需要将操作界面置于最顶层,这样就会影响我们做其他事情,这时我们就不希望操作界面置于最外层,影响我们做其他操作。 今天…

JAVA毕业设计145—基于Java+Springboot+vue+uniapp的驾校预约小程序(源代码+数据库+15000字论文)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvueuniapp的驾校预约小程序(源代码数据库15000字论文)145 一、系统介绍 本项目前后端分离&#xff0c;分为用户、教练、管理员三种角色 1、用户&#xff1a; …

技术分享:分布式数据库DNS服务器的架构思路

DNS是企业数字化转型的基石。伴随微服务或单元化部署的推广&#xff0c;许多用户也开始采用分布式数据库将原来的单体数据库集群服务架构拆分为大量分布式子服务集群&#xff0c;对应不同的微服务或服务单元。本文将从分布式数据库DNS服务器的架构需求、架构分析两方面入手&…

今天起,全球所有Mac用户可免费安装桌面版ChatGPT

在 macOS 上&#xff0c;用户在安装新的 ChatGPT 应用程序后&#xff0c;使用 Option Space 的键盘组合即可快速调用 ChatGPT。 刚刚&#xff0c;OpenAI 宣布推出适用于 macOS 的应用程序。 虽然 Mac 应用程序尚未在 Mac App Store 中提供&#xff0c;但用户可以直接从 Open…

计算机网络之OSI七层体系结构

目录 1.物理层 1.1物理层组成 1.2物理层功能 1.3物理层服务 1.4物理层标准 1.5物理层接口 2.数据链路层 2.1基于物理层的问题 2.2数据链路层功能 2.3数据链路层服务 2.4数据链路层协议 3.网络层 3.1基于DL层的问题 3.2网络层功能 3.3网络层服务 3.4网络层协议 …

饮料添加剂光照试验太阳光模拟器试验箱

饮料添加剂光照试验是一种用来评估饮料在光照条件下稳定性的实验方法。这个过程通常包括以下几个步骤&#xff1a; 样品准备&#xff1a; 首先&#xff0c;将饮料密封在市售包装或近似市售包装中&#xff0c;确保包装的完整性和密封性。 光照条件设置&#xff1a; 将封装好的…

开源大模型RAG企业本地知识库问答机器人-ChatWiki

ChatWiki ChatWiki是一款开源的知识库 AI 问答系统。系统基于大语言模型&#xff08;LLM &#xff09;和检索增强生成&#xff08;RAG&#xff09;技术构建&#xff0c;提供开箱即用的数据处理、模型调用等能力&#xff0c;可以帮助企业快速搭建自己的知识库 AI 问答系统。 开…

idea2024使用springboot3.x系列新建java项目,使用jdk17,启动项目报错

身为一名开发人员&#xff0c;敲代码无数&#xff0c;竟被一个小小启动给我卡了大半天&#xff0c;太丢脸了 报错一&#xff1a;Field infoSysRepository in com.erectile.Impl.PersonalInfoServiceImpl required a bean of type ‘com.erectile.jpa.repository.InfoSysReposit…

短视频视频配:成都柏煜文化传媒有限公司

短视频视频配&#xff1a;​艺术与技术的完美融合 在短视频盛行的当下&#xff0c;一个优秀的短视频作品不仅仅依赖于精彩的内容&#xff0c;更需要在视频配上做足功夫。视频配&#xff0c;作为短视频的重要组成部分&#xff0c;涵盖了音效、配乐、字幕等多个方面&#xff0c;…

Spring Boot中 CommandLineRunner 与 ApplicationRunner作用、区别

CommandLineRunner 和 ApplicationRunner 是 Spring Boot 提供的两种用于在应用程序启动后执行初始化代码的机制。这两种接口允许你在 Spring 应用上下文完全启动后执行一些自定义的代码&#xff0c;通常用于执行一次性初始化任务&#xff0c;如数据库预填充、缓存预热等。 Co…

Docker 部署 MariaDB 数据库 与 Adminer 数据库管理工具

文章目录 MariaDBmariadb.cnf开启 binlog Adminerdocker-compose.ymlAdminer 连接 MariaDB MariaDB MariaDB是一个流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是MySQL的一个分支和替代品。 官网&#xff1a;https://mariadb.com/镜像&#xff…

拆分盘投资策略解析:机制、案例与风险考量

一、引言 随着互联网技术的迅猛发展和金融市场的不断创新&#xff0c;拆分盘这一投资模式逐渐崭露头角&#xff0c;成为投资者关注的焦点。它基于特定的拆分策略&#xff0c;通过调整投资者持有的份额和单价&#xff0c;实现了看似稳健的资产增长。本文旨在深入探讨拆分盘的运…

黑芝麻科技A1000简介

文章目录 1. A1000 简介2. 感知能力评估3. 竞品对比4. 系统软件1. A1000 简介

父元素hover子元素显示之opacity

碰到的几种问题&#xff1a; opacity 占实际位置, 会触发父元素的hover事件。 尝试了一下把菜单的pointer-events: none;但是鼠标移动不到菜单上去了&#xff0c;移动到菜单上也会不显示。 解决方法&#xff1a; opacity 和 visibility一起使用。 .dropdown .dropdown-menu …

OpenHarmony南向驱动开发实战-Input

简介 该仓下主要包含Input模块HDI&#xff08;Hardware Driver Interface&#xff09;接口定义及其实现&#xff0c;对上层输入服务提供操作input设备的驱动能力接口&#xff0c;HDI接口主要包括如下三大类&#xff1a; InputManager&#xff1a;管理输入设备&#xff0c;包括…

11集干货必看!在Docker上编译tensorFlow Lite MCU例子工程-《MCU嵌入式AI开发笔记》

【11集在Docker上编译tensorFlow Lite MCU例子工程-《MCU嵌入式AI开发笔记》】 这一集咱们一步一步的在doc下面编译TensorFlow Lite的例程 https://tensorflow.google.cn/lite/tutorials?hlzh-cn 进入这个例子&#xff1a; https://codelabs.developers.google.cn/codelabs/…

《Attention is all you need》通俗解读,彻底理解版:part2

这是《Attention Is All You Need》通俗解读的第2篇&#xff0c;上一篇见这里。 本篇解读模型结构的编码器和解码器&#xff0c;对应于论文的 3.1 小节。 这一部分在论文中作者写的并不长&#xff0c;很多内容没有展开来讲。 虽然对于这一类具有原创架构的论文而言&#xff…

open-chat-video-editor:开源短视频生成和编辑工具,以及抖音|TikTok 的移动端短视频项目

open-chat-video-editor&#xff1a;开源短视频生成和编辑工具&#xff0c;以及抖音|TikTok 的移动端短视频项目。 open-chat-video-editor&#xff1a;开源短视频生成和编辑工具 简介 Open Chat Video Editor是开源的短视频生成和编辑工具&#xff0c;整体技术框架如下&…