2017-10-11 76 views
3

我正在使用Selenium Grid在不同PC上執行GWT Web應用程序的跨瀏覽器測試。我面臨的問題是生成的屏幕截圖的大小(在測試過程中獲得的)對於不同的PC是不同的,我想讓我的代碼具有通用性,即設置屏幕截圖的默認大小。這裏是我用來截取屏幕截圖的代碼,然後將生成的圖像與本地PC上存儲的圖像進行比較。在Selenium Grid的不同PC上擁有不同尺寸的屏幕截圖

首先我會調用CallScreenshotAndCompareImage方法和 參數(canvas,className)。

這裏的畫布是代表GWT應用程序中的HTML5畫布的WebElement 。

FileBase是本地存儲在我的項目中的文件,fileActual是生成的截圖。

public class Browser { 
    //ThreadLocal will provide thread-safe tests 
     protected ThreadLocal<RemoteWebDriver> threadLocal = null; 
     String serverMachine = "xxx.xxx.xxx.xxx:xxx/hub"; //IP Address of hub 
     @BeforeTest 
     @Parameters("browser") 
     public void setup(String browser) throws MalformedURLException{ 

      if(browser.equalsIgnoreCase("chrome")) { 

       System.setProperty("webdriver.chrome.driver", ".src/Drivers/chromedriver.exe"); 
       DesiredCapabilities capability = null; 
       capability = DesiredCapabilities.chrome(); 
       capability.setPlatform(Platform.WINDOWS); 
       capability.setBrowserName("chrome"); 
       createRemoteWebDriver(capability); 
      } 
      else if(browser.equalsIgnoreCase("firefox")) { 

       System.setProperty("webdriver.gecko.driver", ".src/Drivers/geckodriver.exe"); 
       DesiredCapabilities capability = null; 
       capability = DesiredCapabilities.firefox(); 
       capability.setPlatform(Platform.WINDOWS); 
       capability.setBrowserName("firefox"); 
       createRemoteWebDriver(capability); 
      } 

     } 
     public void createRemoteWebDriver(DesiredCapabilities capability) throws MalformedURLException { 
      threadLocal = new ThreadLocal<RemoteWebDriver>(); 
      threadLocal.set(new RemoteWebDriver(new URL(serverMachine), capability)); 
     } 

     public WebDriver getDriver() { 
      return threadLocal.get(); 
     } 

public void CallScreenshotAndCompareImage(WebElement element, String className) throws IOException, InterruptedException { 
      File fileBase1 = new File("./src/Images/baseDrawing"+className+"Chrome.png"); 
      File fileBase2 = new File("./src/Images/baseDrawing"+className+"Firefox.png"); 
      Capabilities cap = ((RemoteWebDriver) getDriver()).getCapabilities(); 
      String browserName = cap.getBrowserName().toLowerCase(); 
      File fileActual = new File("./src/Images/actualDrawing"+className+browserName+".png"); 
      File elementImage = this.takeElementScreenshot(element,"png"); 
      FileUtils.copyFile(elementImage, fileActual); 
      if(browserName.equalsIgnoreCase("chrome")) 
       this.compareImage(fileBase1,fileActual); 
      else if(browserName.equalsIgnoreCase("firefox")) 
       this.compareImage(fileBase2,fileActual); 
      Thread.sleep(3000); 
     } 

public File takeElementScreenshot(WebElement element, String imageFormat) throws IOException{ 

      Point elementXY = element.getLocation(); 
      int elementHeight = element.getSize().getHeight(); 
      int elementWidth = element.getSize().getWidth(); 
      Rectangle elementRectArea = new Rectangle(elementWidth,elementHeight); 
      WrapsDriver wrapsDriver = (WrapsDriver) element; 
      File pageImage = ((TakesScreenshot)wrapsDriver.getWrappedDriver()).getScreenshotAs(OutputType.FILE); 
      BufferedImage bufferedImage = ImageIO.read(pageImage); 
      BufferedImage elementImage = bufferedImage.getSubimage(elementXY.getX(), elementXY.getY(), elementRectArea.width, elementRectArea.height); 
      ImageIO.write(elementImage, imageFormat, pageImage); 
      return pageImage; 
     } 

