You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by mo...@apache.org on 2015/12/24 05:55:23 UTC

incubator-zeppelin git commit: Add firebug and firepath for debugging

Repository: incubator-zeppelin
Updated Branches:
  refs/heads/master 8dd7f4938 -> ad7a6c082


Add firebug and firepath for debugging

Hi,

I've refactored some of the selenium related test case, and added firebug and firepath for debugging so that if CI is failing on travis it can be debugged on local.

Also I feel that we should delete notebook once selenium test case is finished.

Author: Prabhjyot Singh <pr...@gmail.com>

Closes #490 from prabhjyotsingh/addFirebug and squashes the following commits:

1cc00e0 [Prabhjyot Singh] Merge remote-tracking branch 'remote/master' into addFirebug
6af0aa6 [Prabhjyot Singh] resolving merge issue
28f5087 [Prabhjyot Singh] Fixing CI failure
31e330c [Prabhjyot Singh] remove firebug binaries
3e8613e [Prabhjyot Singh] Download firebug binaries insted of keeping it in resource
4e0e33c [Prabhjyot Singh] refactor add firebug and firepath for debugging delete notebook once test is finished


Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/ad7a6c08
Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/ad7a6c08
Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/ad7a6c08

Branch: refs/heads/master
Commit: ad7a6c0821840d32c8ddc87c9835c8b0cf1d33e1
Parents: 8dd7f49
Author: Prabhjyot Singh <pr...@gmail.com>
Authored: Fri Dec 18 12:35:48 2015 +0530
Committer: Lee moon soo <mo...@apache.org>
Committed: Thu Dec 24 13:56:31 2015 +0900

----------------------------------------------------------------------
 .../org/apache/zeppelin/CommandExecutor.java    |  74 +++++
 .../java/org/apache/zeppelin/ProcessData.java   | 248 +++++++++++++++
 .../org/apache/zeppelin/WebDriverManager.java   | 185 +++++++++++
 .../java/org/apache/zeppelin/ZeppelinIT.java    | 305 ++++++++-----------
 .../org/apache/zeppelin/ZeppelinITUtils.java    |  42 +++
 5 files changed, 676 insertions(+), 178 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/ad7a6c08/zeppelin-server/src/test/java/org/apache/zeppelin/CommandExecutor.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/CommandExecutor.java b/zeppelin-server/src/test/java/org/apache/zeppelin/CommandExecutor.java
