77

Is there a way to capture browser logs while running automated test cases with Selenium? I found an article on how to capture JavaScript errors in Selenium. But that is just for Firefox and only for errors. I would like to get all the console logs.

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
user3246489
  • 1,111
  • 3
  • 12
  • 20

10 Answers10

71

I assume it is something in the lines of:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class ChromeConsoleLogging {
    private WebDriver driver;


    @BeforeMethod
    public void setUp() {
        System.setProperty("webdriver.chrome.driver", "c:\\path\\to\\chromedriver.exe");        
        DesiredCapabilities caps = DesiredCapabilities.chrome();
        LoggingPreferences logPrefs = new LoggingPreferences();
        logPrefs.enable(LogType.BROWSER, Level.ALL);
        caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
        driver = new ChromeDriver(caps);
    }

    @AfterMethod
    public void tearDown() {
        driver.quit();
    }

    public void analyzeLog() {
        LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
        for (LogEntry entry : logEntries) {
            System.out.println(new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
            //do something useful with the data
        }
    }

    @Test
    public void testMethod() {
        driver.get("http://mypage.com");
        //do something on page
        analyzeLog();
    }
}

Source : Get chrome's console log

Community
  • 1
  • 1
Margus
  • 19,694
  • 14
  • 55
  • 103
  • Not sure what browser support you need, but by changing **import org.openqa.selenium.chrome.ChromeDriver;** and **DesiredCapabilities caps = DesiredCapabilities.chrome();** you should be able to select it. – Margus Aug 21 '14 at 16:36
  • I would be requiring for all the browsers ...thanks for this . It is definitely something which i can work with @Margus – user3246489 Aug 21 '14 at 16:38
  • nice solution for chrome but have you a solution for IE11? – Stéphane GRILLON Jun 27 '17 at 14:06
  • 2
    @Margus If i call `driver.manage().logs().get("browser");` multiple times with in the same driver instance, it fails to capture entries (tried refreshing driver, navigating to another url). Any thoughts or workarounds? – user2649233 Feb 08 '18 at 12:24
  • @user3246489 Last time I checked it wasn't supported for IE see https://github.com/SeleniumHQ/selenium/issues/4802 – elworthy Feb 05 '19 at 08:58
64

In a more concise way, you can do:

LogEntries logs = driver.manage().logs().get(LogType.BROWSER);

For me it worked wonderfully for catching JS errors in console. Then you can add some verification for its size. For example, if it is > 0, add some error output.

Charlie
  • 8,530
  • 2
  • 55
  • 53
Johnny
  • 14,397
  • 15
  • 77
  • 118
25

As a non-java selenium user, here is the python equivalent to Margus's answer:

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities    

class ChromeConsoleLogging(object):

    def __init__(self, ):
        self.driver = None

    def setUp(self, ):
        desired = DesiredCapabilities.CHROME
        desired ['loggingPrefs'] = { 'browser':'ALL' }
        self.driver = webdriver.Chrome(desired_capabilities=desired)

    def analyzeLog(self, ):
        data = self.driver.get_log('browser')
        print(data)

    def testMethod(self, ):
        self.setUp()
        self.driver.get("http://mypage.com")
        self.analyzeLog()

Reference

Edit: Keeping Python answer in this thread because it is very similar to the Java answer and this post is returned on a Google search for the similar Python question

cacti5
  • 2,006
  • 2
  • 25
  • 33
5

A less elegant solution is taking the log 'manually' from the user data dir:

  1. Set the user data dir to a fixed place:

    options = new ChromeOptions();
    capabilities = DesiredCapabilities.chrome();
    options.addArguments("user-data-dir=/your_path/");
    capabilities.setCapability(ChromeOptions.CAPABILITY, options);
    
  2. Get the text from the log file chrome_debug.log located in the path you've entered above.

I use this method since RemoteWebDriver had problems getting the console logs remotely. If you run your test locally that can be easy to retrieve.

didinino
  • 93
  • 1
  • 8
5

Adding LoggingPreferences to "goog:loggingPrefs" properties with the Chrome Driver options can help to fetch the Browser console logs for all Log levels.

ChromeOptions options = new ChromeOptions();    
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
options.setCapability("goog:loggingPrefs", logPrefs);
WebDriver driver = new ChromeDriver(options);
TechRookie
  • 171
  • 2
  • 4
3

Starting with Firefox 65 an about:config flag exists now so console API calls like console.log() land in the output stream and thus the log file (see (https://github.com/mozilla/geckodriver/issues/284#issuecomment-458305621).

profile = new FirefoxProfile();
profile.setPreference("devtools.console.stdout.content", true);
phk
  • 2,002
  • 1
  • 29
  • 54
1

Driver manager logs can be used to get console logs from browser and it will help to identify errors appears in console.

   import org.openqa.selenium.logging.LogEntries;
   import org.openqa.selenium.logging.LogEntry;

    public List<LogEntry> getBrowserConsoleLogs()
    {
    LogEntries log= driver.manage().logs().get("browser")
    List<LogEntry> logs=log.getAll();
    return logs;
    }
shiv
  • 497
  • 3
  • 17
0

Before launching webdriver, we just set this environment variable to let chrome generate it:

export CHROME_LOG_FILE=$(pwd)/tests/e2e2/logs/client.log
DerWOK
  • 1,061
  • 9
  • 13
0

Add cast RemoteWebDriver to driver initialize and you will have the .setLogLevel method:

import java.util.logging.Level;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;

public class PrintLogTest {
    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "/Users/.../chromedriver");
        WebDriver driver = new ChromeDriver();

        //here
        ((RemoteWebDriver) driver).setLogLevel(Level.INFO);

        driver.get("https://google.com/");
        driver.findElement(By.name("q")).sendKeys("automation test");
        driver.quit();
    }
}

Example output:

Jun 15, 2020 4:27:04 PM org.openqa.selenium.remote.RemoteWebDriver log
INFO: Executing: get [430aec21a9beb6340a4185c4ea6a693d, get {url=https://google.com/}]
Jun 15, 2020 4:27:06 PM org.openqa.selenium.remote.RemoteWebDriver log
INFO: Executed: [430aec21a9beb6340a4185c4ea6a693d, get {url=https://google.com/}]
Jun 15, 2020 4:27:06 PM org.openqa.selenium.remote.RemoteWebDriver log
INFO: Executing: findElement [430aec21a9beb6340a4185c4ea6a693d, findElement {using=name, value=q}]
Jun 15, 2020 4:27:06 PM org.openqa.selenium.remote.RemoteWebDriver log
INFO: Executed: [430aec21a9beb6340a4185c4ea6a693d, findElement {using=name, value=q}]
...
...

At least I've tried it on ChromeDriver() and FirefoxDriver() and it working fine.

frianH
  • 7,295
  • 6
  • 20
  • 45
0

Browser and performance logging only captures whatever is logged to the console and connection metadata in Chrome (at least, at the time of this writing). To actually get the contents of a fetch request I found some JS (source) to intercept all fetch requests and log the contents to the console which I could then access in browser logs. Total overkill, but hey it works.

const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
  let [resource, config] = args;

  let response = await originalFetch(resource, config);

  response
    .clone()
    .json()
    .then((data) => console.log("fetch response:" + JSON.stringify(data)));

  return response;
};

Minified

const{fetch:originalFetch}=window;window.fetch=async(...n)=>{let[t,e]=n,o=await originalFetch(t,e);return o.clone().json().then((n=>console.log("fetch :"+JSON.stringify(n)))),o};

Usage snippet (Scala)

driver.executeScript("""const{fetch:originalFetch}=window;window.fetch=async(...n)=>{let[e,o]=n,t=await originalFetch(e,o);return t.clone().json().then((n=>console.log("fetch response:"+JSON.stringify(n)))),t};""")

// action that triggers the fetch

val logEntry = driver.manage().logs().get("browser").iterator().asScala.filter(_.getMessage.contains("fetch response:")).toList
Sean Glover
  • 1,766
  • 18
  • 31