     public void compareImage(File fileBase, File fileActual) { 
      /* 
     STEPS: 
     1) For first image file, recognize the contents of the file and decodes it into a BufferedImage which can be directly used by Java 2D. 
     2) Get the raster from the bufferedImage object which is a copy of image data. 
     3) Get the DataBuffer associated with the raster. 
     4) Get the size of the all the banks(data arrays) for the DataBuffer object. 
     5) Repeat steps 1-4 for the second image file. 
     6) If sizes of both of the images are different, then images won't be same. 
     7) If sizes are same, then compare all the data array elements for both of the DataBuffer objects. If they are same. then both images will be same. 
      */ 

      try { 

       BufferedImage bufferedImage = ImageIO.read(fileBase); 
       DataBuffer dataBufferFirst = bufferedImage.getData().getDataBuffer(); 
       int sizeFirst = dataBufferFirst.getSize();    
       BufferedImage bufferedImage2 = ImageIO.read(fileActual); 
       DataBuffer dataBufferSecond = bufferedImage2.getData().getDataBuffer(); 
       int sizeSecond = dataBufferSecond.getSize(); 
       int count=0; 
       Assert.assertEquals(sizeFirst, sizeSecond,"Size of Base Drawing and actual Drawing is not same"); 
       if(sizeFirst == sizeSecond) 
       { 
        for(int i=0; i<sizeFirst; i++) 
        { 
         if(dataBufferFirst.getElem(i) != dataBufferSecond.getElem(i)) //getElem() returns the data array element at the specified index. 
         { 
          count++; 
         } 

        } 
        Assert.assertEquals(count, 0,"Both images are not same"); 
       } 
      } catch (Exception e) { 
       Assert.fail("Failed to compare image files...!!!"); 
      } 
     } 
} 

運行此代碼,當我比較兩個基座(本地)圖像和實際的(生成的)圖像的屬性後,再有就是這兩個圖像之間的差別不大。

基本繪圖:尺寸 - > 253 KB,位深度 - > 32,尺寸 - > 1570 X 873個像素

實際繪製:尺寸 - > 232 KB,位深度 - > 24 ,尺寸 - > 1570 x 873像素

其他所有內容在這兩個圖像的屬性中都是相同的。

我應該在我的代碼中添加什麼,以便來自不同PC的生成的屏幕截圖始終具有相同的大小?

回答

0

雖然@Florent B.的回答給了我一個方向,以找出解決方案,但在這裏我就是這樣做來解決這個問題。

  1. 檢查圖像的位深度是24還是32。
  2. 如果它是32,然後從它刪除所有的alpha通道。
  3. 接下來,我設置了一個範圍,如果兩個相應圖像的像素的RGB值之間的差值小於10,則將這些圖像視爲相同。
-1

我想你必須使用一個命令來設置執行的驅動程序的分辨率。 這樣做加入Java

driver.manage().window().setSize(new Dimension (1280, 1024)); 

在你的測試步驟之前。 現在截圖將始終具有相同的分辨率。

+0

但是我的圖像的分辨率是一樣的,這不是我的問題。主要問題與圖像大小(和位深度)有關,而不是分辨率。請仔細閱讀我在問題詳細信息結尾處的塊引用中指定的內容。 – DG4

+0

好的這個信息本來是有用的。 –

1

問題不是圖像的大小,而是Alpha通道(透明度),它存在於基礎繪圖中,並且在屏幕截圖中缺失。

該驅動程序應該返回一個PNG Base64編碼的字符串。但沒有說明它應該是24位RGB還是32位RGBA PNG。 因此,爲了能夠比較緩衝區,您首先必須將它們中的每一個轉換爲所需的顏色空間。

下面是一個例子:

public static void main(String[] args) throws Exception { 
    BufferedImage imageA = ImageIO.read(new File("C:\\temp\\img_24bits.png")); 
    BufferedImage imageB = ImageIO.read(new File("C:\\temp\\img_32bits.png")); 
    boolean same = isSameImage(imageA, imageB); 
} 

public static boolean isSameImage(BufferedImage imageA, BufferedImage imageB) throws IOException { 
    DataBufferInt bufferA = getImageBuffer(imageA); 
    DataBufferInt bufferB = getImageBuffer(imageB); 

    if (bufferA.getSize() != bufferB.getSize() || bufferA.getNumBanks() != bufferB.getNumBanks()) 
     return false; 

    for (int i = 0; i < bufferA.getNumBanks(); ++i) { 
     if (!Arrays.equals(bufferA.getData(i), bufferB.getData(i))) 
      return false; 
    } 

    return true; 
} 

private static DataBufferInt getImageBuffer(BufferedImage img) throws IOException { 
    BufferedImage bi = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); 
    ColorConvertOp cco = new ColorConvertOp(bi.getColorModel().getColorSpace(), img.getColorModel().getColorSpace(), null); 
    cco.filter(img, bi); 
    return (DataBufferInt)bi.getRaster().getDataBuffer(); 
} 
+0

我試過你的方法,但仍然說這兩個圖像是不同的。我通過打印相同變量的布爾值來檢查。 – DG4

+0

如果該方法返回false,則圖像與至少一個具有不同顏色的像素不同。這可能是肉眼看不到的,但不同之處在於。這可能是由於不同的抗鋸齒。嚴格的像素比較只能用於比較來自同一瀏覽器的屏幕截圖。要比較瀏覽器之間的屏幕截圖,您必須應用一些過濾器來縮小要驗證的功能。看看圖像魔術。 –

+0

你在說什麼樣的過濾器?就像允許圖像中的至少一個或兩個不同的像素或其他一些濾鏡一樣? – DG4