<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一款自動(dòng)生成單元測(cè)試的 IDEA 插件

          共 10666字,需瀏覽 22分鐘

           ·

          2022-05-16 09:06

          點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”


          回復(fù)”學(xué)習(xí)資料“獲取學(xué)習(xí)寶典

          ??
          ? 今天來介紹一款工具Squaretest,它是一款自動(dòng)生成單元測(cè)試的插件,為什么會(huì)用到它?

          主要因?yàn)樽罱旧狭舜a質(zhì)量管控的指標(biāo),會(huì)考評(píng)各個(gè)項(xiàng)目的單元測(cè)試覆蓋率,以及sonar掃描出來的各種問題,很多老項(xiàng)目老代碼,或者著急交付的項(xiàng)目,單元測(cè)試嚴(yán)重缺失,覆蓋率只有5%不到。

          所以幾個(gè)小伙伴這幾天就在瘋狂的堆單元測(cè)試,3個(gè)人堆了2天才堆到30%,于是我也來上手幫忙寫了兩個(gè),寫到第二個(gè)的時(shí)候就發(fā)現(xiàn),這個(gè)活不應(yīng)該是人干的,要去看原來的代碼,然后根據(jù)邏輯寫各種Mock,感覺是有跡可循的東西,所以就查了下,發(fā)現(xiàn)果然有插件幫我們來干這個(gè)事情,那么解下來就來看看。

          我使用的是idea,我們先來下載一下插件,File——>Settings——>Plugins,搜索Squaretest,然后install就好了,插件安裝完成后需要重啟一下

          重啟之后,菜單欄就多了一項(xiàng)Squaretest,下面我們來講下怎么用,大家也可以通過看這個(gè)菜單的最后一項(xiàng):Generate Test Methods(Help)來看它的一個(gè)演示,但演示不太全,我下面截圖給大家看下我怎么用的,以及一些使用心得。


          首先我們打開一個(gè)類,這個(gè)類就是我們即將要作為實(shí)驗(yàn)的類,這個(gè)類有7個(gè)public方法,因?yàn)?/span>Squaretest生成的單元測(cè)試方法都是只能生成public的,當(dāng)然這也是合理的嘛!畢竟private的肯定被public調(diào)用了。


          如果我們來手寫這個(gè)類的單元測(cè)試,光看都要一會(huì),下面看我操作,打開你的類,光標(biāo)定位到代碼里,右擊鼠標(biāo)選擇Generate…


          然后你就會(huì)看到這里有兩個(gè)熟悉的圖標(biāo),第一次的話選擇第二個(gè)選項(xiàng),它會(huì)讓你選擇你一下單元測(cè)試的模板,因?yàn)槲乙呀?jīng)選擇過了,所以我現(xiàn)在演示不回再?gòu)棾觯竺嫖視?huì)告訴你怎么更改模板。


          選擇第二項(xiàng)后就會(huì)彈出一個(gè)框看下面這里它自動(dòng)會(huì)識(shí)別出當(dāng)前類需要Mock的成員變量,直接點(diǎn)ok


          自動(dòng)會(huì)使用類的真實(shí)目錄層次在test文件夾中創(chuàng)建出來一個(gè)單元測(cè)試類,類名就是原類名后加Test


          我把代碼貼出來給大家看看它生成出來的是什么樣的,看看嚇不嚇人,牛逼牛逼,7個(gè)單元測(cè)試方法,秒秒鐘就出來了,各位看官你們自己寫要多久能寫出來,畢竟時(shí)間就是金錢啊!然后我們執(zhí)行一把試試!

          public?class?CrawlerScreenShotServiceImplTest?{

          ????@Mock
          ????private?CrawerScreenShotTaskMapper?mockCrawerScreenShotTaskMapper;
          ????@Mock
          ????private?CrawerScreenShotTaskLogMapper?mockCrawerScreenShotTaskLogMapper;

          ????@InjectMocks
          ????private?CrawlerScreenShotServiceImpl?crawlerScreenShotServiceImplUnderTest;

          ????@Before
          ????public?void?setUp()?{
          ????????initMocks(this);
          ????}

          ????@Test
          ????public?void?testReceiveData()?{
          ????????//?Setup
          ????????final?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?test
          ????????final?Result?result?=?crawlerScreenShotServiceImplUnderTest.receiveData(vo);

          ????????//?Verify?the?results
          ????}

          ????@Test
          ????public?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?crawlerScreenShotTaskDtos?=?Arrays.asList(crawlerScreenShotTaskDto);
          ????????when(mockCrawerScreenShotTaskMapper.listJobScreenShotTask(new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime())).thenReturn(crawlerScreenShotTaskDtos);

          ????????//?Run?the?test
          ????????final?List?result?=?crawlerScreenShotServiceImplUnderTest.listJobScreenShotTask();

          ????????//?Verify?the?results
          ????}

          ????@Test
          ????public?void?testQuery()?{
          ????????//?Setup
          ????????final?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?pimScreenShotVos?=?Arrays.asList(pimScreenShotVo);
          ????????when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);

          ????????//?Run?the?test
          ????????final?PageInfo?result?=?crawlerScreenShotServiceImplUnderTest.query(requestVo);

          ????????//?Verify?the?results
          ????}

          ????@Test
          ????public?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?pimScreenShotVos?=?Arrays.asList(pimScreenShotVo);
          ????????when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);

          ????????//?Run?the?test
          ????????final?PimScreenShotTaskParamsDto?result?=?crawlerScreenShotServiceImplUnderTest.querySelectBoxData();

          ????????//?Verify?the?results
          ????}

          ????@Test
          ????public?void?testFindExecutionScreenShotTaskCount()?{
          ????????//?Setup
          ????????when(mockCrawerScreenShotTaskMapper.findExecutionScreenShotTaskCount()).thenReturn(0);

          ????????//?Run?the?test
          ????????final?Integer?result?=?crawlerScreenShotServiceImplUnderTest.findExecutionScreenShotTaskCount();

          ????????//?Verify?the?results
          ????????assertEquals(0,?result);
          ????}

          ????@Test
          ????public?void?testFindCrawerScreenshotTaskByCreateTime()?{
          ????????//?Setup
          ????????final?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?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?crawlerScreenShotTaskSyncDtos?=?Arrays.asList(crawlerScreenShotTaskSyncDto1);
          ????????when(mockCrawerScreenShotTaskMapper.findCrawerScreenshotTaskByCreateTime(new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime())).thenReturn(crawlerScreenShotTaskSyncDtos);

          ????????//?Run?the?test
          ????????final?List?result?=?crawlerScreenShotServiceImplUnderTest.findCrawerScreenshotTaskByCreateTime(new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime());

          ????????//?Verify?the?results
          ????????assertEquals(expectedResult,?result);
          ????}

          ????@Test
          ????public?void?testQueryCrawlerDashboard()?{
          ????????//?Setup
          ????????when(mockCrawerScreenShotTaskMapper.queryCrawlerDashboard(0,?0,?0,?new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime(),?new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime())).thenReturn(0);

          ????????//?Run?the?test
          ????????final?Integer?result?=?crawlerScreenShotServiceImplUnderTest.queryCrawlerDashboard(0,?0,?0,?new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime(),?new?GregorianCalendar(2019,?Calendar.JANUARY,?1).getTime());

          ????????//?Verify?the?results
          ????????assertEquals(0,?result);
          ????}
          }

          報(bào)錯(cuò)了呢,不要慌,這個(gè)斷言是為了檢查你單元測(cè)試跑出來的結(jié)果是否符合預(yù)期的,如果你不想檢查只想完成覆蓋率,直接干掉就可以了(手動(dòng)狗頭)。

          怎么樣!刺不刺激,爽不爽,秒秒鐘90多行的代碼覆蓋率就到了90%以上.


          上面說過第一次進(jìn)來會(huì)讓你選擇單元測(cè)試的模板,如果你要切換的話可以在單元測(cè)試類中按快捷鍵,Alt+M,或者通過Squaretest的菜單倒數(shù)第二個(gè),下面這個(gè)就是按快捷鍵的效果,我選擇的是這個(gè)模板,你們也可以借鑒。


          OK,以上Squaretest部分就結(jié)束了,當(dāng)然拉也不能高興的太早,這個(gè)類算是比較成功的情況,很多時(shí)候還是要你自己小修小改的,畢竟它生成出來的測(cè)試數(shù)據(jù)可能完全匹配不上你的if else數(shù)據(jù)對(duì)吧,但這都很好改啊,這樣就從自己分析if else變成了,debug程序了呀,哪里報(bào)錯(cuò),debug過去,看看是不是生成的數(shù)據(jù)有問題,改個(gè)數(shù)據(jù),就通過了,反正本人用的是很舒暢的,妥妥的節(jié)省70%的工作量。

          解決了上面一個(gè)問題之后,又發(fā)現(xiàn)另一個(gè)問題,這個(gè)工具VO,DTO,Entity,Command,Model這種實(shí)體類來講,一般這種實(shí)體類我們都用lombok的注解get,set,還有constract構(gòu)造器等注解,但是這個(gè)工具只能生成這些實(shí)體類的構(gòu)造器的單元測(cè)試,無法生成get set方法的單元測(cè)試,所以寫了個(gè)base方法,實(shí)體類繼承一下,簡(jiǎn)單的寫兩行帶就好了,看下面代碼:

          @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));
          ????????}
          ????}

          ????@Test
          ????public?void?getAndSetTest()?throws?InvocationTargetException,?IntrospectionException,
          ????????????InstantiationException,?IllegalAccessException?
          {
          ????????this.testGetAndSet();
          ????}

          }

          同樣的方式我們?cè)趯?shí)體類上通過Squaretest生成單元測(cè)試,然后繼承我上面寫的那個(gè)base類,vo的單元測(cè)試代碼稍加改動(dòng),如下

          看run完之后,覆蓋率100%,妥妥的,通過這兩個(gè)解決方案,一天之內(nèi)我們就把覆蓋率搞到了60%以上,不要太刺激,大家可以用用試試哦,當(dāng)然這個(gè)也不是純?yōu)榱藨?yīng)付差事寫的單元測(cè)試,我們后續(xù)開發(fā)的時(shí)候,也可以用這個(gè)工具來生成,然后自測(cè)自己的代碼,這樣也是提升工作效率的嘛!


          來源:blog.csdn.net/sun5769675/article/details/111043213

          -------------? END??-------------
          掃描下方二維碼,加入技術(shù)群。暗號(hào):加群

          瀏覽 43
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一级电影中文 | 三级片www. | 在线观看中文字幕一区 | 无码乱伦中文字幕 | 操逼地址 |