web-dev-qa-db-fra.com

Captures d'écran du site Web complet Selenium WebDriver C # avec ChromeDriver et FirefoxDriver

Lorsque je prends des captures d'écran avec ChromeDriver, j'obtiens des écrans de la taille de ma fenêtre.
Lorsque je prends des captures d'écran avec FirefoxDriver, j'obtiens ce que je veux, c'est-à-dire une impression en plein écran d'un site Web.

ChromeDriver est déclaré comme ceci:

IWebDriver driver = new ChromeDriver();

FirefoxDriver est déclaré comme ceci:

IWebDriver driver = new FirefoxDriver();

Les deux pilotes exécutent un code identique:

driver.Manage().Window.Maximize();
driver.Navigate().GoToUrl(url);//url is a string variable
ITakesScreenshot screenshotDriver = driver as ITakesScreenshot;
Screenshot screenshot = screenshotDriver.GetScreenshot();
screenshot.SaveAsFile("c:/test.png", ImageFormat.Png);

Le test.png de ChromeDriver a une résolution de 1920x1099 et ne contient que la fenêtre du navigateur.
Le test.png de FirefoxDriver a une résolution de 1903x16559 et contient la page entière.

Je sais que la méthode GetScreenshot() ne renvoie pas des tailles de résolution identiques car elle a des implémentations légèrement différentes dans IEDriver, FirefoxDriver, OperaDriver, ChromeDriver.

Mes questions sont:

  1. Pourquoi y a-t-il une telle différence entre la méthode .GetScreenshot() de ChromeDriver et celle de FirefoxDriver, même si elles utilisent une interface identique (ITakesScreenshot)?

  2. Existe-t-il un moyen de faire en sorte que la méthode GetScreenshot() de ChromeDriver renvoie la totalité de l'écran de la page Web au lieu de la fenêtre d'affichage?

17
user2429052

nous ne pouvons pas obtenir la capture d'écran de la page entière avec ChromeDriver2, nous devons opter pour une implémentation manuelle.J'ai modifié une méthode avec est disponible dans un blog qui fonctionne bien avec ChromeDriver.

utilisez cette méthode comme suit:

private IWebDriver _driver = new ChromeDriver(CHROME_DRIVER_PATH);
screenshot.SaveAsFile(saveFileName, ImageFormat.Jpeg);

public Bitmap GetEntereScreenshot()
    {

        Bitmap stitchedImage = null;
        try
        {
            long totalwidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.offsetWidth");//documentElement.scrollWidth");

            long totalHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return  document.body.parentNode.scrollHeight");

            int totalWidth = (int)totalwidth1;
            int totalHeight = (int)totalHeight1;

            // Get the Size of the Viewport
            long viewportWidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.clientWidth");//documentElement.scrollWidth");
            long viewportHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return window.innerHeight");//documentElement.scrollWidth");

            int viewportWidth = (int)viewportWidth1;
            int viewportHeight = (int)viewportHeight1;


        // Split the Screen in multiple Rectangles
        List<Rectangle> rectangles = new List<Rectangle>();
        // Loop until the Total Height is reached
        for (int i = 0; i < totalHeight; i += viewportHeight)
        {
            int newHeight = viewportHeight;
            // Fix if the Height of the Element is too big
            if (i + viewportHeight > totalHeight)
            {
                newHeight = totalHeight - i;
            }
            // Loop until the Total Width is reached
            for (int ii = 0; ii < totalWidth; ii += viewportWidth)
            {
                int newWidth = viewportWidth;
                // Fix if the Width of the Element is too big
                if (ii + viewportWidth > totalWidth)
                {
                    newWidth = totalWidth - ii;
                }

                // Create and add the Rectangle
                Rectangle currRect = new Rectangle(ii, i, newWidth, newHeight);
                rectangles.Add(currRect);
            }
        }

        // Build the Image
        stitchedImage = new Bitmap(totalWidth, totalHeight);
        // Get all Screenshots and stitch them together
        Rectangle previous = Rectangle.Empty;
        foreach (var rectangle in rectangles)
        {
            // Calculate the Scrolling (if needed)
            if (previous != Rectangle.Empty)
            {
                int xDiff = rectangle.Right - previous.Right;
                int yDiff = rectangle.Bottom - previous.Bottom;
                // Scroll
                //Selenium.RunScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));
                ((IJavaScriptExecutor)_driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));
                System.Threading.Thread.Sleep(200);
            }

            // Take Screenshot
            var screenshot = ((ITakesScreenshot)_driver).GetScreenshot();

            // Build an Image out of the Screenshot
            Image screenshotImage;
            using (MemoryStream memStream = new MemoryStream(screenshot.AsByteArray))
            {
                screenshotImage = Image.FromStream(memStream);
            }

            // Calculate the Source Rectangle
            Rectangle sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height);

            // Copy the Image
            using (Graphics g = Graphics.FromImage(stitchedImage))
            {
                g.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel);
            }

            // Set the Previous Rectangle
            previous = rectangle;
        }
        }
        catch (Exception ex)
        {
            // handle
        }
        return stitchedImage;
    }
