移植MonkeyRunner的圖片對比功能實現-Appium篇
如果你的目標測試app有很多imageview組成的話,這個時候monkeyrunner的截圖比較功能就體現出來了。而其他幾個流行的框架如Robotium,UIAutomator以及Appium都提供了截圖,但少了兩個功能:
獲取子圖
圖片比較
既然Google開發的MonkeyRunner能盛行這么久,且它體功能的結果驗證功能只有截屏比較,那么必然有它的道理,有它存在的價值,所以我們很有必要在需要的情況下把它相應的功能給移植到其他框架上面上來。
經過本人前面文章描述的幾個框架的源碼的研究(robotium還沒有做),大家可以知道MonkeyRunner是跑在PC端的,只有在需要發送相應的命令事件時才會驅動目標機器的monkey或者shell等。比如獲取圖片是從目標機器的buffer設備得到,但是比較圖片和獲取子圖是從客戶PC端做的。
這里Appium工作的方式非常的類似,因為它也是在客戶端跑,但需要注入事件發送命令時還是通過目標機器段的bootstrap來驅動uiatuomator來完成的,所以要把MonkeyRunner的獲取子圖已經圖片比較的功能移植過來是非常容易的事情。
但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. 客戶端調用代碼舉例
packagesample.demo.AppiumDemo; importstaticorg.junit.Assert.*; importjava.awt.image.BufferedImage; importjava.io.File; importjava.io.IOException; importjava.net.URL; importjavax.imageio.ImageIO; importlibs.Util; importio.appium.java_client.android.AndroidDriver; importorg.apache.commons.io.FileUtils; importorg.junit.After; importorg.junit.Before; importorg.junit.Test; importorg.openqa.selenium.By; importorg.openqa.selenium.OutputType; importorg.openqa.selenium.WebElement; importorg.openqa.selenium.remote.DesiredCapabilities; publicclassCompareScreenShots{ privateAndroidDriverdriver; @Before publicvoidsetUp()throwsException{ DesiredCapabilitiescap=newDesiredCapabilities(); cap.setCapability("deviceName","Android"); cap.setCapability("appPackage","com.example.android.notepad"); cap.setCapability("appActivity",".NotesList"); driver=newAndroidDriver(newURL("http://127.0.0.1:4723/wd/hub"),cap); } @After publicvoidtearDown()throwsException{ driver.quit(); } @Test publicvoidcompareScreenAndSubScreen()throwsInterruptedException,IOException{ Thread.sleep(2000); WebElementel=driver.findElement(By.className("android.widget.ListView")).findElement(By.name("Note1")); el.click(); Thread.sleep(1000); Stringp1="C:/1"; Stringp2="C:/2"; Filef2=newFile(p2); Filef1=driver.getScreenshotAs(OutputType.FILE); FileUtils.copyFile(f1,newFile(p1)); BufferedImageimg1=Util.getImageFromFile(f1); f2=driver.getScreenshotAs(OutputType.FILE); FileUtils.copyFile(f2,newFile(p2)); BufferedImageimg2=Util.getImageFromFile(f2); Booleansame=Util.sameAs(img1,img2,0.9); assertTrue(same); BufferedImagesubImg1=Util.getSubImage(img1,6,39,474,38); BufferedImagesubImg2=Util.getSubImage(img1,6,39,474,38); same=Util.sameAs(subImg1,subImg2,1); Filef3=newFile("c:/sub-1.png"); ImageIO.write(subImg1,"PNG",f3); Filef4=newFile("c:/sub-2.png"); ImageIO.write(subImg1,"PNG",f4); } } |
也不多解析了,沒有什么特別的東西。
大家用得上的就支持下就好了...
posted on 2014-12-23 00:10 順其自然EVO 閱讀(1026) 評論(0) 編輯 收藏 所屬分類: 測試學習專欄