<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 插件,開(kāi)發(fā)效率提升 70% 以上!

          共 19137字,需瀏覽 39分鐘

           ·

          2022-06-20 23:33

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

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

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

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

          我使用的是idea,我們先來(lái)下載一下插件,File——>Settings——>Plugins,搜索Squaretest,然后install就好了,插件安裝完成后需要重啟一下。另外,更多 IDEA 好用的插件全部整理好了,微信搜索Java技術(shù)棧,在后臺(tái)發(fā)送:工具,可以在線閱讀。

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

          首先我們打開(kāi)一個(gè)類(lèi),這個(gè)類(lèi)就是我們即將要作為實(shí)驗(yàn)的類(lèi),這個(gè)類(lèi)有7個(gè)public方法,因?yàn)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);">Squaretest生成的單元測(cè)試方法都是只能生成public的,當(dāng)然這也是合理的嘛!畢竟private的肯定被public調(diào)用了。

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

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

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

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

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

          最新面試題整理好了,大家可以在Java面試庫(kù)小程序在線刷題。

          我把代碼貼出來(lái)給大家看看它生成出來(lái)的是什么樣的,看看嚇不嚇人,牛逼牛逼,7個(gè)單元測(cè)試方法,秒秒鐘就出來(lái)了,各位看官你們自己寫(xiě)要多久能寫(xiě)出來(lái),畢竟時(shí)間就是金錢(qián)啊!然后我們執(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"falsefalse"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<String> 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<CrawlerScreenShotTaskDto> crawlerScreenShotTaskDtos = Arrays.asList(crawlerScreenShotTaskDto);
                  when(mockCrawerScreenShotTaskMapper.listJobScreenShotTask(new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime())).thenReturn(crawlerScreenShotTaskDtos);

                  // Run the test
                  final List<CrawlerScreenShotTaskDto> 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<PimScreenShotVo> pimScreenShotVos = Arrays.asList(pimScreenShotVo);
                  when(mockCrawerScreenShotTaskMapper.query(any(NikeScreenShotListRequestVo.class))).thenReturn(pimScreenShotVos);

                  // Run the test
                  final PageInfo<PimScreenShotVo> 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<PimScreenShotVo> 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<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 test
                  final List<CrawlerScreenShotTaskSyncDto> 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è)試跑出來(lái)的結(jié)果是否符合預(yù)期的,如果你不想檢查只想完成覆蓋率,直接干掉就可以了(手動(dòng)狗頭)。

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

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

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

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

          @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());
                      // 過(guò)濾字段
                      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í)體類(lèi)上通過(guò)Squaretest生成單元測(cè)試,然后繼承我上面寫(xiě)的那個(gè)base類(lèi),vo的單元測(cè)試代碼稍加改動(dòng),如下

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

          另外,更多 IDEA 好用的插件全部整理好了,微信搜索Java技術(shù)棧,在后臺(tái)發(fā)送:工具,可以在線閱讀。覺(jué)得不錯(cuò)就用起來(lái)吧!

          版權(quán)聲明:本文為CSDN博主「孫琛斌(浮生)」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/sun5769675/article/details/111043213








          Spring Boot 定時(shí)任務(wù)開(kāi)啟后,怎么自動(dòng)停止?
          工作 3 年的同事不知道如何回滾代碼
          23 種設(shè)計(jì)模式實(shí)戰(zhàn)(很全)
          Spring Boot 保護(hù)敏感配置的 4 種方法!
          面了個(gè) 5 年 Java,兩個(gè)線程數(shù)據(jù)交換都不會(huì)
          阿里為什么推薦使用 LongAdder?
          新來(lái)一個(gè)技術(shù)總監(jiān):禁止戴耳機(jī)寫(xiě)代碼。。
          重磅!Spring Boot 2.7 正式發(fā)布
          Java 18 正式發(fā)布,finalize 被棄用。
          Spring Boot Admin 橫空出世!
          Spring Boot 學(xué)習(xí)筆記,這個(gè)太全了!



          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 84
          點(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.操逼.com | 亚洲人成在线播放 | 无码内射视频 |