11
S.Roshanth

J'ai nettoyé la réponse de @Selvantharajah Roshanth et ajouté une coche pour qu'il n'essaye pas d'assembler des captures d'écran qui tiennent déjà dans la fenêtre.

public Image GetEntireScreenshot()
{
    // Get the total size of the page
    var totalWidth = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return document.body.offsetWidth"); //documentElement.scrollWidth");
    var totalHeight = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return  document.body.parentNode.scrollHeight");
    // Get the size of the viewport
    var viewportWidth = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return document.body.clientWidth"); //documentElement.scrollWidth");
    var viewportHeight = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.innerHeight"); //documentElement.scrollWidth");

    // We only care about taking multiple images together if it doesn't already fit
    if (totalWidth <= viewportWidth && totalHeight <= viewportHeight)
    {
        var screenshot = driver.TakeScreenshot();
        return ScreenshotToImage(screenshot);
    }
    // Split the screen in multiple Rectangles
    var rectangles = new List<Rectangle>();
    // Loop until the totalHeight is reached
    for (var y = 0; y < totalHeight; y += viewportHeight)
    {
        var newHeight = viewportHeight;
        // Fix if the height of the element is too big
        if (y + viewportHeight > totalHeight)
        {
            newHeight = totalHeight - y;
        }
        // Loop until the totalWidth is reached
        for (var x = 0; x < totalWidth; x += viewportWidth)
        {
            var newWidth = viewportWidth;
            // Fix if the Width of the Element is too big
            if (x + viewportWidth > totalWidth)
            {
                newWidth = totalWidth - x;
            }
            // Create and add the Rectangle
            var currRect = new Rectangle(x, y, newWidth, newHeight);
            rectangles.Add(currRect);
        }
    }
    // Build the Image
    var stitchedImage = new Bitmap(totalWidth, totalHeight);
    // Get all Screenshots and stitch them together
    var previous = Rectangle.Empty;
    foreach (var rectangle in rectangles)
    {
        // Calculate the scrolling (if needed)
        if (previous != Rectangle.Empty)
        {
            var xDiff = rectangle.Right - previous.Right;
            var yDiff = rectangle.Bottom - previous.Bottom;
            // Scroll
            ((IJavaScriptExecutor) driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));
        }
        // Take Screenshot
        var screenshot = driver.TakeScreenshot();
        // Build an Image out of the Screenshot
        var screenshotImage = ScreenshotToImage(screenshot);
        // Calculate the source Rectangle
        var sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height);
        // Copy the Image
        using (var graphics = Graphics.FromImage(stitchedImage))
        {
            graphics.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel);
        }
        // Set the Previous Rectangle
        previous = rectangle;
    }
    return stitchedImage;
}

private static Image ScreenshotToImage(Screenshot screenshot)
{
    Image screenshotImage;
    using (var memStream = new MemoryStream(screenshot.AsByteArray))
    {
        screenshotImage = Image.FromStream(memStream);
    }
    return screenshotImage;
}
9

Il semble que les captures d'écran en plein écran ne soient pas encore implémentées dans ChromeDriver, en raison de certaines inexactitudes dans sa précédente implémentation.

Source: https://code.google.com/p/chromedriver/issues/detail?id=294

J'ai récemment écrit une application basée sur Selenium pour tester une interface utilisateur Internet Explorer et j'ai constaté que:

  1. Prendre des captures d'écran avec Selenium n'était pas aussi rapide que d'utiliser .NET, et
  2. Selenium ne peut pas prendre de captures d'écran lorsque des boîtes de dialogue sont présentes. C'était un inconvénient majeur, car je devais identifier les dialogues inattendus lors de l'interaction avec les pages.

Enquêtez à l'aide de la méthode Graphics.CopyFromScreen dans System.Drawing comme solution alternative jusqu'à ce que la fonctionnalité soit implémentée dans Chrome. Une fois que vous aurez essayé l'approche .Net, je ne pense pas que vous regarderez en arrière =]

Je suis tombé sur le même problème et ChromeDriver2 ne le prend tout simplement pas en charge.

J'ai donc créé un petit script qui défile sur la page, prend des captures d'écran et assemble le tout.

Vous pouvez trouver le script dans mon article de blog ici: http://dev.flauschig.ch/wordpress/?p=341

2
Roemer