1
votes

Is there a trick to getting Win Jenkins slave to be OK with chromedriver?

My tests pull chromedriver and portable chrome from a maven repo and then execute them. The work fine on my local and when my build users does the same on my build systems.

When jenkins does the same thing, even when running in the foreground (not a svc) it fails with the error below. I've tried passing params to boost the verbosity to no avail.

org.openqa.selenium.WebDriverException: unknown error: Chrome failed to start: exited normally (Driver info: chromedriver=2.23.409699 (49b0fa931cda1caad0ae15b7d1b68004acd05129),platform=Windows NT 6.1.7601 SP1 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 62.63 seconds Build info: version: '2.41.0', revision: '3192d8a6c4449dc285928ba024779344f5423c58', time: '2014-03-27 11:29:39' System info: host: 'winengbld15', ip: '10.2.2.105', os.name: 'Windows Server 2008 R2', os.arch: 'amd64', os.version: '6.1', java.version: '1.8.0_40' Driver info: org.openqa.selenium.chrome.ChromeDriver at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:422) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:193) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:595) at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:240) at org.openqa.selenium.chrome.ChromeDriver.startSession(ChromeDriver.java:181) at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:126) at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:139) at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:160) at org.openqa.selenium.chrome.ChromeDriver.(ChromeDriver.java:128)

I setup the Chrome driver thus:

defaultPath = "target/drivers/chromedriver.exe";
System.setProperty("webdriver.chrome.driver", defaultPath);
ChromeLocator locator = new ChromeLocator();
driver = new ChromeDriver(locator.getCapabilities());

public class ChromeLocator {
  private static final Logger log = Logger.getLogger(ChromeLocator.class);

  /**
   * Obtain Chrome Configuration with location of binary
   * @return
   * @throws IOException 
   */
  public DesiredCapabilities getCapabilities() throws IOException {
    Map<String, Object> chromeOptions = new HashMap<String, Object>();
    chromeOptions.put("binary", getChromeExecutableLocation().getAbsolutePath());

    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
    capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);

    return capabilities;
  }

  // Windows defaults to unpacked location
  private File getChromeExecutableLocation() throws IOException {

    File chromeExe;

    if (SystemUtils.IS_OS_WINDOWS) {
      chromeExe = new File(System.getProperty("win.google.chrome.bin"));  
      log.info("*** win.google.chrome.bin: " + System.getProperty("win.google.chrome.bin"));
    } else {
      // Use the standard locator option for all other operating systems
      GoogleChromeLocator locator = new GoogleChromeLocator();
      BrowserInstallation installation = locator.findBrowserLocationOrFail();
      chromeExe = new File(installation.launcherFilePath());
    }
    log.info("Chrome Exe: " + chromeExe.getAbsolutePath() + " Is File: " + chromeExe.isFile());
    if (! chromeExe.exists() || ! chromeExe.isFile()) {
      throw new IOException("Cannot locate Chrome Executable.  Expected Location: " + chromeExe.getAbsolutePath());
    }
    return chromeExe;
  }
}
1

1 Answers

1
votes

We have several issues and the key seems to be the no-sandbox option to Chrome. Below is a solution that works on the desktop and on a jenkins slave running in the foreground or via service.

Part One: Maven Unpack of Chrome & Driver

  • Download PortableApps GoogleChrome
  • Install
  • Rename dir to generic name (GoogleChrome)
  • Zip dir
  • add to repository manager
  • setup maven-dependency-plugin executions to unpack

      <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.8</version>
    <executions>
     <execution>
       <id>extract portable google chrome</id>
       <phase>process-test-resources</phase>
       <goals>
         <goal>unpack</goal>
       </goals>
       <configuration>
         <skip>${skipWinChromeUnpack}</skip>
         <markersDirectory>${project.build.directory}/dependency-maven-plugin-markers/googlechrome</markersDirectory>
         <overWriteIfNewer>false</overWriteIfNewer>
         <artifactItems>
           <artifactItem>
              <groupId>com.google.chromium</groupId>
              <artifactId>chromedriver</artifactId>
              <version>${win.chromedriver.version}</version>                
              <classifier>win32</classifier>
              <type>zip</type>
            <outputDirectory>${project.build.directory}</outputDirectory>
           </artifactItem>
           <artifactItem>
              <groupId>com.portableapps</groupId>
              <artifactId>googlechrome</artifactId>
              <version>${win.chrome.version}</version>
              <classifier>win64</classifier>
              <type>zip</type>
            <outputDirectory>${project.build.directory}</outputDirectory>
           </artifactItem>
         </artifactItems>
       </configuration>
     </execution>         
    


