Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure sessions are always closed, even when receiving SIGINT #39

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@
<redirectTestOutputToFile>false</redirectTestOutputToFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
51 changes: 49 additions & 2 deletions src/test/java/com/yourcompany/Tests/TestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
/**
* Simple TestNG test which demonstrates being instantiated via a DataProvider in order to supply multiple browser combinations.
*
* @author Neil Manvar
* @authors Neil Manvar, Dylan Lacey
*/
public class TestBase {

Expand All @@ -35,13 +35,57 @@ public class TestBase {
/**
* ThreadLocal variable which contains the {@link WebDriver} instance which is used to perform browser interactions with.
*/
private ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>();
private InheritableThreadLocal<WebDriver> webDriver = new InheritableThreadLocal<WebDriver>();

/**
* ThreadLocal variable which contains the Sauce Job Id.
*/
private ThreadLocal<String> sessionId = new ThreadLocal<String>();

/**
* ThreadLocal variable which contains the Shutdown Hook instance for this Thread's WebDriver.
*
* Registered just before Browser creation, de-registered after 'quit' is called.
*/
private ThreadLocal<Thread> shutdownHook = new ThreadLocal<>();

/**
* Creates the shutdownHook, or returns an existing copy.
*/
private Thread getShutdownHook() {
if (shutdownHook.get() == null) {
shutdownHook.set( new Thread(() -> {
try {
if (webDriver.get() != null) webDriver.get().quit();
} catch (org.openqa.selenium.NoSuchSessionException ignored) { } // Don't care if session already closed
}));
}
return shutdownHook.get();
}

/**
* Registers the shutdownHook with the runtime.
*
* Ignoring exceptions on registration; They mean the VM is already shutting down and it's too late.
*/
private void registerShutdownHook() {
try {
Runtime.getRuntime().addShutdownHook(getShutdownHook());
} catch (IllegalStateException ignored) {} // Thrown if a hook is added while shutting down; We don't care
}

/**
* De-registers the shutdownHook. This allows the GC to remove the thread and avoids double-quitting.
*
* Silently swallows exceptions if the VM is already shutting down; it's too late.
*/
private void deregisterShutdownHook() {
if (shutdownHook.get() != null) {
try {
Runtime.getRuntime().removeShutdownHook(getShutdownHook());
} catch (IllegalStateException ignored) { } // VM already shutting down; Irrelevant
}
}
/**
* DataProvider that explicitly sets the browser combinations to be used.
*
Expand Down Expand Up @@ -106,6 +150,8 @@ protected void createDriver(String browser, String version, String os, String me
new URL("https://" + username + ":" + accesskey + "@ondemand.saucelabs.com/wd/hub"),
capabilities));

registerShutdownHook();

// set current sessionId
String id = ((RemoteWebDriver) getWebDriver()).getSessionId().toString();
sessionId.set(id);
Expand All @@ -120,6 +166,7 @@ protected void createDriver(String browser, String version, String os, String me
public void tearDown(ITestResult result) throws Exception {
((JavascriptExecutor) webDriver.get()).executeScript("sauce:job-result=" + (result.isSuccess() ? "passed" : "failed"));
webDriver.get().quit();
deregisterShutdownHook();
}

protected void annotate(String text) {
Expand Down