2017-10-11 11 views
3

Selenium Grid를 사용하여 다른 PC에서 GWT 웹 응용 프로그램의 크로스 브라우저 테스트를 수행하고 있습니다. 내가 직면하고있는 문제는 생성 된 스크린 샷 (테스트 중에 찍은)의 크기가 PC마다 다르다는 것입니다. 따라서 코드를 일반적으로 스크린 샷의 기본 크기로 설정하려고합니다. 스크린 샷을 찍은 다음 생성 된 이미지를 내 PC에 로컬로 저장된 이미지와 비교하는 데 사용하는 코드입니다.Selenium Grid의 다른 PC에서 다른 크기의 스크린 샷

첫째로 나는 인수 (캔버스, 클래스 이름)와 CallScreenshotAndCompareImage 메소드를 호출합니다.

캔버스는 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...!!!"); 
      } 
     } 
} 

는 I베이스 (로컬) 화상과 실제 (생성) 화상 모두의 특성을 비교하면,이 코드를 실행 한 후, 그 다음 그 이미지의 양쪽 사이에 약간의 차이가 있었다.

자료 그리기 : 크기 -> 253킬로바이트, 비트 깊이 -> 32, 치수 -> 1570 X 873 개 픽셀

실제 도면 : 크기 -> 232킬로바이트, 비트 깊이 -> (24) , 크기 -> 1570 x 873 픽셀

이 두 가지 이미지의 속성은 모두 동일합니다.

다른 PC의 생성 된 스크린 샷이 항상 같은 크기가되도록 내 코드에 무엇을 추가해야합니까?

답변

0

하지만, 여기에 내가이 문제를 해결하기 위해 무슨 짓을했는지 :

다음은 예입니다.

  1. 이미지의 비트 심도가 24인지 32인지 확인합니다.
  2. 32이면 알파 채널을 모두 제거합니다.
  3. 다음으로 두 이미지의 픽셀의 RGB 값 차이가 10보다 작 으면 이미지를 동일하게 간주하는 범위를 설정합니다.
-1

실행 된 드라이버의 해상도를 설정하는 명령을 사용해야한다고 생각합니다. 은 그래서 당신의 teststeps 전에

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

자바

에 추가 할 수. 이제 스크린 샷의 해상도는 항상 동일합니다.

+0

그러나 내 이미지의 해상도는 동일하며 내 문제는 아닙니다. 주요 문제는 해상도가 아닌 이미지의 크기 (및 비트 심도)와 관련됩니다. 내 질문의 세부 사항 끝에있는 블록 인용문에서 지정한 내용을 읽으십시오. – DG4

+0

아,이 정보가 유용했을 것입니다. –

1

문제는 이미지의 크기가 아니라 기본 그림에있는 스크린 채널에없는 알파 채널 (투명도)입니다.

드라이버가 PNG Base64로 인코딩 된 문자열을 반환해야합니다. 그러나 24 비트 RGB 또는 32 비트 RGBA PNG 여야하는지 여부는 지정하지 않습니다. 버퍼를 비교하려면 먼저 각 버퍼를 원하는 색상 공간으로 변환해야합니다. @Florent B.의 대답은 나에게 솔루션을 접근하는 방향을 준 있지만

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