Result At test execution time we have target/chromedriver.exe and target/GooglePortable/Google...exe files to use

Part Two: Maven Surefire config

We set System properties for location of driver and chrome exe to pass down to all unit tests

        <systemPropertyVariables>
          <webdriver.chrome.driver>${project.build.directory}/chromedriver.exe</webdriver.chrome.driver>
          <win.google.chrome.bin>${win.chrome.exe}</win.google.chrome.bin>  
        </systemPropertyVariables>

Part Three: Test Code

We use chrome driver service builder to set verbosity to 11 and start the driver using our favorite capabilities from that

public class ChromeLocator {
    private static final Logger log = Logger.getLogger(ChromeLocator.class);

/**
 * Obtain Chrome Configuration with location of binary
 * @return
 * @throws IOException
 */
public DesiredCapabilities getCapabilities() throws IOException {
    ChromeOptions chromeOptions = new ChromeOptions();
    chromeOptions.setBinary(getChromeExecutableLocation().getAbsolutePath());
    chromeOptions.addArguments("no-sandbox");
    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
    capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);


    return capabilities;
}

// Windows defaults to unpacked location
private File getChromeExecutableLocation() throws IOException {

    File chromeExe;

    if (SystemUtils.IS_OS_WINDOWS) {
        chromeExe = new File(System.getProperty("win.google.chrome.bin"));
    } else {
        // Use the standard locator option for all other operating systems
        GoogleChromeLocator locator = new GoogleChromeLocator();
        BrowserInstallation installation = locator.findBrowserLocationOrFail();
        chromeExe = new File(installation.launcherFilePath());
    }
    System.out.println("Chrome Exe: " + chromeExe.getAbsolutePath() + " Is File: " + chromeExe.isFile());
    if (! chromeExe.exists() || ! chromeExe.isFile()) {
        throw new IOException("Cannot locate Chrome Executable.  Expected Location: " + chromeExe.getAbsolutePath());
    }
    return chromeExe;
}

}

public class WebTest

{
static ChromeDriverService service = null;
static WebDriver driver = null;

@BeforeClass
static public void setupOnce() throws IOException {

    // Setup ChromeDriver with Verbosity on - perhaps control via system property - off by default?
    service = new ChromeDriverService.Builder()
            .withVerbose(true)
            .usingAnyFreePort()
            .build();

    service.start();

    // Setup locator to find unpacked Portable chrome exe
    ChromeLocator locator = new ChromeLocator();

    // Use service + capabilities from locator to open driver with settings and chrome bin
    driver = new RemoteWebDriver(service.getUrl(), locator.getCapabilities());
}

@AfterClass
static public void teardownOnce() {
    if (null != service) {
        service.stop();
        service = null;
    }
}
@Test
public void testGoogleSearch() throws InterruptedException, IOException {
    driver.get("http://www.google.com/xhtml");
    assertEquals("Google", driver.getTitle());

    WebElement searchBox = driver.findElement(By.name("q"));
    String searchString = "ChromeDriver";
    searchBox.sendKeys(searchString);
    searchBox.submit();

    String source = driver.getPageSource().toString();
    assertTrue("Expected DOCTYPE in\n" + source,
            source.contains("DOCTYPE"));
    driver.quit();
    service.stop();

}

}