如何在自動(dòng)化測試中實(shí)現(xiàn)精準(zhǔn)截圖?

今天分享的這個(gè)技能可以說是灰常有用,做自動(dòng)化測試,無論是Web端的Selenium(Appium的使用基本類似Selenium)還是移動(dòng)端的UiAutomator2.0都有提供相應(yīng)的截屏API,直接調(diào)用對應(yīng)方法輕松截屏,可是問題來了,很多時(shí)候我并不想截取整個(gè)屏幕,除了整屏圖片太大外,還有有時(shí)候我還需要二次處理,比如常見的對指定位置進(jìn)行背景色提取、樣式、文字或數(shù)據(jù)驗(yàn)證等,這時(shí)候就需要我們精準(zhǔn)的截取需要的部分,從而排除無關(guān)的干擾區(qū)域。這要怎么做?下面就以Selenium和UiAutomator2.0的實(shí)現(xiàn)代碼來演示……

思路

大致思路是在截取整屏后,我們根據(jù)坐標(biāo)和截取區(qū)域大小,再次去截取對應(yīng)的小圖,因此要精準(zhǔn)截圖,這就要以我們能獲取到的控件元素或?qū)ο鬄榛A(chǔ),通過對應(yīng)的對象獲取該對象在屏幕中的的坐標(biāo),以及對象的區(qū)域(長、寬)等信息,有了這些信息就可以通過代碼輕松截取指定位置和區(qū)域的圖了。下面看具體實(shí)現(xiàn):

Selenium實(shí)現(xiàn)精準(zhǔn)截圖

你可以讓最終結(jié)果返回一個(gè)File對象,指向?qū)?yīng)的截圖后的文件對象,也可以直接返回截圖后的文件路徑(返回路徑:file.getAbsolutePath()),這個(gè)根據(jù)需要,自己去選擇。

private File snapshotAndSave(WebElement element, String filePath) {
    File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);//截圖整個(gè)頁面
    try {
        BufferedImage img = ImageIO.read(scrFile);
        // 獲得元素的高度和寬度
        int width = element.getSize().getWidth();
        int height = element.getSize().getHeight() ;
        // 創(chuàng)建一個(gè)矩形使用上面的高度,和寬度
        Rectangle rect = new Rectangle(width, height);
        // 得到元素的起始坐標(biāo)
        int x = element.getLocation().getX();
        int y = element.getLocation().getY();
        //開始按坐標(biāo)和區(qū)域截圖
        BufferedImage dest = img.getSubimage(x, y, rect.width, rect.height);
        //存為png格式
        ImageIO.write(dest, SNAPSHOT_IMG_SUFFIX, scrFile);
        File file = new File(filePath);
        FileUtils.copyFile(scrFile, file);
        return file;
    } catch (Exception e) {
        LOGGER.error("snapshotAndSave error:", e);
    }
    return null;
}

UiAutomator2.0實(shí)現(xiàn)精準(zhǔn)截圖

實(shí)現(xiàn)思路跟Selenium幾乎是一樣的,這里傳入了一個(gè)paths數(shù)組(當(dāng)然你也可以改一下分開傳2個(gè)參數(shù)),傳一個(gè)就代表截屏和后面的再次截圖是用的同一個(gè)路徑,傳2個(gè)就對應(yīng)分開了。返回對應(yīng)圖片文件對象還是路徑根據(jù)自己需要去調(diào)整了。(注:鑒于排版,有些I/O的規(guī)范就沒遵循了,用的時(shí)候自己去調(diào)整下流的關(guān)閉位置)

public static String takeElementshot(UiObject2 object, String...paths) {
    if (paths == null || paths.length < 1) {
        throw new IllegalArgumentException("paths參數(shù)不能為空");
    }
    if (object == null) {
        return null;
    }
    try {
        File file = new File(paths[0]);
        mDevice.takeScreenshot(file);

        BitmapFactory.Options bfOptions = new BitmapFactory.Options();
        bfOptions.inDither = false;
        bfOptions.inTempStorage = new byte[12 * 1024];
        bfOptions.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(paths[0]);
        Rect rect = object.getVisibleBounds();
        bitmap = bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height());//獲取區(qū)域

        String jpgCutPath = paths.length > 1 ? paths[1] : paths[0];
        File filePic = new File(jpgCutPath);
    
        if (!filePic.exists()) {
            filePic.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(jpgCutPath);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
        return filePic.getAbsolutePath();
    } catch (Exception e) {
        return null;
    }
}

怕有童鞋看不清楚,給個(gè)調(diào)用的例子演示一下:

String jpgPath = Config.LOG_PATH + "ocr.jpg";
String jpgCutPath = Config.LOG_PATH + "ocr_cut.jpg";
String path = takeElementshot(object, jpgPath, jpgCutPath);

原文來自下方公眾號,轉(zhuǎn)載請聯(lián)系作者,并務(wù)必保留出處。
想第一時(shí)間看到更多原創(chuàng)技術(shù)好文和資料,請關(guān)注公眾號:測試開發(fā)棧

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容