Skip to content

Instantly share code, notes, and snippets.

@klepikov
Last active August 25, 2023 03:12
Show Gist options
  • Save klepikov/5457750 to your computer and use it in GitHub Desktop.
Save klepikov/5457750 to your computer and use it in GitHub Desktop.
Demo code for the GTAC 2013 talk "Web Performance Testing with WebDriver" by Michael Klepikov
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import org.json.*;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.*;
import org.openqa.selenium.logging.*;
import org.openqa.selenium.remote.*;
public class Test {
private static final String WEBDRIVER_SERVER_URL = "http://localhost:9515/";
private static String androidPackage = null; // Assigned in main()
private WebDriver driver;
public void testGoogleSearch() throws Exception {
driver.get("http://www.google.com/news");
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("Selenium Conference 2013");
element.submit();
driver.findElement(By.linkText("Web")).click();
}
public void setUp() throws Exception {
DesiredCapabilities caps = DesiredCapabilities.chrome();
if (null != androidPackage) {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOptions("androidPackage", androidPackage);
caps.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
}
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
logPrefs.enable(LogType.PERFORMANCE, Level.INFO);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
driver = new Augmenter().augment(new RemoteWebDriver(new URL(WEBDRIVER_SERVER_URL), caps));
Capabilities actualCaps = ((HasCapabilities) driver).getCapabilities();
System.out.println("Actual caps: " + actualCaps);
}
public void tearDown() throws Exception {
try {
Logs logs = driver.manage().logs();
System.out.println("Log types: " + logs.getAvailableLogTypes());
printLog(LogType.BROWSER);
submitPerformanceResult("Test.testGoogleSearch", logs.get(LogType.PERFORMANCE).getAll());
} finally {
driver.quit();
}
}
void printLog(String type) {
List<LogEntry> entries = driver.manage().logs().get(type).getAll();
System.out.println(entries.size() + " " + type + " log entries found");
for (LogEntry entry : entries) {
System.out.println(
new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
}
}
void submitPerformanceResult(String name, List<LogEntry> perfLogEntries)
throws IOException, JSONException {
JSONArray devToolsLog = new JSONArray();
System.out.println(perfLogEntries.size() + " performance log entries found");
for (LogEntry entry : perfLogEntries) {
JSONObject message = new JSONObject(entry.getMessage());
JSONObject devToolsMessage = message.getJSONObject("message");
// System.out.println(
// devToolsMessage.getString("method") + " " + message.getString("webview"));
devToolsLog.put(devToolsMessage);
}
byte[] screenshot = null;
if (null == androidPackage) { // Chrome on Android does not yet support screenshots
screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
}
String resultUrl = new WebPageTest(new URL("http://localhost:8888/"), "Test", name)
.submitResult(devToolsLog, screenshot);
System.out.println("Result page: " + resultUrl);
}
public static void main(String[] argv) throws Exception {
if (argv.length > 0 && "--android".equals(argv[0])) {
// androidPackage = "com.google.android.apps.chrome_dev";
androidPackage = "com.google.android.apps.chrome";
}
Test test = new Test();
test.setUp();
try {
test.testGoogleSearch();
} finally {
test.tearDown();
}
}
}
# This does not include WebPageTest submission, only an illustration
# how to use the Logging API from the WebDriver Python bindings.
from selenium import webdriver
from selenium.webdriver.common import keys
driver = webdriver.Chrome(
executable_path="chromedriver2_server",
desired_capabilities={'loggingPrefs': {'profiler': 'INFO'}})
# Hack the Logging API into the Python remote driver.
# Not implemented in Selenium, patch welcome!!
driver.command_executor._commands.update({
'getAvailableLogTypes': ('GET', '/session/$sessionId/log/types'),
'getLog': ('POST', '/session/$sessionId/log')})
try:
print 'Available log types:', driver.execute('getAvailableLogTypes')['value']
driver.get('http://news.google.com')
elem = driver.find_element_by_name('q') # Find the query box
elem.send_keys('GTAC 2013' + keys.Keys.RETURN)
elem = driver.find_element_by_link_text('Web')
elem.click()
print 'Profiler log:', driver.execute('getLog', {'type': 'performance'})['value']
finally:
driver.quit()
import java.io.*;
import java.net.*;
import java.util.zip.*;
import org.json.*;
public class WebPageTest {
private final String location;
private final URL createTestUrl;
private final URL workDoneUrl;
private final String mimeBoundary = "-----CorrectBatteryHorseStaple";
public WebPageTest(URL baseUrl, String location, String testUrl) throws IOException {
this.location = location;
this.createTestUrl = new URL(baseUrl,
"runtest.php?location=" + location + "&url=" + URLEncoder.encode(testUrl, "UTF-8") +
"&fvonly=1&f=json");
this.workDoneUrl = new URL(baseUrl, "work/workdone.php");
}
public String submitResult(JSONArray devToolsLog, byte[] screenshot) throws IOException, JSONException {
JSONObject testDescriptor = createTest();
postResult(testDescriptor, devToolsLog, screenshot);
return testDescriptor.getJSONObject("data").getString("userUrl");
}
private void writeResultsZip(OutputStream os, JSONArray devToolsLog, byte[] screenshot)
throws IOException, JSONException {
ZipOutputStream zos = new ZipOutputStream(os);
if (null != devToolsLog) {
zos.putNextEntry(new ZipEntry("1_devtools.json"));
OutputStreamWriter writer = new OutputStreamWriter(zos);
devToolsLog.write(writer);
writer.flush();
zos.closeEntry();
}
if (null != screenshot) {
zos.putNextEntry(new ZipEntry("1_screen.png"));
zos.write(screenshot);
zos.closeEntry();
}
zos.finish();
}
private JSONObject createTest() throws IOException, JSONException {
HttpURLConnection http = (HttpURLConnection) createTestUrl.openConnection();
if (HttpURLConnection.HTTP_OK != http.getResponseCode()) {
throw new IOException("WebPateTest test creation failed for location " + location + ": " +
http.getResponseCode() + " " +http.getResponseMessage());
}
Reader reader = new InputStreamReader(http.getInputStream(), "UTF-8");
try {
return new JSONObject(new JSONTokener(reader));
} finally {
reader.close();
}
}
private void postResult(JSONObject testDescriptor, JSONArray devToolsLog, byte[] screenshot)
throws IOException, JSONException {
HttpURLConnection http = (HttpURLConnection) workDoneUrl.openConnection();
http.setDoOutput(true);
http.addRequestProperty("Content-Type", "multipart/form-data; boundary=" +
mimeBoundary);
http.setChunkedStreamingMode(4096);
writeMultipartContent(http.getOutputStream(), testDescriptor, devToolsLog, screenshot);
http.getInputStream().close();
if (HttpURLConnection.HTTP_OK != http.getResponseCode()) {
throw new IOException("Result submission failed for " +
testDescriptor.getJSONObject("data").getString("userUrl") + " : " +
http.getResponseCode() + " " +http.getResponseMessage());
}
}
private void writeMultipartContent(
OutputStream os, JSONObject testDescriptor, JSONArray devToolsLog, byte[] screenshot)
throws IOException, JSONException {
String testId = testDescriptor.getJSONObject("data").getString("testId");
OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");
startMimePart(writer, "location", null);
writer.write("\r\n" + location + "\r\n");
startMimePart(writer, "id", null);
writer.write("\r\n" + testId + "\r\n");
startMimePart(writer, "done", null);
writer.write("\r\n1\r\n");
startMimePart(writer, "file", "1_results.zip");
writer.write("Content-Type: application/zip\r\n");
writer.write("Content-Transfer-Encoding: binary\r\n\r\n");
writer.flush();
writeResultsZip(os, devToolsLog, screenshot);
writer.write("\r\n--");
writer.write(mimeBoundary);
writer.write("--\r\n");
writer.flush();
}
private void startMimePart(Writer writer, String name, String filename) throws IOException {
writer.write("--");
writer.write(mimeBoundary);
writer.write("\r\n");
writer.write("Content-Disposition: form-data; name=\"");
writer.write(name);
if (null != filename) {
writer.write("\"; filename=\"");
writer.write(filename);
}
writer.write("\"\r\n");
}
}
@mediga
Copy link

mediga commented Jun 12, 2015

Issue "org.openqa.selenium.WebDriverException: unknown error: log type 'performance' not found" has been fixed refer this thread

https://code.google.com/p/selenium/issues/detail?id=8457#c10

@durgartanu
Copy link

Thanks for the post.. very valuable. I am getting one issue with the above code.
"unknown error: unhandled inspector error: {"code":-32601,"message":"'Timeline.start' wasn't found"}".
Any idea? thanks in advance.

@mvoitko
Copy link

mvoitko commented Nov 14, 2016

@klepikov Could you please be so kind and provide demo example of submitting performance logs to WebPageTest in Python?

@galina62
Copy link

galina62 commented Jan 2, 2017

@klepikov: I run your code. Performance record type appears to only include network activity. I am more interested in client CPU activity. I tried to change code by adding adding/enabling timeline but still got only Network activity records.
Could you please suggest how to retrieve client CPU activity.

Map<String, Object> perfLogPrefs = new HashMap<String, Object>();
perfLogPrefs.put("traceCategories", "browser,devtools.timeline,devtools"); // comma-separated trace categories
perfLogPrefs.put("enableTimeline", true);

@Napster158
Copy link

@klepikov: Could you please be so kind and provide demo example of submitting performance logs to WebPageTest in Python?

@SKumar-777
Copy link

Could you please provide the demo example of submitting performance logs to WebPageTest using C# with Selenium?
Also is it possible to download the HAR file from WebPageTest using Logging API(REST call) with C#?

@Pareshdanej
Copy link

Pareshdanej commented Jun 4, 2020

am trying to extract the browser console logs for my tests which are running on standalone-chrome-debug container on different server. I do not get the logs when in run on docker container.

However when i run the same test on my local machine with chrome driver, the logs are getting extracted as expected. Does any one has idea if we can extract the browser console logs for the test running on docker container.

Following way i am trying to achieve this.

   logPrefs.enable(LogType.BROWSER, Level.ALL);


    public LogEntries getBrowserConsoleLogs() {
        return driver.manage().logs().get(LogType.BROWSER);
    }```

@shubhamsharmas
Copy link

shubhamsharmas commented Jan 8, 2022

Can someone help me understand in the WebPageTest what is the baseURL? and the location? because i get the below error while running
Exception in thread "main" org.json.JSONException: A JSONObject text must begin with '{' at 1 [character 2 line 1]
at org.json.JSONTokener.syntaxError(JSONTokener.java:507)
at org.json.JSONObject.(JSONObject.java:225)
at video.ui.automation.stepDefinition.WebPageTest.createTest(WebPageTest.java:57)
at video.ui.automation.stepDefinition.WebPageTest.submitResult(WebPageTest.java:24)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment