IDEA懒人必备插件:自动生成单元测试,太爽了!

5800448df2e2f2cb53228239b6d8e1da.jpeg

程序员的成长之路

互联网/程序员/技术/资料共享 

关注

阅读本文大概需要 7 分钟。

来自:blog.csdn.net/sun5769675/article/details/111043213

今天来介绍一款工具Squaretest,它是一款自动生成单元测试的插件,会用到它也是因为最近公司上了代码质量管控的指标,会考评各个项目的单元测试覆盖率,以及sonar扫描出来的各种问题。

很多老项目老代码,或者着急交付的项目,单元测试严重缺失,覆盖率只有5%不到,所以几个小伙伴这几天就在疯狂的堆单元测试,3个人堆了2天才堆到30%,于是我也来上手帮忙写了两个,写到第二个的时候就发现,这个活不应该是人干的,要去看原来的代码,然后根据逻辑写各种Mock,感觉是有迹可循的东西,所以就查了下,发现果然有插件帮我们来干这个事情,那么解下来就来看看。

我使用的是idea,我们先来下载一下插件,File——>Settings——>Plugins,搜索Squaretest,然后install就好了,插件安装完成后需要重启一下

6a900ccdb203034223aa75ec9c9af690.png

图片

重启之后,菜单栏就多了一项Squaretest,下面我们来讲下怎么用,大家也可以通过看这个菜单的最后一项:Generate Test Methods(Help)来看它的一个演示,但演示不太全,我下面截图给大家看下我怎么用的,以及一些使用心得。

a78c1209e09ca5b202281c1bf6ce48c1.png

图片

首先我们打开一个类,这个类就是我们即将要作为实验的类,这个类有7个public方法,因为Squaretest生成的单元测试方法都是只能生成public的,当然这也是合理的嘛!毕竟private的肯定被public调用了。

5bc25eca8177470d78c20e4cc25d435d.png

图片

如果我们来手写这个类的单元测试,光看都要一会,下面看我操作,打开你的类,光标定位到代码里,右击鼠标选择Generate…

3de501c5a146c875b76032ee257401ad.png

图片

然后你就会看到这里有两个熟悉的图标,第一次的话选择第二个选项,它会让你选择你一下单元测试的模板,因为我已经选择过了,所以我现在演示不回再弹出,但后面我会告诉你怎么更改模板。

a49181af597f836d869f05f9b51a5051.png

图片

选择第二项后就会弹出一个框看下面这里它自动会识别出当前类需要Mock的成员变量,直接点ok

68aed44ebe6a61335c367d2f634286fe.png

图片

自动会使用类的真实目录层次在test文件夹中创建出来一个单元测试类,类名就是原类名后加Test

a9131dfe14c25190f4815b6656a5473a.png

图片

我把代码贴出来给大家看看它生成出来的是什么样的,看看吓不吓人,牛逼牛逼,7个单元测试方法,秒秒钟就出来了,各位看官你们自己写要多久能写出来,毕竟时间就是金钱啊!然后我们执行一把试试!

public class CrawlerScreenShotServiceImplTest {@Mockprivate CrawerScreenShotTaskMapper mockCrawerScreenShotTaskMapper;@Mockprivate CrawerScreenShotTaskLogMapper mockCrawerScreenShotTaskLogMapper;@InjectMocksprivate CrawlerScreenShotServiceImpl crawlerScreenShotServiceImplUnderTest;@Beforepublic void setUp() {initMocks(this);}@Testpublic void testReceiveData() {// Setupfinal CrawlerScreenShotVO vo = new CrawlerScreenShotVO();vo.setUrl("url");vo.setPcFlag(false);vo.setMembergroup("membergroup");vo.setTaskType(0);vo.setUrlType(0);when(mockCrawerScreenShotTaskLogMapper.saveSelective(any(CrawerScreenShotTaskLog.class))).thenReturn(0);when(mockCrawerScreenShotTaskMapper.saveBatch(Arrays.asList(new CrawlerScreenShotTask(0L, "url", "imageOssUrl", false, false, "memberGroup", 0, 0, "fileName", new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), false, "skuCode", "state", "operater")))).thenReturn(0);// Run the testfinal Result<String> result = crawlerScreenShotServiceImplUnderTest.receiveData(vo);// Verify the results}@Testpublic void testListJobScreenShotTask() {// Setup// Configure CrawerScreenShotTaskMapper.listJobScreenShotTask(...).final CrawlerScreenShotTaskDto crawlerScreenShotTaskDto = new CrawlerScreenShotTaskDto();crawlerScreenShotTaskDto.setId(0L);crawlerScreenShotTaskDto.setUrl("url");crawlerScreenShotTaskDto.setSkuCode("skuCode");crawlerScreenShotTaskDto.setPcFlag(false);crawlerScreenShotTaskDto.setMemberGroup("memberGroup");crawlerScreenShotTaskDto.setUrlType(0);crawlerScreenShotTaskDto.setFileName("fileName");crawlerScreenShotTaskDto.setTaskType(0);crawlerScreenShotTaskDto.setState("state");final List<CrawlerScreenShotTaskDto> crawlerScreenShotTaskDtos = Arrays.asList(crawlerScreenShotTaskDto);when(mockCrawerScreenShotTaskMapper.listJobScreenShotTask(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(crawlerScreenShotTaskDtos);// Run the testfinal List<CrawlerScreenShotTaskDto> result = crawlerScreenShotServiceImplUnderTest.listJobScreenShotTask();// Verify the results}@Testpublic void testQuery() {// Setupfinal NikeScreenShotListRequestVo requestVo = new NikeScreenShotListRequestVo();requestVo.setUrl("url");requestVo.setUrlType(0);requestVo.setStartTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());requestVo.setEndTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());requestVo.setStatus(0);requestVo.setPcFlag(0);requestVo.setPageNum(0);requestVo.setPageSize(0);// Configure CrawerScreenShotTaskMapper.query(...).final PimScreenShotVo pimScreenShotVo = new PimScreenShotVo();pimScreenShotVo.setId(0L);pimScreenShotVo.setUrl("url");pimScreenShotVo.setImageOssUrl("imageOssUrl");pimScreenShotVo.setStatus(0);pimScreenShotVo.setPcFlag(false);pimScreenShotVo.setCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());pimScreenShotVo.setUrlType(0);pimScreenShotVo.setMsg("msg");final List<PimScreenShotVo> pimScreenShotVos = Arrays.asList(pimScreenShotVo);when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);// Run the testfinal PageInfo<PimScreenShotVo> result = crawlerScreenShotServiceImplUnderTest.query(requestVo);// Verify the results}@Testpublic void testQuerySelectBoxData() {// Setup// Configure CrawerScreenShotTaskMapper.query(...).final PimScreenShotVo pimScreenShotVo = new PimScreenShotVo();pimScreenShotVo.setId(0L);pimScreenShotVo.setUrl("url");pimScreenShotVo.setImageOssUrl("imageOssUrl");pimScreenShotVo.setStatus(0);pimScreenShotVo.setPcFlag(false);pimScreenShotVo.setCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());pimScreenShotVo.setUrlType(0);pimScreenShotVo.setMsg("msg");final List<PimScreenShotVo> pimScreenShotVos = Arrays.asList(pimScreenShotVo);when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);// Run the testfinal PimScreenShotTaskParamsDto result = crawlerScreenShotServiceImplUnderTest.querySelectBoxData();// Verify the results}@Testpublic void testFindExecutionScreenShotTaskCount() {// Setupwhen(mockCrawerScreenShotTaskMapper.findExecutionScreenShotTaskCount()).thenReturn(0);// Run the testfinal Integer result = crawlerScreenShotServiceImplUnderTest.findExecutionScreenShotTaskCount();// Verify the resultsassertEquals(0, result);}@Testpublic void testFindCrawerScreenshotTaskByCreateTime() {// Setupfinal CrawlerScreenShotTaskSyncDto crawlerScreenShotTaskSyncDto = new CrawlerScreenShotTaskSyncDto();crawlerScreenShotTaskSyncDto.setId(0L);crawlerScreenShotTaskSyncDto.setUrl("url");crawlerScreenShotTaskSyncDto.setSkuCode("skuCode");crawlerScreenShotTaskSyncDto.setTaskType(0);crawlerScreenShotTaskSyncDto.setStatus(0);crawlerScreenShotTaskSyncDto.setLastModifyTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());crawlerScreenShotTaskSyncDto.setOperater("operater");crawlerScreenShotTaskSyncDto.setMsg("msg");final List<CrawlerScreenShotTaskSyncDto> expectedResult = Arrays.asList(crawlerScreenShotTaskSyncDto);// Configure CrawerScreenShotTaskMapper.findCrawerScreenshotTaskByCreateTime(...).final CrawlerScreenShotTaskSyncDto crawlerScreenShotTaskSyncDto1 = new CrawlerScreenShotTaskSyncDto();crawlerScreenShotTaskSyncDto1.setId(0L);crawlerScreenShotTaskSyncDto1.setUrl("url");crawlerScreenShotTaskSyncDto1.setSkuCode("skuCode");crawlerScreenShotTaskSyncDto1.setTaskType(0);crawlerScreenShotTaskSyncDto1.setStatus(0);crawlerScreenShotTaskSyncDto1.setLastModifyTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());crawlerScreenShotTaskSyncDto1.setOperater("operater");crawlerScreenShotTaskSyncDto1.setMsg("msg");final List<CrawlerScreenShotTaskSyncDto> crawlerScreenShotTaskSyncDtos = Arrays.asList(crawlerScreenShotTaskSyncDto1);when(mockCrawerScreenShotTaskMapper.findCrawerScreenshotTaskByCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(crawlerScreenShotTaskSyncDtos);// Run the testfinal List<CrawlerScreenShotTaskSyncDto> result = crawlerScreenShotServiceImplUnderTest.findCrawerScreenshotTaskByCreateTime(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());// Verify the resultsassertEquals(expectedResult, result);}@Testpublic void testQueryCrawlerDashboard() {// Setupwhen(mockCrawerScreenShotTaskMapper.queryCrawlerDashboard(0, 0, 0, new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(0);// Run the testfinal Integer result = crawlerScreenShotServiceImplUnderTest.queryCrawlerDashboard(0, 0, 0, new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime(), new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime());// Verify the resultsassertEquals(0, result);}
}

报错了呢,不要慌,这个断言是为了检查你单元测试跑出来的结果是否符合预期的,如果你不想检查只想完成覆盖率,直接干掉就可以了(手动狗头)。

abca70c9f724e419aab9b5e472e57428.png

图片

怎么样!刺不刺激,爽不爽,秒秒钟90多行的代码覆盖率就到了90%以上。

0f8fc04d4748afec743f11cd438ecaeb.png

图片

上面说过第一次进来会让你选择单元测试的模板,如果你要切换的话可以在单元测试类中按快捷键,Alt+M,或者通过Squaretest的菜单倒数第二个,下面这个就是按快捷键的效果,我选择的是这个模板,你们也可以借鉴。

32a989cb53895a35795546a2ded4a801.png

图片

OK,以上Squaretest部分就结束了,当然拉也不能高兴的太早,这个类算是比较成功的情况,很多时候还是要你自己小修小改的,毕竟它生成出来的测试数据可能完全匹配不上你的if else数据对吧,但这都很好改啊,这样就从自己分析if else变成了,debug程序了呀,哪里报错,debug过去,看看是不是生成的数据有问题,改个数据,就通过了,反正本人用的是很舒畅的,妥妥的节省70%的工作量。

解决了上面一个问题之后,又发现另一个问题,这个工具VO,DTO,Entity,Command,Model这种实体类来讲,一般这种实体类我们都用lombok的注解get,set,还有constract构造器等注解,但是这个工具只能生成这些实体类的构造器的单元测试,无法生成get set方法的单元测试,所以写了个base方法,实体类继承一下,简单的写两行带就好了,看下面代码:

@SpringBootTest
@RunWith(MockitoJUnitRunner.class)
public abstract class BaseVoEntityTest<T> {protected abstract T getT();private void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException,InvocationTargetException {T t = getT();Class modelClass = t.getClass();Object obj = modelClass.newInstance();Field[] fields = modelClass.getDeclaredFields();for (Field f : fields) {boolean isStatic = Modifier.isStatic(f.getModifiers());// 过滤字段if (f.getName().equals("isSerialVersionUID") || f.getName().equals("serialVersionUID") || isStatic || f.getGenericType().toString().equals("boolean")|| f.isSynthetic()) {continue;}PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass);Method get = pd.getReadMethod();Method set = pd.getWriteMethod();set.invoke(obj, get.invoke(obj));}}@Testpublic void getAndSetTest() throws InvocationTargetException, IntrospectionException,InstantiationException, IllegalAccessException {this.testGetAndSet();}}

同样的方式我们在实体类上通过Squaretest生成单元测试,然后继承我上面写的那个base类,vo的单元测试代码稍加改动,如下

96383a25641c116ddc98154ed05972de.png

图片

看run完之后,覆盖率100%,妥妥的,通过这两个解决方案,一天之内我们就把覆盖率搞到了60%以上,不要太刺激,大家可以用用试试哦,当然这个也不是纯为了应付差事写的单元测试,我们后续开发的时候,也可以用这个工具来生成,然后自测自己的代码,这样也是提升工作效率的嘛!

753e7efecffdc31bd10770e407c1b704.png

图片

<END>

推荐阅读:

ChatGPT 能接入微信了!

什么是自旋锁?自旋的好处和后果是什么呢?

互联网初中高级大厂面试题(9个G)
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper......等技术栈!
⬇戳阅读原文领取!                                  朕已阅

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac Automator 图片自动压缩上传 COS

把个人博客放在了 netilfy 托管&#xff0c;它给了一个优化建议&#xff0c;可以压缩图片节省带宽。但是每次截图后都要再压缩下图片有点麻烦&#xff0c;于是想着应该可以偷偷懒。目标很明确&#xff0c;截图后图片传到我的 git 仓库 images 目录后&#xff0c;能给我自动压缩…

IDEA 28 个天花板技巧,YYDS!

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…

CSDN 去除图片水印

想要保存 CSDN 博客中的一张图片时&#xff0c;发现图片上有水印&#xff0c;想要删除&#xff0c;怎么办呢&#xff1f; 如下图 右击图片 --> [在新标签中打开图片] 把问号以及问号后面的内容全部删掉&#xff0c;再访问 呐&#xff0c;水印不见了。 PS&#xff1a;写博…

免费的图片去水印消除水印清除水印去水印方法去水印软件免费下载

是一款免费的图片去水印工具。适用于微博下载的&#xff08;偷的&#xff09;图&#xff0c;从别的地方下载的&#xff08;偷的&#xff09;图等。 ** 直接说下载链接&#xff1a;请点击链接里的普通下载&#xff0c;&#xff08;其他是别的下载器&#xff09; 当然&#xff…

批量图片去水印,操作简单,赶紧收藏!

图片怎么去水印?在平时的日常生活中&#xff0c;我们有时候需要用到一些图片或者视频&#xff0c;但是这些视频或者图片往往会有烦人的水印&#xff0c;我们需要去除水印后才能更好来使用~那么你都是怎么去除水印的呢?有什么比较简单轻松的批量图片去水印方法吗?小编这里有一…

2023新版 多功能去水印工具微信小程序源码_带流量主功能(已更新)

简介&#xff1a; 2023新版 多功能去水印工具微信小程序源码_带流量主功能 自带去水印接口的多功能小程序 支持各大平台短视频去水印 支持保存封面,图集,标题等等 支持本地图片去水印 支持图片拼接 支持九宫格切图 支持修改视频的MD5等等 另外当然也有流量主功能的 链…

去除CSDN博客图片水印

今天写论文时要用到之前写博客时的一张图片&#xff0c;但是直接复制过来有水印 &#xff0c;例如&#xff08;右下角&#xff09;&#xff1a; 后来找到了解决办法&#xff0c;故在这里分享一下&#xff1a; 1.右击博客中的图片&#xff0c;选择复制图片地址&#xff0c;如下&…

二十行代码去除图片水印(别再找工具修图啦)

别再找工具修图啦&#xff0c;用代码吧 图片上常常有多余信息&#xff0c;如水印等&#xff0c;常常困扰啦多少痴男怨女。 在简书上看到一段有意思的内容。于是将它搬啦过来。 原地址&#xff1a;https://www.meiwen.com.cn/subject/dofckqtx.html。 消除水印 原图和效果图…

怎么把照片里的水印去掉?这三个办法教给你

图片水印是指在图片上添加一些文字或图形&#xff0c;以标识该图片的来源或版权归属。它可以让人们更容易地辨认出图片的来源&#xff0c;从而增强品牌的辨识度。如果我们在网上看到很喜欢的照片&#xff0c;想要用来个人收藏或者当做背景图&#xff0c;而它的图片水印只是为了…

智能软件aaas系统的整体设计的内容构成和简单介绍---正文开篇 之 现实模型 -----计算机科学、认知科学及其他们的混血儿:计算机认知科学

在开始之前&#xff0c;首先需要说明一下&#xff1a;aaas的设计中大量借鉴了http://www.jfsowa.com/ 中的内容。只是为了软件智能的目的&#xff0c;整体结构、架构和工作机制不同。所借鉴的Jfsowa中的内容被拆散后分布于aaas系统的各个地方。这里一并说明&#xff0c;文档各处…

一、初识MVC的混血宠儿Struts2

Struts 2是一个MVC框架&#xff0c;吸收了Struts1和WebWork两者的精华&#xff0c;以WebWork设计思想为核心&#xff0c;吸收了Struts 1的部分优点&#xff0c;因此一举成为MVC框架领域的混血新宠儿。 一、这里提到了MVC&#xff0c;首先对MVC做一下介绍&#xff1a; 首先控制…

国内技术帝不输国外 CryEngine 3引擎下“混血编辑器”诠释究极画质

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴! 有一款游戏,它用真实且精美的画质征服了无数的玩家,在06年E3展上,它绽放了耀眼的光彩,…

混血手感的逆袭!B.FRIENDit GK6A类青轴机械式键盘!

这太像了啦......&#xff01;看来类青轴的机械式键盘应该也有可能也要掀起大战了&#xff0c;之前手感较好的多数都是POM导套设计系列&#xff0c;敲击起来就像是红轴手感&#xff0c;不过触底依然有一分或至少都有一丝弹弹的感觉。而类青轴最知名的应该就是雨林狼蛛&#xff…

DeepMind为明年的AAAI,准备了一份各种DQN的混血

本文来自AI新媒体量子位&#xff08;QbitAI&#xff09; DeepMind公开了一篇最近投递到AAAI 2018的新论文&#xff0c;这篇论文的主角&#xff0c;依然是这家公司四年前就开始研究的DQN&#xff0c;配角&#xff0c;依然是雅达利&#xff08;Atari&#xff09;游戏。 DQN&#…

【剑指offer】高频ML/DL面试题

学习心得 &#xff08;1&#xff09;机器学习、深度学习、强化学习blabla很多内容都是面试的重点&#xff0c;本文结合菜鸡自身学习过程持续更新。 &#xff08;2&#xff09;如有不正确之处&#xff0c;恳请指正&#xff0c;共同学习&#xff0c;非常谢谢~ &#xff08;3&…

国内技术帝不输国外 CryEngine 3引擎下 混血编辑器 诠释究极画质

有一款游戏&#xff0c;它用真实且精美的画质征服了无数的玩家&#xff0c;在06年E3展上&#xff0c;它绽放了耀眼的光彩&#xff0c;拿下了当年几乎所有画面上的奖项。大家应该已经猜到了&#xff0c;它就是《孤岛危机》。 在《孤岛危机》发售后几年里&#xff0c;制作商Cryte…

Java+PHP整合=混血新宠儿

在2009年互联网上大谈各种系统技术架构&#xff0c;我们看见了很多国内、国外大型网站采用了其他语言和Java(Jee)结合的方式进行工作&#xff0c;其中由我们熟悉的有 手机之家 和 Digg 都是采用PHP和Java混合的方式进行协同工作。 我见过最佳的实践方式也是很多人经常体验过的…

[漫画]120430 混血男孩

混血男孩 introduce:最近&#xff0c;有些事情一直困扰着我…… url:http://manhua.178.com/zajiaosn/ tag:伪娘,路西法,废萌,卖肉 preview: 转载于:https://www.cnblogs.com/jffifa/archive/2012/04/30/2476849.html

好家伙!上天入地混血儿料箱机器人

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。 知识星球-智能仓储物流技术研习社 下个物流技术大咖就是你|原创12万字书等你领 智能仓储物流技术研习社 围绕厂内物流Intralogisitics&#xff0c;分享仓储物流自动化技术、设备、系统等知识&#x…

chatgpt:栅格化原理和代码

栅格化原理 把某个点根据经纬度放在整数经纬度记录的格子里&#xff0c;并把格子编号与点对应起来。 第一步确定每个格子的长和宽&#xff0c;即经度变化量和纬度变换量&#xff1a; 假设测试点的经纬度是(114度, 22.5度) 划定栅格划分的经纬度范围&#xff08;大范围&…