<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    懶人必備:一款自動生成單元測試的 IDEA 插件

    VSole2023-05-15 09:20:12

    大家好,我是胖虎。

    今天來介紹一款工具Squaretest,它是一款自動生成單元測試的插件,為什么會用到它?

    主要因為最近公司上了代碼質量管控的指標,會考評各個項目的單元測試覆蓋率,以及sonar掃描出來的各種問題,很多老項目老代碼,或者著急交付的項目,單元測試嚴重缺失,覆蓋率只有5%不到。

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

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

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

    首先我們打開一個類,這個類就是我們即將要作為實驗的類,這個類有7個public方法,因為Squaretest生成的單元測試方法都是只能生成public的,當然這也是合理的嘛!畢竟private的肯定被public調用了。

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

    然后你就會看到這里有兩個熟悉的圖標,第一次的話選擇第二個選項,它會讓你選擇你一下單元測試的模板,因為我已經選擇過了,所以我現在演示不回再彈出,但后面我會告訴你怎么更改模板。

    選擇第二項后就會彈出一個框看下面這里它自動會識別出當前類需要Mock的成員變量,直接點ok

    自動會使用類的真實目錄層次在test文件夾中創建出來一個單元測試類,類名就是原類名后加Test

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

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

    報錯了呢,不要慌,這個斷言是為了檢查你單元測試跑出來的結果是否符合預期的,如果你不想檢查只想完成覆蓋率,直接干掉就可以了(手動狗頭)。

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

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

    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));
            }
        }
        @Test
        public void getAndSetTest() throws InvocationTargetException, IntrospectionException,
                InstantiationException, IllegalAccessException {
            this.testGetAndSet();
        }
    }
    

    同樣的方式我們在實體類上通過Squaretest生成單元測試,然后繼承我上面寫的那個base類,vo的單元測試代碼稍加改動,如下

    看run完之后,覆蓋率100%,妥妥的,通過這兩個解決方案,一天之內我們就把覆蓋率搞到了60%以上,不要太刺激,大家可以用用試試哦,當然這個也不是純為了應付差事寫的單元測試,我們后續開發的時候,也可以用這個工具來生成,然后自測自己的代碼,這樣也是提升工作效率的嘛!

    test單元測試
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    編寫測試代碼和編寫普通的Go代碼過程是類似的,并不需要學習新的語法、規則或工具。go test命令是一個按照一定約定和組織的測試代碼的驅動程序。
    主要因為最近公司上了代碼質量管控的指標,會考評各個項目的單元測試覆蓋率,以及sonar掃描出來的各種問題,很多老項目老代碼,或者著急交付的項目,單元測試嚴重缺失,覆蓋率只有5%不到。首先我們打開一個類,這個類就是我們即將要作為實驗的類,這個類有7個public方法,因為Squaretest生成的單元測試方法都是只能生成public的,當然這也是合理的嘛!畢竟private的肯定被public調用了。
    前言 OpenAI的ChatGPT智能AI引擎,在全世界范圍流行,各種ChatGPT應用場景也遍地開花。簡單測試一下,ChatGPT在軟件開發方面的功能是否好用,就用一個自動生成單元測試代碼作為例子。文章最后,提供一些好用的ChatGPT插件,覆蓋了日常最常用的ChatGPT的使用場景。0x02 ChatGPT自動生成代碼單元測試用例 源代碼,先寫一個簡單的Lua函數代碼,太復雜的理解的也慢,如下:function ChatGPTlocal ret = num1 + num2return retendChatGPT(5,7)
    推薦 goleak 的背景goroutine 作為 golang 并發實現的核心組成部分,非常容易上手使用,但卻很難駕馭得好。我們經常會遭遇各種形式的 goroutine 泄漏,這些泄漏的 goroutine 會一直存活直到進程終結。等性能分析工具更多是作用于監控報警/故障之后的復盤。我們需要一款能在編譯部署前識別 goroutine 泄漏的工具,從更上游把控工程質量。
    模糊測試是一種向程序提供隨機意外的輸入以測試可能的崩潰或者邊緣情況的方法。通過模糊測試可以揭示一些邏輯錯誤或者性能問題,因此使用模糊測試可以讓程序的穩定性和性能都更有保證。Go 從1.18 版本開始正式把模糊測試加入到了其工具集中,不再依靠三方庫就能在程序代碼中進行模糊測試。為什么引入模糊測試大家看文章開頭第一段的解釋,那就是Go官方要引入模糊測試的原因。
    這樣一旦運行的服務器宕機,就把備份的服務器運行起來。冷備的方案比較容易實現,但冷備的缺點是主機出現故障時備機不會自動接管,需要主動切換服務。當一臺服務器宕機后,自動切換到另一臺備用機使用。
    日常滲透測試中,在進行數據包的重放或者是篡改數據包時,會碰到一些存在數據加密或加簽的站點,這時我們就得尋找加簽或者加密的算法,而這尋找過程往往有一定難度。 總的來講,對于數據解密或者加簽破解的難度:app>web≥wxapp,同時api接口都是相同的,為降低不必要的挖洞難度,可將目光放到微信小程序上。本次就是以一個微信小程序站點開展的測試。
    異步調用幾乎是處理高并發Web應用性能問題的萬金油,那么什么是“異步調用”? “異步調用”對應的是“同步調用”,同步調用指程序按照定義順序依次執行,每一行程序都必須等待上一行程序執行完成之后才能執行;異步調用指程序在順序執行時,不等待異步調用的語句返回結果就執行后面的程序。
    AV-TEST 和 AV-Comparatives 是兩家知名的反惡意軟件評估公司。盡管久負盛名,但是前者遇到了一件尷尬的事情:官方 Twitter 賬號于 7 月 25 日被黑了,但時間過去 1 周仍未恢復對其的控制。
    前不久,國際權威測評機構AV-TEST發布了最新的企業安全產品測評結果,在測評的19個企業級終端安全產品中,深信服EDR在檢測能力、性能消耗以及可用性三個評估維度拿到了全部滿分(6分為滿分)的好成績,也是國內首個全部滿分的終端安全產品,意味著深信服EDR在終端安全防護能力上獲得了的專業肯定與認可。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类