如何在自动化测试中实现精准截图?

字数 639阅读 973

今天分享的这个技能可以说是灰常有用,做自动化测试,无论是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);

原文来自下方公众号,转载请联系作者,并务必保留出处。
想第一时间看到更多原创技术好文和资料,请关注公众号:测试开发栈

推荐阅读更多精彩内容