xebia / Xebium

Xebium provides Selenium (webdriver) bindings for FitNesse, with Selenium-IDE support
http://xebia.github.com/Xebium/
Apache License 2.0
76 stars 62 forks source link

Full-page Chrome screenshots using ShutterBug in conjunction with Xebium #168

Open roboaks opened 7 years ago

roboaks commented 7 years ago

We need to support Chrome as well as Firefox and have run into the issue wherein Chrome, being W3C compliant in this area, takes screenshot of the top-level browsing context’s viewport only. Full-page screenshots are an absolute requirement for us.

The most viable solution we’ve uncovered is to use the well-regarded ShutterBug (https://github.com/assertthat/selenium-shutterbug) for this purpose (if you know of an easier/better approach, please let me know!).

It appears that the best way for us to use ShutterBug with FitNesse is to create a fixture for that purpose. Ironically, although we are a Java shop (and I personally spend most of my time architecting/writing java code), we have never written a fixture because our automated testing group exclusively uses FitNesse/Xebium/Selenium stack—though we make extensive use of Javascript via runScript and storeEval commands. Thus, fixtures are new territory for me.

In this post (http://disq.us/p/1kg9diy), the ShutterBug author suggests:

Probably the easiest would be to create a separate FitNesse fixture for taking screenshots with shutterbug, the only difficulty i foresee is that you'll need to pass WebDriver instance to it from Xebium WebDriver supplier, which is not easy ATM with Xebium (https://github.com/xebia/Xebium/issues/120), so how you'll pass the driver instance is fully dependent on you implementation.

I don’t see how we could pass WebDriver instance to ShutterBug fixture via Xebium WebDriver supplier (DefaultWebDriverSupplier). Is it possible, or would we be better off taking the approach of jguglielmi in the OASIS project and incorporating the Xebium DefaultWebDriverSupplier code into our own?

Some guidance would be greatly appreciated!

ismailkhowaja1 commented 7 years ago

You can pass the web driver in SeleniumDriverFixture by making get function of web driver in DefaultWebDriverSupplier . But, you will need to create a static variable of webdriver in DefaultWebDriverSupplier.

My Solution: I put the dependency of shutterbug in Xebium Pom file. Made changes in these classes:

method executeDoCommand of SeleniumDriverFixture:

private boolean executeDoCommand(final String methodName, final String[] values) {
                ExtendedSeleniumCommand command = new ExtendedSeleniumCommand(methodName);
        SeleniumCommandResult commandResult = null;
        if (command.isCaptureEntirePageScreenshotCommand()) {
            try{
                Shutterbug.shootPage(defaultWebDriverSupplier.getWebDriver(), ScrollStrategy.BOTH_DIRECTIONS).save(screenshotBaseDir);
                FitNesseUtil.changeScreenShotName(screenshotBaseDir, String.format("%s.png",methodName.trim()));
            }
            catch (Exception e){
                System.out.println(e.getMessage());
            }

        } else {
            commandResult = executeDoCommandPolling(values, command);
        }

        if (screenCapture.requireScreenshot(command, commandResult.result)) {
            try {
                screenCapture.captureScreenshot(methodName, values,defaultWebDriverSupplier.getWebDriver());
            } catch (Exception e){
                System.out.println(e);
            }
        }

        if (commandResult.failed()
                && (command.isAssertCommand() || (commandResult.hasException() && stopTestOnException)
                || (!commandResult.hasException() && stopTestOnError))) {
            if (stopBrowserOnAssertion) {
                stopBrowser();
            }
            if (commandResult.hasException()) {
                throw new AssertionAndStopTestError(commandResult.getException());
            }
            throw new AssertionAndStopTestError(commandResult.output);
        }

        if (commandResult.hasException()) {
            throw new AssertionError(commandResult.getException());
        } else {
            return commandResult.result;
        }
    }

in DefaultWebDriverSupplier class:

    private static WebDriver driver;
    public WebDriver getWebDriver(){
        return this.driver;
    }

Lastly, ScreenCapture class methodcaptureScreenShot:

    void captureScreenshot(String methodName, String[] values, WebDriver driver) throws Exception {
        int stepNumber = nextStepNumber();
        try {
            Shutterbug.shootPage(driver, ScrollStrategy.BOTH_DIRECTIONS).save(screenshotBaseDir);
            FitNesseUtil.changeScreenShotName(screenshotBaseDir, String.format("%s.png",methodName.trim()));
        } catch (Exception e) {
            LOG.warn("Unable to finish screenshot capturing: " + e.getMessage());
        }
    }
roboaks commented 7 years ago

I greatly appreciate your help Ismail. Some questions:

  1. Did you make these changes on a forked version of Xebium?
  2. Were you able to test the changes?
  3. What is the quickest way for me to generate a Xebium jar incorporating these changes?

Thanks again!

ismailkhowaja1 commented 7 years ago
  1. Not exactly forked, we downloaded Xebium from their website and added more functionality in it.

  2. Yes, i have tested the functionality. You may not have FitNesseUtil.changeScreenShotName(screenshotBaseDir, String.format("%s.png",methodName.trim())); because we added that for keeping thing organized.

  3. mvn package -Pjar-with-dependencies. If you have that profile in you pom file.