Skip to content

Instantly share code, notes, and snippets.

@rgpower
Created December 15, 2020 19:39
Show Gist options
  • Save rgpower/ff0fcadaa3b95a2d1634838c763ee990 to your computer and use it in GitHub Desktop.
Save rgpower/ff0fcadaa3b95a2d1634838c763ee990 to your computer and use it in GitHub Desktop.
A Junit5 Extension that automagically sets BrowserStack sessions to pass/fail for Browser Automation Tests
/**
* Implements the Browserstack API for setting test sessions to pass/fail status as desribed in
* https://www.browserstack.com/docs/automate/selenium/view-test-results/mark-tests-as-pass-fail
*
**/
package utils.browserstack;
import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;
public class Browserstack {
public static UsernamePasswordCredentials getCredentials() {
UsernamePasswordCredentials creds = null;
String browserstackCreds = System.getenv("BROWSERSTACK_CREDS");
if (browserstackCreds != null && !"".equals(browserstackCreds)) {
String[] envCreds = browserstackCreds.split(":");
if (envCreds.length == 2) {
creds = new UsernamePasswordCredentials(envCreds[0], envCreds[1]);
} else {
throw new IllegalArgumentException("BROWSERSTACK_CREDS env value must be of form user:key");
}
}
return creds;
}
public static void setPassed(String sessionId, String reason) {
StatusUpdate passed = new StatusUpdate();
passed.status = "passed";
passed.reason = reason;
updateTestStatus(sessionId, passed);
}
public static void setFailed(String sessionId, String reason) {
StatusUpdate failed = new StatusUpdate();
failed.status = "failed";
failed.reason = reason;
updateTestStatus(sessionId, failed);
}
private static void updateTestStatus(String sessionId, StatusUpdate statusUpdate) {
UsernamePasswordCredentials credentials = getCredentials();
if (credentials != null) {
CredentialsProvider browserStackCreds = new BasicCredentialsProvider();
browserStackCreds.setCredentials(AuthScope.ANY, credentials);
String jsonText = new Gson().toJson(statusUpdate, StatusUpdate.class);
HttpEntity payload = EntityBuilder.create().setText(jsonText).build();
HttpPut request = new HttpPut(String.format("https://api.browserstack.com/automate/sessions/%s.json", sessionId));
request.setHeader("Content-Type", "application/json");
request.setEntity(payload);
CloseableHttpClient client = null;
HttpResponse response = null;
try {
client = HttpClientBuilder.create().setDefaultCredentialsProvider(browserStackCreds).build();
response = client.execute(request);
if (200 != response.getStatusLine().getStatusCode()) {
throw new RuntimeException("Unable thenTo set browserstack status for sessionId=" + sessionId);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
HttpClientUtils.closeQuietly(response);
HttpClientUtils.closeQuietly(client);
}
}
}
static class StatusUpdate {
String status;
String reason;
}
}
/**
* To use, modify your JUnit 5-based Browser Automation Test Class to use the JUnit5 Extension and
* provide the extension with access to your (WebDriver etc) session info by implementing
* the BrowserstackStatusUpdateable interface and using the ExtendWith annotation
*
* This implementation depends on Junit5, Apache HTTP Client, and Google Gson
*
*
* @ExtendWith(BrowserstackStatusUpdater.class)
* public class JUnitSeleniumTest implements BrowserstackStatusUpdateable {
* ...
* @Override
* public String getSessionID() {
* return this.webDriver.getSessionId().toString();
* }
*
**/
package utils.browserstack;
public interface BrowserstackStatusUpdateable {
String getSessionID();
}
/**
* Note that this JUnit5 Extension relies on Browserstack class, and configuration of enviroment variable
* BROWSERSTACK_CREDS which will contain the username:password of your BrowserStack Automation credentials
*
**/
package utils.browserstack;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import java.util.Optional;
public class BrowserstackStatusUpdater implements AfterEachCallback {
@Override
public void afterEach(ExtensionContext context) {
Optional testInstance = context.getTestInstance();
if (testInstance.isPresent()) {
Object o = testInstance.get();
if (o instanceof BrowserstackStatusUpdateable) {
BrowserstackStatusUpdateable test = (BrowserstackStatusUpdateable) o;
String sessionId = test.getSessionID();
Optional<Throwable> exception = context.getExecutionException();
String displayName = context.getDisplayName();
if (exception.isPresent()) {
Throwable t = exception.get();
Browserstack.setFailed(sessionId, displayName + ": " + t.getMessage());
} else {
Browserstack.setPassed(sessionId, displayName);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment