今天分享的這個技能可以說是灰常有用,做自動化測試,無論是Web端的Selenium(Appium的使用基本類似Selenium)還是移動端的UiAutomator2.0都有提供相應(yīng)的截屏API踩娘,直接調(diào)用對應(yīng)方法輕松截屏,可是問題來了喉祭,很多時候我并不想截取整個屏幕养渴,除了整屏圖片太大外,還有有時候我還需要二次處理泛烙,比如常見的對指定位置進行背景色提取理卑、樣式、文字或數(shù)據(jù)驗證等蔽氨,這時候就需要我們精準的截取需要的部分藐唠,從而排除無關(guān)的干擾區(qū)域帆疟。這要怎么做?下面就以Selenium和UiAutomator2.0的實現(xiàn)代碼來演示……
思路
大致思路是在截取整屏后宇立,我們根據(jù)坐標和截取區(qū)域大小踪宠,再次去截取對應(yīng)的小圖,因此要精準截圖妈嘹,這就要以我們能獲取到的控件元素或?qū)ο鬄榛A(chǔ)柳琢,通過對應(yīng)的對象獲取該對象在屏幕中的的坐標,以及對象的區(qū)域(長润脸、寬)等信息柬脸,有了這些信息就可以通過代碼輕松截取指定位置和區(qū)域的圖了。下面看具體實現(xiàn):
Selenium實現(xiàn)精準截圖
你可以讓最終結(jié)果返回一個File對象毙驯,指向?qū)?yīng)的截圖后的文件對象倒堕,也可以直接返回截圖后的文件路徑(返回路徑:file.getAbsolutePath()),這個根據(jù)需要爆价,自己去選擇涩馆。
private File snapshotAndSave(WebElement element, String filePath) {
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);//截圖整個頁面
try {
BufferedImage img = ImageIO.read(scrFile);
// 獲得元素的高度和寬度
int width = element.getSize().getWidth();
int height = element.getSize().getHeight() ;
// 創(chuàng)建一個矩形使用上面的高度,和寬度
Rectangle rect = new Rectangle(width, height);
// 得到元素的起始坐標
int x = element.getLocation().getX();
int y = element.getLocation().getY();
//開始按坐標和區(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實現(xiàn)精準截圖
實現(xiàn)思路跟Selenium幾乎是一樣的允坚,這里傳入了一個paths數(shù)組(當然你也可以改一下分開傳2個參數(shù))魂那,傳一個就代表截屏和后面的再次截圖是用的同一個路徑,傳2個就對應(yīng)分開了稠项。返回對應(yīng)圖片文件對象還是路徑根據(jù)自己需要去調(diào)整了涯雅。(注:鑒于排版,有些I/O的規(guī)范就沒遵循了展运,用的時候自己去調(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;
}
}
怕有童鞋看不清楚活逆,給個調(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ù)必保留出處蔗候。
想第一時間看到更多原創(chuàng)技術(shù)好文和資料,請關(guān)注公眾號:測試開發(fā)棧