new file mode 100644
index 0000000..fd8a66f
--- /dev/null
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/CommandExecutor.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class CommandExecutor {
+
+  public final static Logger LOG = LoggerFactory.getLogger(CommandExecutor.class);
+
+  public enum IGNORE_ERRORS {
+    TRUE,
+    FALSE
+  }
+
+  public static int NORMAL_EXIT = 0;
+
+  private static IGNORE_ERRORS DEFAULT_BEHAVIOUR_ON_ERRORS = IGNORE_ERRORS.TRUE;
+
+  public static Object executeCommandLocalHost(String[] command, boolean printToConsole, ProcessData.Types_Of_Data type, IGNORE_ERRORS ignore_errors) {
+    List<String> subCommandsAsList = new ArrayList<String>(Arrays.asList(command));
+    String mergedCommand = StringUtils.join(subCommandsAsList, " ");
+
+    LOG.info("Sending command \"" + mergedCommand + "\" to localhost");
+
+    ProcessBuilder processBuilder = new ProcessBuilder(command);
+    Process process = null;
+    try {
+      process = processBuilder.start();
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
+    ProcessData data_of_process = new ProcessData(process, printToConsole);
+    Object output_of_process = data_of_process.getData(type);
+    int exit_code = data_of_process.getExitCodeValue();
+
+    if (!printToConsole)
+      LOG.trace(output_of_process.toString());
+    else
+      LOG.debug(output_of_process.toString());
+    if (ignore_errors == IGNORE_ERRORS.FALSE && exit_code != NORMAL_EXIT) {
+      LOG.error(String.format("*********************Command '%s' failed with exitcode %s *********************", mergedCommand, exit_code));
+    }
+    return output_of_process;
+  }
+
+  public static Object executeCommandLocalHost(String command, boolean printToConsole, ProcessData.Types_Of_Data type) {
+    return executeCommandLocalHost(new String[]{"bash", "-c", command}, printToConsole, type, DEFAULT_BEHAVIOUR_ON_ERRORS);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/ad7a6c08/zeppelin-server/src/test/java/org/apache/zeppelin/ProcessData.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/ProcessData.java b/zeppelin-server/src/test/java/org/apache/zeppelin/ProcessData.java
new file mode 100644
index 0000000..d1e0d5c
--- /dev/null
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/ProcessData.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.concurrent.TimeUnit;
+
+public class ProcessData {
+  public enum Types_Of_Data {
+    OUTPUT,
+    ERROR,
+    EXIT_CODE,
+    STREAMS_MERGED,
+    PROCESS_DATA_OBJECT
+  }
+
+  public final static Logger LOG = LoggerFactory.getLogger(ProcessData.class);
+
+  private Process checked_process;
+  private boolean printToConsole = false;
+  private boolean removeRedundantOutput = true;
+
+  public ProcessData(Process connected_process, boolean printToConsole, int silenceTimeout, TimeUnit timeUnit) {
+    this.checked_process = connected_process;
+    this.printToConsole = printToConsole;
+    this.silenceTimeout = TimeUnit.MILLISECONDS.convert(silenceTimeout, timeUnit);
+  }
+
+  public ProcessData(Process connected_process, boolean printToConsole, int silenceTimeoutSec) {
+    this.checked_process = connected_process;
+    this.printToConsole = printToConsole;
+    this.silenceTimeout = TimeUnit.MILLISECONDS.convert(silenceTimeoutSec, TimeUnit.SECONDS);
+  }
+
+  public ProcessData(Process connected_process, boolean printToConsole) {
+    this.checked_process = connected_process;
+    this.printToConsole = printToConsole;
+  }
+
+  public ProcessData(Process connected_process) {
+    this.checked_process = connected_process;
+    this.printToConsole = true;
+  }
+
+
+  boolean returnCodeRetrieved = false;
+
+  private String outPutStream = null;
+  private String errorStream = null;
+  private int returnCode;
+  private long silenceTimeout = 10 * 60 * 1000;
+  private final long unconditionalExitDelayMinutes = 30;
+
+  public static boolean isRunning(Process process) {
+    try {
+      process.exitValue();
+      return false;
+    } catch (IllegalThreadStateException e) {
+      return true;
+    }
+  }
+
+  public Object getData(Types_Of_Data type) {
+    //TODO get rid of Pseudo-terminal will not be allocated because stdin is not a terminal.
+    switch (type) {
+      case OUTPUT: {
+        return this.getOutPutStream();
+      }
+      case ERROR: {
+        return this.getErrorStream();
+      }
+      case EXIT_CODE: {
+        return this.getExitCodeValue();
+      }
+      case STREAMS_MERGED: {
+        return this.getOutPutStream() + "\n" + this.getErrorStream();
+      }
+      case PROCESS_DATA_OBJECT: {
+        this.getErrorStream();
+        return this;
+      }
+      default: {
+        throw new IllegalArgumentException("Data Type " + type + " not supported yet!");
+      }
+    }
+  }
+
+  public int getExitCodeValue() {
+    try {
+      if (!returnCodeRetrieved) {
+        this.checked_process.waitFor();
+        this.returnCode = this.checked_process.exitValue();
+        this.returnCodeRetrieved = true;
+        this.checked_process.destroy();
+      }
+    } catch (Exception inter) {
+      throw new RuntimeException("Couldn't finish waiting for process " + this.checked_process + " termination", inter);
+    }
+    return this.returnCode;
+  }
+
+  public String getOutPutStream() {
+    if (this.outPutStream == null) {
+      try {
+        buildOutputAndErrorStreamData();
+      } catch (Exception e) {
+        throw new RuntimeException("Couldn't retrieve Output Stream data from process: " + this.checked_process.toString(), e);
+
+      }
+    }
+    this.outPutStream = this.outPutStream.replace("Pseudo-terminal will not be allocated because stdin is not a terminal.", "");
+    this.errorStream = this.errorStream.replace("Pseudo-terminal will not be allocated because stdin is not a terminal.", "");
+    return this.outPutStream;
+  }
+
+  public String getErrorStream() {
+    if (this.errorStream == null) {
+      try {
+        buildOutputAndErrorStreamData();
+      } catch (Exception e) {
+        throw new RuntimeException("Couldn't retrieve Error Stream data from process: " + this.checked_process.toString(), e);
+
+      }
+    }
+    this.outPutStream = this.outPutStream.replace("Pseudo-terminal will not be allocated because stdin is not a terminal.", "");
+    this.errorStream = this.errorStream.replace("Pseudo-terminal will not be allocated because stdin is not a terminal.", "");
+    return this.errorStream;
+  }
+
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(String.format("[OUTPUT STREAM]\n%s\n", this.outPutStream));
+    result.append(String.format("[ERROR STREAM]\n%s\n", this.errorStream));
+    result.append(String.format("[EXIT CODE]\n%d", this.returnCode));
+    return result.toString();
+  }
+
+  private void buildOutputAndErrorStreamData() throws IOException {
+    StringBuilder sbInStream = new StringBuilder();
+    StringBuilder sbErrorStream = new StringBuilder();
+
+    try {
+      InputStream in = this.checked_process.getInputStream();
+      InputStream inErrors = this.checked_process.getErrorStream();
+      BufferedReader inReader = new BufferedReader(new InputStreamReader(in));
+      BufferedReader inReaderErrors = new BufferedReader(new InputStreamReader(inErrors));
+      LOG.trace("Started retrieving data from streams of attached process: " + this.checked_process);
+
+      long lastStreamDataTime = System.currentTimeMillis();   //Store start time to be able to finish method if command hangs
+      long unconditionalExitTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(unconditionalExitDelayMinutes, TimeUnit.MINUTES); // Stop after 'unconditionalExitDelayMinutes' even if process is alive and sending output
+      final int BUFFER_LEN = 300;
+      char charBuffer[] = new char[BUFFER_LEN];     //Use char buffer to read output, size can be tuned.
+      boolean outputProduced = true;                //Flag to check if previous iteration produced any output
+      while (isRunning(this.checked_process) || outputProduced) {   //Continue if process is alive or some output was produced on previous iteration and there may be still some data to read.
+        outputProduced = false;
+        ZeppelinITUtils.sleep(100, false);                                  //Some local commands can exit fast, but immediate stream reading will give no output and after iteration, 'while' condition will be false so we will not read out any output while it is still there, just need to wait for some time for it to appear in streams.
+
+        StringBuilder tempSB = new StringBuilder();
+        while (inReader.ready()) {
+          tempSB.setLength(0);                                // clean temporary StringBuilder
+          int readCount = inReader.read(charBuffer, 0, BUFFER_LEN); //read up to 'BUFFER_LEN' chars to buffer
+          if (readCount < 1) {                                     // if nothing read or error occurred
+            break;
+          }
+          tempSB.append(charBuffer, 0, readCount);
+
+          sbInStream.append(tempSB);
+          if (tempSB.length() > 0) {
+            outputProduced = true;                                //set flag to know that we read something and there may be moire data, even if process already exited
+          }
+
+          lastStreamDataTime = System.currentTimeMillis();        //remember last time data was read from streams to be sure we are not looping infinitely
+        }
+
+        tempSB = new StringBuilder();                               //Same, but for error stream
+        while (inReaderErrors.ready()) {
+          tempSB.setLength(0);
+          int readCount = inReaderErrors.read(charBuffer, 0, BUFFER_LEN);
+          if (readCount < 1) {
+            break;
+          }
+          tempSB.append(charBuffer, 0, readCount);
+          sbErrorStream.append(tempSB);
+          if (tempSB.length() > 0) {
+            outputProduced = true;
+            String temp = new String(tempSB);
+            temp = temp.replaceAll("Pseudo-terminal will not be allocated because stdin is not a terminal.", "");
+            //TODO : error stream output need to be improved, because it outputs downloading information.
+            if (printToConsole) {
+              if (!temp.trim().equals("")) {
+                if (temp.toLowerCase().contains("error") || temp.toLowerCase().contains("failed")) {
+                  LOG.warn(temp.trim());
+                } else {
+                  LOG.debug(temp.trim());
+                }
+              }
+            }
+          }
+          lastStreamDataTime = System.currentTimeMillis();
+        }
+
+
+        if ((System.currentTimeMillis() - lastStreamDataTime > silenceTimeout) ||     //Exit if silenceTimeout ms has passed from last stream read. Means process is alive but not sending any data.
+            (System.currentTimeMillis() > unconditionalExitTime)) {                    //Exit unconditionally - guards against alive process continuously sending data.
+          LOG.info("Conditions: " + (System.currentTimeMillis() - lastStreamDataTime > silenceTimeout) + " " +
+              (System.currentTimeMillis() > unconditionalExitTime));
+          this.checked_process.destroy();
+          try {
+            if ((System.currentTimeMillis() > unconditionalExitTime))
+              LOG.error("!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Unconditional exit occured@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@!\nsome process hag up for more than " + unconditionalExitDelayMinutes + " minutes.");
+            LOG.error("!##################################!");
+            StringWriter sw = new StringWriter();
+            new Exception("Exited from buildOutputAndErrorStreamData by timeout").printStackTrace(new PrintWriter(sw)); //Get stack trace
+            String exceptionAsString = sw.toString();
+            LOG.error(exceptionAsString);
+          } catch (Exception ignore) {
+          }
+          break;
+        }
+      }
+
+      in.close();
+      inErrors.close();
+    } finally {
+      this.outPutStream = sbInStream.toString();
+      this.errorStream = sbErrorStream.toString();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/ad7a6c08/zeppelin-server/src/test/java/org/apache/zeppelin/WebDriverManager.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/WebDriverManager.java b/zeppelin-server/src/test/java/org/apache/zeppelin/WebDriverManager.java
new file mode 100644
index 0000000..5b0b199
--- /dev/null
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/WebDriverManager.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin;
+
+import org.apache.commons.io.FileUtils;
+import org.openqa.selenium.By;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.firefox.FirefoxBinary;
+import org.openqa.selenium.firefox.FirefoxDriver;
+import org.openqa.selenium.firefox.FirefoxProfile;
+import org.openqa.selenium.safari.SafariDriver;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+import org.openqa.selenium.support.ui.WebDriverWait;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import static org.junit.Assert.fail;
+
+
+public class WebDriverManager {
+
+  public final static Logger LOG = LoggerFactory.getLogger(WebDriverManager.class);
+
+  private static String downLoadsDir = "";
+
+  static WebDriver getWebDriver() {
+    WebDriver driver = null;
+
+    if (driver == null) {
+      try {
+        FirefoxBinary ffox = new FirefoxBinary();
+        if ("true".equals(System.getenv("TRAVIS"))) {
+          ffox.setEnvironmentProperty("DISPLAY", ":99"); // xvfb is supposed to
+          // run with DISPLAY 99
+        }
+        int firefoxVersion = WebDriverManager.getFirefoxVersion();
+        LOG.info("Firefox version " + firefoxVersion + " detected");
+
+        downLoadsDir = FileUtils.getTempDirectory().toString();
+
+        String tempPath = downLoadsDir + "/firebug/";
+
+        downloadFireBug(firefoxVersion, tempPath);
+
+        final String firebugPath = tempPath + "firebug.xpi";
+        final String firepathPath = tempPath + "firepath.xpi";
+
+        FirefoxProfile profile = new FirefoxProfile();
+        profile.setPreference("browser.download.folderList", 2);
+        profile.setPreference("browser.download.dir", downLoadsDir);
+        profile.setPreference("browser.helperApps.alwaysAsk.force", false);
+        profile.setPreference("browser.download.manager.showWhenStarting", false);
+        profile.setPreference("browser.download.manager.showAlertOnComplete", false);
+        profile.setPreference("browser.download.manager.closeWhenDone", true);
+        profile.setPreference("app.update.auto", false);
+        profile.setPreference("app.update.enabled", false);
+        profile.setPreference("dom.max_script_run_time", 0);
+        profile.setPreference("dom.max_chrome_script_run_time", 0);
+        profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/x-ustar,application/octet-stream,application/zip,text/csv,text/plain");
+        profile.setPreference("network.proxy.type", 0);
+
+        profile.addExtension(new File(firebugPath));
+        profile.addExtension(new File(firepathPath));
+
+        driver = new FirefoxDriver(ffox, profile);
+      } catch (Exception e) {
+      }
+    }
+
+    if (driver == null) {
+      try {
+        driver = new ChromeDriver();
+      } catch (Exception e) {
+      }
+    }
+
+    if (driver == null) {
+      try {
+        driver = new SafariDriver();
+      } catch (Exception e) {
+      }
+    }
+
+    String url;
+    if (System.getProperty("url") != null) {
+      url = System.getProperty("url");
+    } else {
+      url = "http://localhost:8080";
+    }
+
+    long start = System.currentTimeMillis();
+    boolean loaded = false;
+    driver.get(url);
+
+    while (System.currentTimeMillis() - start < 60 * 1000) {
+      // wait for page load
+      try {
+        (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
+          @Override
+          public Boolean apply(WebDriver d) {
+            return d.findElement(By.partialLinkText("Create new note"))
+                .isDisplayed();
+          }
+        });
+        loaded = true;
+        break;
+      } catch (TimeoutException e) {
+        driver.navigate().to(url);
+      }
+    }
+
+    if (loaded == false) {
+      fail();
+    }
+
+    return driver;
+  }
+
+  private static void downloadFireBug(int firefoxVersion, String tempPath) {
+    String firebugUrlString = null;
+    if (firefoxVersion < 23)
+      firebugUrlString = "http://getfirebug.com/releases/firebug/1.11/firebug-1.11.4.xpi";
+    else if (firefoxVersion >= 23 && firefoxVersion < 30)
+      firebugUrlString = "http://getfirebug.com/releases/firebug/1.12/firebug-1.12.8.xpi";
+    else if (firefoxVersion >= 30)
+      firebugUrlString = "http://getfirebug.com/releases/firebug/2.0/firebug-2.0.7.xpi";
+
+
+    LOG.info("firebug version: " + firefoxVersion + ", will be downloaded to " + tempPath);
+    try {
+      File firebugFile = new File(tempPath + "firebug.xpi");
+      URL firebugUrl = new URL(firebugUrlString);
+      if (!firebugFile.exists()) {
+        FileUtils.copyURLToFile(firebugUrl, firebugFile);
+      }
+
+
+      File firepathFile = new File(tempPath + "firepath.xpi");
+      URL firepathUrl = new URL("https://addons.cdn.mozilla.net/user-media/addons/11900/firepath-0.9.7.1-fx.xpi");
+      if (!firepathFile.exists()) {
+        FileUtils.copyURLToFile(firepathUrl, firepathFile);
+      }
+
+    } catch (IOException e) {
+      LOG.error("Download of firebug version: " + firefoxVersion + ", falied in path " + tempPath);
+      LOG.error(e.toString());
+    }
+    LOG.info("Download of firebug version: " + firefoxVersion + ", successful");
+  }
+
+  public static int getFirefoxVersion() {
+    try {
+      String firefoxVersionCmd = "firefox -v";
+      if (System.getProperty("os.name").startsWith("Mac OS")) {
+        firefoxVersionCmd = "/Applications/Firefox.app/Contents/MacOS/" + firefoxVersionCmd;
+      }
+      String versionString = (String) CommandExecutor.executeCommandLocalHost(firefoxVersionCmd, false, ProcessData.Types_Of_Data.OUTPUT);
+      return Integer.valueOf(versionString.replaceAll("Mozilla Firefox", "").trim().substring(0, 2));
+    } catch (Exception e) {
+      e.printStackTrace();
+      return -1;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/ad7a6c08/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
index 2a32c9c..6b464dd 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
@@ -68,70 +68,12 @@ public class ZeppelinIT {
   private static final long MAX_PARAGRAPH_TIMEOUT_SEC = 60;
   private WebDriver driver;
 
-  private void setWebDriver() {
-
-    if (driver == null) {
-      try {
-        FirefoxBinary ffox = new FirefoxBinary();
-        if ("true".equals(System.getenv("TRAVIS"))) {
-          ffox.setEnvironmentProperty("DISPLAY", ":99"); // xvfb is supposed to
-                                                         // run with DISPLAY 99
-        }
-        FirefoxProfile profile = new FirefoxProfile();
-        driver = new FirefoxDriver(ffox, profile);
-      } catch (Exception e) {
-        LOG.error("Starting Firefox failed",e);
-      }
-    }
-
-    if (driver == null) {
-      try {
-        driver = new ChromeDriver();
-      } catch (Exception e) {
-        LOG.error("Starting Chrome failed",e);
-      }
-    }
-
-    if (driver == null) {
-      try {
-        driver = new SafariDriver();
-      } catch (Exception e) {
-        LOG.error("Starting Safari failed",e);
-      }
-    }
-
-    String url;
-    if (System.getProperty("url") != null) {
-      url = System.getProperty("url");
-    } else {
-      url = "http://localhost:8080";
-    }
-
-    long start = System.currentTimeMillis();
-    boolean loaded = false;
-    driver.get(url);
-
-    while (System.currentTimeMillis() - start < 60 * 1000) {
-      try { // wait for page load
-        WebElement element = pollingWait(By.partialLinkText("Create new note"), MAX_BROWSER_TIMEOUT_SEC);
-        loaded = element.isDisplayed();
-        break;
-      } catch (TimeoutException e) {
-        driver.navigate().to(url);
-      }
-    }
-
-    if (loaded == false) {
-      fail();
-    }
-  }
-
   @Before
   public void startUp() {
     if (!endToEndTestEnabled()) {
       return;
     }
-    setWebDriver();
+    driver = WebDriverManager.getWebDriver();
   }
 
   @After
@@ -186,125 +128,132 @@ public class ZeppelinIT {
       return;
     }
     try {
-    createNewNote();
-
-    // wait for first paragraph's " READY " status text
-    waitForParagraph(1, "READY");
-
-    /*
-     * print angular template
-     * %angular <div id='angularTestButton' ng-click='myVar=myVar+1'>BindingTest_{{myVar}}_</div>
-     */
-    WebElement paragraph1Editor = driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea"));
-    paragraph1Editor.sendKeys("println" + Keys.chord(Keys.SHIFT, "9") + "\""
-                + Keys.chord(Keys.SHIFT, "5")
-                + "angular <div id='angularTestButton' "
-                + "ng" + Keys.chord(Keys.SUBTRACT) + "click='myVar=myVar+1'>"
-                + "BindingTest_{{myVar}}_</div>\")");
-    paragraph1Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(1, "FINISHED");
-
-    // check expected text
-    waitForText("BindingTest__", By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-
-    /*
-     * Bind variable
-     * z.angularBind("myVar", 1)
-     */
-    assertEquals(1, driver.findElements(By.xpath(getParagraphXPath(2) + "//textarea")).size());
-    WebElement paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea"));
-    paragraph2Editor.sendKeys("z.angularBind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", 1)");
-    paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(2, "FINISHED");
-
-    // check expected text
-    waitForText("BindingTest_1_", By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-
-
-    /*
-     * print variable
-     * print("myVar="+z.angular("myVar"))
-     */
-    WebElement paragraph3Editor = driver.findElement(By.xpath(getParagraphXPath(3) + "//textarea"));
-    paragraph3Editor.sendKeys(
-        "print" + Keys.chord(Keys.SHIFT, "9") + "\"myVar=\"" + Keys.chord(Keys.ADD)
-        + "z.angular" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\"))");
-    paragraph3Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(3, "FINISHED");
-
-    // check expected text
-    waitForText("myVar=1", By.xpath(
-        getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]"));
-
-    /*
-     * Click element
-     */
-    driver.findElement(By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click();
-
-    // check expected text
-    waitForText("BindingTest_2_", By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-
-    /*
-     * Register watcher
-     * z.angularWatch("myVar", (before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext) => {
-     *   z.run(2, context)
-     * }
-     */
-    WebElement paragraph4Editor = driver.findElement(By.xpath(getParagraphXPath(4) + "//textarea"));
-    paragraph4Editor.sendKeys(
-        "z.angularWatch" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", "
-        + Keys.chord(Keys.SHIFT, "9")
-        + "before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext)"
-        + Keys.EQUALS + ">{ z.run" +Keys.chord(Keys.SHIFT, "9") + "2, context)}");
-    paragraph4Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(4, "FINISHED");
-
-
-    /*
-     * Click element, again and see watcher works
-     */
-    driver.findElement(By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click();
-
-    // check expected text
-    waitForText("BindingTest_3_", By.xpath(
-        getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-    waitForParagraph(3, "FINISHED");
-
-    // check expected text by watcher
-    waitForText("myVar=3", By.xpath(
-        getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]"));
-
-    /*
-     * Unbind
-     * z.angularUnbind("myVar")
-     */
-    WebElement paragraph5Editor = driver.findElement(By.xpath(getParagraphXPath(5) + "//textarea"));
-    paragraph5Editor.sendKeys(
-        "z.angularUnbind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\")");
-    paragraph5Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(5, "FINISHED");
-
-    // check expected text
-    waitForText("BindingTest__",
-        By.xpath(getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-
-    /*
-     * Bind again and see rebind works.
-     */
-    paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea"));
-    paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
-    waitForParagraph(2, "FINISHED");
-
-    // check expected text
-    waitForText("BindingTest_1_",
-        By.xpath(getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
-
-    System.out.println("testCreateNotebook Test executed");
+      createNewNote();
+
+      // wait for first paragraph's " READY " status text
+      waitForParagraph(1, "READY");
+
+      /*
+       * print angular template
+       * %angular <div id='angularTestButton' ng-click='myVar=myVar+1'>BindingTest_{{myVar}}_</div>
+       */
+      WebElement paragraph1Editor = driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea"));
+      paragraph1Editor.sendKeys("println" + Keys.chord(Keys.SHIFT, "9") + "\""
+                  + Keys.chord(Keys.SHIFT, "5")
+                  + "angular <div id='angularTestButton' "
+                  + "ng" + Keys.chord(Keys.SUBTRACT) + "click='myVar=myVar+1'>"
+                  + "BindingTest_{{myVar}}_</div>\")");
+      paragraph1Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(1, "FINISHED");
+
+      // check expected text
+      waitForText("BindingTest__", By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+
+      /*
+       * Bind variable
+       * z.angularBind("myVar", 1)
+       */
+      assertEquals(1, driver.findElements(By.xpath(getParagraphXPath(2) + "//textarea")).size());
+      WebElement paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea"));
+      paragraph2Editor.sendKeys("z.angularBind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", 1)");
+      paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(2, "FINISHED");
+
+      // check expected text
+      waitForText("BindingTest_1_", By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+
+
+      /*
+       * print variable
+       * print("myVar="+z.angular("myVar"))
+       */
+      WebElement paragraph3Editor = driver.findElement(By.xpath(getParagraphXPath(3) + "//textarea"));
+      paragraph3Editor.sendKeys(
+          "print" + Keys.chord(Keys.SHIFT, "9") + "\"myVar=\"" + Keys.chord(Keys.ADD)
+          + "z.angular" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\"))");
+      paragraph3Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(3, "FINISHED");
+
+      // check expected text
+      waitForText("myVar=1", By.xpath(
+          getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]"));
+
+      /*
+       * Click element
+       */
+      driver.findElement(By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click();
+
+      // check expected text
+      waitForText("BindingTest_2_", By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+
+      /*
+       * Register watcher
+       * z.angularWatch("myVar", (before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext) => {
+       *   z.run(2, context)
+       * }
+       */
+      WebElement paragraph4Editor = driver.findElement(By.xpath(getParagraphXPath(4) + "//textarea"));
+      paragraph4Editor.sendKeys(
+          "z.angularWatch" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\", "
+          + Keys.chord(Keys.SHIFT, "9")
+          + "before:Object, after:Object, context:org.apache.zeppelin.interpreter.InterpreterContext)"
+          + Keys.EQUALS + ">{ z.run" +Keys.chord(Keys.SHIFT, "9") + "2, context)}");
+      paragraph4Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(4, "FINISHED");
+
+
+      /*
+       * Click element, again and see watcher works
+       */
+      driver.findElement(By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]")).click();
+
+      // check expected text
+      waitForText("BindingTest_3_", By.xpath(
+          getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+      waitForParagraph(3, "FINISHED");
+
+      // check expected text by watcher
+      waitForText("myVar=3", By.xpath(
+          getParagraphXPath(3) + "//div[@ng-bind=\"paragraph.result.msg\"]"));
+
+      /*
+       * Unbind
+       * z.angularUnbind("myVar")
+       */
+      WebElement paragraph5Editor = driver.findElement(By.xpath(getParagraphXPath(5) + "//textarea"));
+      paragraph5Editor.sendKeys(
+          "z.angularUnbind" + Keys.chord(Keys.SHIFT, "9") + "\"myVar\")");
+      paragraph5Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(5, "FINISHED");
+
+      // check expected text
+      waitForText("BindingTest__",
+          By.xpath(getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+
+      /*
+       * Bind again and see rebind works.
+       */
+      paragraph2Editor = driver.findElement(By.xpath(getParagraphXPath(2) + "//textarea"));
+      paragraph2Editor.sendKeys(Keys.chord(Keys.SHIFT, Keys.ENTER));
+      waitForParagraph(2, "FINISHED");
+
+      // check expected text
+      waitForText("BindingTest_1_",
+          By.xpath(getParagraphXPath(1) + "//div[@id=\"angularTestButton\"]"));
+
+      driver.findElement(By.xpath("//*[@id='main']/div//h3/span[1]/button[@tooltip='Remove the notebook']"))
+          .sendKeys(Keys.ENTER);
+      ZeppelinITUtils.sleep(1000, true);
+      driver.findElement(By.xpath("//div[@class='modal-dialog'][contains(.,'delete this notebook')]" +
+          "//div[@class='modal-footer']//button[contains(.,'OK')]")).click();
+      ZeppelinITUtils.sleep(100, true);
+
+      System.out.println("testCreateNotebook Test executed");
     } catch (ElementNotVisibleException e) {
       File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/ad7a6c08/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinITUtils.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinITUtils.java b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinITUtils.java
new file mode 100644
index 0000000..2fa6806
--- /dev/null
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinITUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ZeppelinITUtils {
+
+  public final static Logger LOG = LoggerFactory.getLogger(ZeppelinITUtils.class);
+
+  public static void sleep(long millis, boolean logOutput) {
+    if (logOutput) {
+      LOG.info("Starting sleeping for " + (millis / 1000) + " seconds...");
+      LOG.info("Caller: " + Thread.currentThread().getStackTrace()[2]);
+    }
+    try {
+      Thread.sleep(millis);
+    } catch (InterruptedException e) {
+      e.printStackTrace();
+    }
+    if (logOutput) {
+      LOG.info("Finished.");
+    }
+  }
+}