转转QA CodeDiff 实现方案简述

笑哼 for 转转QA · November 01, 2018 · Last by OBJ replied at November 03, 2018 · 2516 hits

作者|黄莹

前言

CodeDiff-从字面上理解就是代码差异的比较,其实我们的测试工作从某种程度上可以理解为针对代码逻辑的测试。因此CodeDiff可以作为一种补充测试的手段,辅助我们在测试过程中通过代码内容更好地判断测试范围,以及加深对技术实现的理解,使得我们能够从内到外更好地把控项目的风险与质量。

CodeDiff的意义

在日常工作中大家进行CodeDiff所用的工具和方式多样化,但其目的都是通过两个版本的比对拿到差异内容,通过差异内容进行流程性或者模块化的梳理从而得出此次提测的改动点,然后再对其进行需求/业务相关性评估。CodeDiff需要测试人员熟悉原有业务流程与新需求所涉及的范围,对所涉及模块之间上下游的调用关系、数据流向、状态变化等有一定程度的了解,通过了解开发设计方案、接口改动等等方面来综合评估影响面以及测试/回归范围。

为什么要自研?

1、CodeDiff工具方式多样化,希望提供一个统一、简易的平台(支持SVN/Git两种模式、省去打开IDE、反复拉代码、查看无权限等繁琐操作),让每个人能快速进行Diff,培养同学diff代码的习惯;
2、目前公司开发模式统一切成Git,相比Git平台提供的能力,我们希望实现任意两个CommitId/分支之间进行diff的方式(两种Diff模式的优缺点);
3、参考业界其他互联网公司自研案例,自研的方案拓展性更强,且方便接入公司项目管理流程之中,使其能够平台化、提升效能;
CodeDiff接入到beetle中,与每一次编译做结合,开发人员可以增量查看每次编译的diff结果,测试人员可以看到每次提测基于首次编译的增量diff,也支持自主选择版本。
4、可以为所有基于代码差异的测试方法所使用,如CodeReview、代码覆盖率统计、代码静态检测、语法检测等。

设计实现

1、基本思路
自研的CodeDiff平台支持SVN、Git两种模式,虽然这两种版本控制系统存在诸多不同(集中式/分布式、用法思想上等),但CodeDiff实现的基本思路是一致的:基于任意两个版本/分支进行代码比对,得出差异结果,再将差异结果进行解析并进行展现。

2、实现方案
SVN-SVNKit
纯Java的SVN版本连接库,整个连接底层由Java实现。一共提供两个层次的API,通过这两个API就可以基本实现与客户端相同效果的操作,不需要额外的支持:

  • Low-Level API:针对Subversion Repository的操作,相当于操作Repository的中间驱动,实现了对底层协议与Subversion仓库的对话,比较抽象,可以理解为一个包含版本控制的、抽象复杂的树结构。
  • High-Level API:针对Working Copy的一系列操作,将所有管理工作拷贝的操作逻辑分配在不同的SVN*Client中。不同的操作基于不同的SVN*Client去实现。例如:所有的工作拷贝的更新操作如checkout、update都有SVNUpdateClient这个类去执行。操作方法和参数与SVN客户端命令行相似,其底层实现实际上也调用了Low-Level API。

GIT-JGIT
纯Java的Git版本控制,提供了Git命令的Java API,通过调用API可实现创建本地仓库、远程操作代码库如clone、fetch、push、diff等命令,可以达到与客户端相同的操作效果。
举个栗子:将某个git工程的版本库clone到本地,git命令行:$ git clone [url]

目前转转的研发模式已经切换至Git,接下来就以Git为例来展开介绍基于Git的CodeDiff具体是如何实现的:

Part1-差异内容的获取

(1)JGit Authentication:JGit验证机制大部分与本地Git相同,支持SSH协议和HTTP(S)协议,可以通过调用JGit提供的验证API来安全地连接远程Git库;
(2)通过实例化需要用到的git命令的方法来实现对本地仓库的操作。如CloneCommand,FetchCommand,CheckoutCommand等等,这些命令都有一个相同的基本类-TransportCommand,它提供了我们所实例的所有方法;
(3)拿到需要进行对比的两个版本参数后,通过调用git.diff()方法拿到基于这两个版本的差异结果,将结果交由处理器进行逐行解析最后返回;

Part2-全文件内容拼接

(4)拿到差异内容后,根据文件名在本地代码仓库查找目标文件,找到之后通过处理器对目标文件的内容进行逐行解析;
(5)根据文件修改类型(modify/add/remove)决定全文件内容的拼接策略,最后得到目标文件的完整内容后返回。

写在最后

1、 CodeDiff整体方案的设计和实现经历了一版又一版的迭代优化,与beetle平台集成之后也更好地服务了技术同学的日常工作,真正实现不用拉代码一键diff的目的,希望CodeDiff可以真正融入我们测试工作的日常,成为辅助测试、把控风险的有效手段,让我们每一次发布上线变得更为可靠。
2、CodeDiff为代码覆盖率统计、CodeReview的实现提供了能力支撑,也实现了相应的拓展,同时还适用于所有基于代码差异的测试方法如代码静态检测、语法检测等,为测试方法的多样化探索过程提供了更多可能性。

共收到 9 条回复 时间 点赞

这种方案是不是不能排除注释和空行这种非逻辑变更?

jacoco不就是现成的吗?

还有一个现实意义就是代码分支合并的时候QA做对应确认
确认没有把非本次版本的内容误合并进来导致漏测

AngryTester 回复

排除注释和空行的情况可目前是支持的,但需要根据实际应用场景来决定是否需要排除。如:基于codediff的代码覆盖率统计就是排除了注解、空行、import等无实际意义的变更。目前codediff已经支持相应能力的拓展。

hellomike 回复

jacoco是基于代码差异去统计覆盖率的测试方法,本文探讨的是代码差异的实现方案,这个实现方案可以适用于所有基于代码差异的测试方法,包括覆盖率。

6Floor has been deleted
纯稀饭 回复

说的很对,是codediff意义的一个补充,赞

有没有开源

OBJ 回复

暂时没咧,哈哈

准备开源不哦

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up