2017-10-11 19 views
3

Je suis en train d'effectuer le test croisé d'une application web GWT sur différents PC en utilisant Selenium Grid. Le problème auquel je suis confronté est que la taille des captures d'écran générées (prises au cours des tests) est différente pour les différents PC et je veux rendre mon code générique, c'est-à-dire soit définir une taille par défaut des captures d'écran. Voici mon code que j'utilise pour prendre la capture d'écran et ensuite comparer l'image générée avec l'image stockée localement sur mon PC.Captures d'écran ayant différentes tailles sur différents PC dans Selenium Grid

D'abord, j'appellerai la méthode CallScreenshotAndCompareImage avec les arguments (canvas, className).

Ici, canvas est le WebElement représentant le canevas HTML5 dans l'application GWT. FileBase est le fichier stocké localement dans mon projet et fileActual est l'image de capture générée.

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...!!!"); 
      } 
     } 
} 

Après l'exécution de ce code, lorsque je comparais les propriétés à la fois la base image (locale) et l'image réelle (générée), puis il y avait une petite différence entre ces deux images.

base Dessin: Taille -> 253 Ko, profondeur de bits -> 32, Dimensions -> 1570 x 873 pixels

dessin réel: Taille -> 232 Ko, profondeur de bits -> 24 , Dimensions -> 1570 x 873 pixels

Tout le reste était identique dans les propriétés de ces deux images.

Que dois-je ajouter dans mon code pour que les captures d'écran générées depuis différents PC soient toujours de la même taille?

Répondre

0

Bien que la réponse de @Florent B. m'a donné une direction pour approcher la solution, mais voici ce que je l'ai fait pour résoudre ce problème.

  1. Vérifie si la résolution de l'image est 24 ou 32.
  2. S'il est 32, alors il a supprimé tous les canaux alpha de celui-ci.
  3. Ensuite, je définis une plage qui, si la différence entre les valeurs RVB des pixels de deux images correspondantes était inférieure à 10, considère ces images comme identiques.
-1

Je pense que vous devez utiliser une commande pour définir la résolution du pilote exécuté. Pour cela, ajoutez en Java

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

avant votre TestSTEPS. Maintenant, la capture d'écran aura toujours la même résolution.

+0

Mais la résolution de mes images est la même et ce n'est pas mon problème. Le problème principal concerne les tailles (et la profondeur de bits) des images qui sont différentes et non la résolution. Veuillez lire ce que j'ai indiqué dans le bloc-citation à la fin des détails de ma question. – DG4

+0

Ah ok cette information aurait été utile. –

1

Le problème n'est pas la taille de l'image, mais le canal Alpha (transparence) qui est présent dans le dessin de base et qui manque dans la capture d'écran.

Le pilote est censé renvoyer une chaîne codée PNG Base64. Mais il n'est pas spécifié s'il doit s'agir d'un PNG RVB 24 bits ou 32 bits. Donc, pour pouvoir comparer les tampons, vous devez d'abord convertir chacun d'entre eux dans l'espace colorimétrique désiré.

Voici un exemple:

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

J'ai essayé votre méthode mais je dis toujours que les deux images sont différentes. J'ai vérifié cela en imprimant la valeur booléenne de la même variable. – DG4

+0

Si la méthode renvoie false, les images sont différentes avec au moins un pixel de couleur différente. C'est probablement invisible à l'œil nu, mais la différence est là. C'est probablement dû à un anti-aliasing différent. La comparaison de pixels stricte ne doit être utilisée que pour comparer des captures d'écran du même navigateur. Pour comparer les captures d'écran entre les navigateurs, vous devrez appliquer des filtres pour restreindre les fonctionnalités que vous essayez de valider. Jetez un oeil à la magie de l'image. –

+0

De quel type de filtres parlez-vous? Comme permettant au moins un ou deux pixels différents dans les images ou d'autres filtres? – DG4