假设你的目标測试app有非常多imageview组成的话,这个时候monkeyrunner的截图比較功能就体现出来了。
而其它几个流行的框架如Robotium,UIAutomator以及Appium都提供了截图,但少了两个功能:
- 获取子图
- 图片比較
既然Google开发的MonkeyRunner能盛行这么久,且它体功能的结果验证功能仅仅有截屏比較,那么必定有它的道理。有它存在的价值,所以我们非常有必要在须要的情况下把它对应的功能给移植到其它框架上面上来。
经过本人前面文章描写叙述的几个框架的源代码的研究(robotium还没有做),大家能够知道MonkeyRunner是跑在PC端的,仅仅有在须要发送对应的命令事件时才会驱动目标机器的monkey或者shell等。
比方获取图片是从目标机器的buffer设备得到。可是比較图片和获取子图是从客户PC端做的。
这里Appium工作的方式很的类似,由于它也是在client跑。但须要注入事件发送命令时还是通过目标机器段的bootstrap来驱动uiatuomator来完毕的,所以要把MonkeyRunner的获取子图已经图片比較的功能移植过来是很easy的事情。
但UiAutomator就是另外一回事了。由于它全然是在目标机器那边跑的。所以你的代码必需要android那边支持,所以本人在移植到UiAutomator上面就碰到了问题。这里先给出Appium 上面的移植。以方便大家的使用,至于UiAutomator和Robotium的,今后本人会酌情考虑是否提供给大家。
还有就是这个移植过来的代码没有经过优化的,比方失败是否保存图片以待今后查看等。大家能够基于这个基础实现满足自己要求的功能
1. 移植代码
移植代码放在一个Util.java了工具类中:
public static boolean sameAs(BufferedImage myImage,BufferedImage otherImage, double percent)
{
//BufferedImage otherImage = other.getBufferedImage();
//BufferedImage myImage = getBufferedImage();
if (otherImage.getWidth() != myImage.getWidth()) {
return false;
}
if (otherImage.getHeight() != myImage.getHeight()) {
return false;
}
int[] otherPixel = new int[1];
int[] myPixel = new int[1];
int width = myImage.getWidth();
int height = myImage.getHeight();
int numDiffPixels = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (myImage.getRGB(x, y) != otherImage.getRGB(x, y)) {
numDiffPixels++;
}
}
}
double numberPixels = height * width;
double diffPercent = numDiffPixels / numberPixels;
return percent <= 1.0D - diffPercent;
}
public static BufferedImage getSubImage(BufferedImage image,int x, int y, int w, int h)
{
return image.getSubimage(x, y, w, h);
}
public static BufferedImage getImageFromFile(File f) {
BufferedImage img = null;
try {
img = ImageIO.read(f);
} catch (IOException e) {
//if failed, then copy it to local path for later check:TBD
//FileUtils.copyFile(f, new File(p1));
e.printStackTrace();
System.exit(1);
}
return img;
}
这里就不多描写叙述了。基本上就是基于MonkeyRunner做轻微的修改,所以叫做移植。而UiAutomator就可能须要大修改,要重现实现了。
2. client调用代码举例
package sample.demo.AppiumDemo;
import static org.junit.Assert.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import libs.Util;
import io.appium.java_client.android.AndroidDriver;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
public class CompareScreenShots {
private AndroidDriver driver;
@Before
public void setUp() throws Exception {
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability("deviceName", "Android");
cap.setCapability("appPackage", "com.example.android.notepad");
cap.setCapability("appActivity", ".NotesList");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),cap);
}
@After
public void tearDown() throws Exception {
driver.quit();
}
@Test
public void compareScreenAndSubScreen() throws InterruptedException, IOException{
Thread.sleep(2000);
WebElement el = driver.findElement(By.className("android.widget.ListView")).findElement(By.name("Note1"));
el.click();
Thread.sleep(1000);
String p1 = "C:/1";
String p2 = "C:/2";
File f2 = new File(p2);
File f1 = driver.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(f1, new File(p1));
BufferedImage img1 = Util.getImageFromFile(f1);
f2 = driver.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(f2, new File(p2));
BufferedImage img2 = Util.getImageFromFile(f2);
Boolean same = Util.sameAs(img1, img2, 0.9);
assertTrue(same);
BufferedImage subImg1 = Util.getSubImage(img1, 6, 39, 474, 38);
BufferedImage subImg2 = Util.getSubImage(img1, 6, 39, 474, 38);
same = Util.sameAs(subImg1, subImg2, 1);
File f3 = new File("c:/sub-1.png");
ImageIO.write(subImg1, "PNG", f3);
File f4 = new File("c:/sub-2.png");
ImageIO.write(subImg1, "PNG", f4);
}
}
也不多解析了。没有什么特别的东西。
大家用得上的就支持下就好了...
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | | 服务号:TechGoGoGo 扫描码: | http://blog.csdn.net/zhubaitian |