今天分享的这个技能可以说是灰常有用,做自动化测试,无论是Web端的Selenium(Appium的使用基本类似Selenium)还是移动端的UiAutomator2.0都有提供相应的截屏API,直接调用对应方法轻松截屏,可是问题来了,很多时候我并不想截取整个屏幕,除了整屏图片太大外,还有有时候我还需要二次处理,比如常见的对指定位置进行背景色提取、样式、文字或数据验证等,这时候就需要我们精准的截取需要的部分,从而排除无关的干扰区域。这要怎么做?下面就以Selenium和UiAutomator2.0的实现代码来演示……
思路
大致思路是在截取整屏后,我们根据坐标和截取区域大小,再次去截取对应的小图,因此要精准截图,这就要以我们能获取到的控件元素或对象为基础,通过对应的对象获取该对象在屏幕中的的坐标,以及对象的区域(长、宽)等信息,有了这些信息就可以通过代码轻松截取指定位置和区域的图了。下面看具体实现:
Selenium实现精准截图
你可以让最终结果返回一个File对象,指向对应的截图后的文件对象,也可以直接返回截图后的文件路径(返回路径:file.getAbsolutePath()),这个根据需要,自己去选择。
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() ;
// 创建一个矩形使用上面的高度,和宽度
Rectangle rect = new Rectangle(width, height);
// 得到元素的起始坐标
int x = element.getLocation().getX();
int y = element.getLocation().getY();
//开始按坐标和区域截图
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实现精准截图
实现思路跟Selenium几乎是一样的,这里传入了一个paths数组(当然你也可以改一下分开传2个参数),传一个就代表截屏和后面的再次截图是用的同一个路径,传2个就对应分开了。返回对应图片文件对象还是路径根据自己需要去调整了。(注:鉴于排版,有些I/O的规范就没遵循了,用的时候自己去调整下流的关闭位置)
public static String takeElementshot(UiObject2 object, String...paths) {
if (paths == null || paths.length < 1) {
throw new IllegalArgumentException("paths参数不能为空");
}
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());//获取区域
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;
}
}
怕有童鞋看不清楚,给个调用的例子演示一下:
String jpgPath = Config.LOG_PATH + "ocr.jpg";
String jpgCutPath = Config.LOG_PATH + "ocr_cut.jpg";
String path = takeElementshot(object, jpgPath, jpgCutPath);
原文来自下方公众号,转载请联系作者,并务必保留出处。
想第一时间看到更多原创技术好文和资料,请关注公众号:测试开发栈