packagedev.selenium.troubleshooting;importjava.io.IOException;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.Arrays;importjava.util.logging.FileHandler;importjava.util.logging.Handler;importjava.util.logging.Level;importjava.util.logging.Logger;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importorg.openqa.selenium.manager.SeleniumManager;importorg.openqa.selenium.remote.RemoteWebDriver;publicclassLoggingTest{@Testpublicvoidlogging()throwsIOException{Loggerlogger=Logger.getLogger("");logger.setLevel(Level.FINE);Arrays.stream(logger.getHandlers()).forEach(handler->{handler.setLevel(Level.FINE);});Handlerhandler=newFileHandler("selenium.xml");logger.addHandler(handler);Logger.getLogger(RemoteWebDriver.class.getName()).setLevel(Level.FINEST);Logger.getLogger(SeleniumManager.class.getName()).setLevel(Level.SEVERE);LoggerlocalLogger=Logger.getLogger(this.getClass().getName());localLogger.warning("this is a warning");localLogger.info("this is useful information");localLogger.fine("this is detailed debug information");byte[]bytes=Files.readAllBytes(Paths.get("selenium.xml"));StringfileContent=newString(bytes);Assertions.assertTrue(fileContent.contains("this is a warning"));Assertions.assertTrue(fileContent.contains("this is useful information"));Assertions.assertTrue(fileContent.contains("this is detailed debug information"));}}
Python logs are typically created per module. You can match all submodules by referencing the top
level module. So to work with all loggers in selenium module, you can do this:
importatexitimportloggingimportosimportpytestdeftest_logging():logger=logging.getLogger('selenium')logger.setLevel(logging.DEBUG)log_path="selenium.log"handler=logging.FileHandler(log_path)logger.addHandler(handler)logging.getLogger('selenium.webdriver.remote').setLevel(logging.WARN)logging.getLogger('selenium.webdriver.common').setLevel(logging.DEBUG)logger.info("this is useful information")logger.warning("this is a warning")logger.debug("this is detailed debug information")try:withopen(log_path,'r')asfp:assertlen(fp.readlines())==3finally:atexit.register(delete_path,log_path)defdelete_path(path):os.remove(path)
You must also create and add a log handler (StreamHandler, FileHandler, etc).
.NET logger is managed with a static class, so all access to logging is managed simply by referencing Log from the OpenQA.Selenium.Internal.Logging namespace.
If you want to see as much debugging as possible in all the classes,
you can turn on debugging globally in Ruby by setting $DEBUG = true.
For more fine-tuned control, Ruby Selenium created its own Logger class to wrap the default Logger class.
This implementation provides some interesting additional features.
Obtain the logger directly from the #loggerclass method on the Selenium::WebDriver module:
# frozen_string_literal: truerequire'spec_helper'RSpec.describe'Logging'dodescribe'Options'dolet(:file_name){File.expand_path('selenium.log')}after{FileUtils.rm_f(file_name)}it'logs things'dologger=Selenium::WebDriver.loggerlogger.level=:debuglogger.output=file_namelogger.ignore(:jwp_caps,:logger_info)logger.allow(%i[selenium_managerexample_id])logger.warn('this is a warning',id::example_id)logger.info('this is useful information',id::example_id)logger.debug('this is detailed debug information',id::example_id)expect(File.readlines(file_name).grep(/\[:example_id\]/).size).toeq3endendend
packagedev.selenium.troubleshooting;importjava.io.IOException;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.Arrays;importjava.util.logging.FileHandler;importjava.util.logging.Handler;importjava.util.logging.Level;importjava.util.logging.Logger;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importorg.openqa.selenium.manager.SeleniumManager;importorg.openqa.selenium.remote.RemoteWebDriver;publicclassLoggingTest{@Testpublicvoidlogging()throwsIOException{Loggerlogger=Logger.getLogger("");logger.setLevel(Level.FINE);Arrays.stream(logger.getHandlers()).forEach(handler->{handler.setLevel(Level.FINE);});Handlerhandler=newFileHandler("selenium.xml");logger.addHandler(handler);Logger.getLogger(RemoteWebDriver.class.getName()).setLevel(Level.FINEST);Logger.getLogger(SeleniumManager.class.getName()).setLevel(Level.SEVERE);LoggerlocalLogger=Logger.getLogger(this.getClass().getName());localLogger.warning("this is a warning");localLogger.info("this is useful information");localLogger.fine("this is detailed debug information");byte[]bytes=Files.readAllBytes(Paths.get("selenium.xml"));StringfileContent=newString(bytes);Assertions.assertTrue(fileContent.contains("this is a warning"));Assertions.assertTrue(fileContent.contains("this is useful information"));Assertions.assertTrue(fileContent.contains("this is detailed debug information"));}}
Python has 6 logger levels: CRITICAL, ERROR, WARNING, INFO, DEBUG, and NOTSET.
The default is WARNING
importatexitimportloggingimportosimportpytestdeftest_logging():logger=logging.getLogger('selenium')logger.setLevel(logging.DEBUG)log_path="selenium.log"handler=logging.FileHandler(log_path)logger.addHandler(handler)logging.getLogger('selenium.webdriver.remote').setLevel(logging.WARN)logging.getLogger('selenium.webdriver.common').setLevel(logging.DEBUG)logger.info("this is useful information")logger.warning("this is a warning")logger.debug("this is detailed debug information")try:withopen(log_path,'r')asfp:assertlen(fp.readlines())==3finally:atexit.register(delete_path,log_path)defdelete_path(path):os.remove(path)
Things get complicated when you use PyTest, though. By default, PyTest hides logging unless the test
fails. You need to set 3 things to get PyTest to display logs on passing tests.
To always output logs with PyTest you need to run with additional arguments.
First, -s to prevent PyTest from capturing the console.
Second, -p no:logging, which allows you to override the default PyTest logging settings so logs can
be displayed regardless of errors.
So you need to set these flags in your IDE, or run PyTest on command line like:
pytest -s -p no:logging
Finally, since you turned off logging in the arguments above, you now need to add configuration to
turn it back on:
logging.basicConfig(level=logging.WARN)
.NET has 6 logger levels: Error, Warn, Info, Debug, Trace and None. The default level is Info.
usingMicrosoft.VisualStudio.TestTools.UnitTesting;usingOpenQA.Selenium;usingOpenQA.Selenium.Internal.Logging;usingOpenQA.Selenium.Remote;usingSystem;usingSystem.IO;namespaceSeleniumDocs.Troubleshooting{ [TestClass]publicclassLoggingTest{privateconststringfilePath="Selenium.log"; [TestMethod]publicvoidLogging(){Log.SetLevel(LogEventLevel.Trace);Log.Handlers.Add(newFileLogHandler(filePath));Log.SetLevel(typeof(RemoteWebDriver),LogEventLevel.Debug);Log.SetLevel(typeof(SeleniumManager),LogEventLevel.Info);Warn("this is a warning");Info("this is useful information");Debug("this is detailed debug information");using(varfileStream=File.Open(filePath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite)){using(varstreamReader=newStreamReader(fileStream)){varfileLogContent=streamReader.ReadToEnd();StringAssert.Contains(fileLogContent,"this is a warning");StringAssert.Contains(fileLogContent,"this is useful information");StringAssert.Contains(fileLogContent,"this is detailed debug information");}}} [TestCleanup]publicvoidTestCleanup(){// reset log to defaultLog.SetLevel(LogEventLevel.Info).Handlers.Clear().Handlers.Add(newConsoleLogHandler());}// logging is only for internal usage// hacking it via reflectionprivatevoidDebug(stringmessage){LogMessage("Debug",message);}privatevoidWarn(stringmessage){LogMessage("Warn",message);}privatevoidInfo(stringmessage){LogMessage("Info",message);}privatevoidLogMessage(stringmethodName,stringmessage){vargetLoggerMethod=typeof(Log).GetMethod("GetLogger",System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.NonPublic,newType[]{typeof(Type)});varlogger=getLoggerMethod.Invoke(null,newobject[]{typeof(LoggingTest)});varemitMethod=logger.GetType().GetMethod(methodName);emitMethod.Invoke(logger,newobject[]{message});}}}
Ruby logger has 5 logger levels: :debug, :info, :warn, :error, :fatal.
As of Selenium v4.9.1, The default is :info.
# frozen_string_literal: truerequire'spec_helper'RSpec.describe'Logging'dodescribe'Options'dolet(:file_name){File.expand_path('selenium.log')}after{FileUtils.rm_f(file_name)}it'logs things'dologger=Selenium::WebDriver.loggerlogger.level=:debuglogger.output=file_namelogger.ignore(:jwp_caps,:logger_info)logger.allow(%i[selenium_managerexample_id])logger.warn('this is a warning',id::example_id)logger.info('this is useful information',id::example_id)logger.debug('this is detailed debug information',id::example_id)expect(File.readlines(file_name).grep(/\[:example_id\]/).size).toeq3endendend
JavaScript has 9 logger levels: OFF, SEVERE, WARNING, INFO, DEBUG, FINE, FINER, FINEST, ALL.
The default is OFF.
To change the level of the logger:
logger.setLevel(logging.Level.INFO)
Content Help
Note: This section needs additional and/or updated content
packagedev.selenium.troubleshooting;importjava.io.IOException;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.Arrays;importjava.util.logging.FileHandler;importjava.util.logging.Handler;importjava.util.logging.Level;importjava.util.logging.Logger;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importorg.openqa.selenium.manager.SeleniumManager;importorg.openqa.selenium.remote.RemoteWebDriver;publicclassLoggingTest{@Testpublicvoidlogging()throwsIOException{Loggerlogger=Logger.getLogger("");logger.setLevel(Level.FINE);Arrays.stream(logger.getHandlers()).forEach(handler->{handler.setLevel(Level.FINE);});Handlerhandler=newFileHandler("selenium.xml");logger.addHandler(handler);Logger.getLogger(RemoteWebDriver.class.getName()).setLevel(Level.FINEST);Logger.getLogger(SeleniumManager.class.getName()).setLevel(Level.SEVERE);LoggerlocalLogger=Logger.getLogger(this.getClass().getName());localLogger.warning("this is a warning");localLogger.info("this is useful information");localLogger.fine("this is detailed debug information");byte[]bytes=Files.readAllBytes(Paths.get("selenium.xml"));StringfileContent=newString(bytes);Assertions.assertTrue(fileContent.contains("this is a warning"));Assertions.assertTrue(fileContent.contains("this is useful information"));Assertions.assertTrue(fileContent.contains("this is detailed debug information"));}}
By default all logs are sent to sys.stderr. To direct output somewhere else, you need to add a
handler with either a StreamHandler or a FileHandler:
importatexitimportloggingimportosimportpytestdeftest_logging():logger=logging.getLogger('selenium')logger.setLevel(logging.DEBUG)log_path="selenium.log"handler=logging.FileHandler(log_path)logger.addHandler(handler)logging.getLogger('selenium.webdriver.remote').setLevel(logging.WARN)logging.getLogger('selenium.webdriver.common').setLevel(logging.DEBUG)logger.info("this is useful information")logger.warning("this is a warning")logger.debug("this is detailed debug information")try:withopen(log_path,'r')asfp:assertlen(fp.readlines())==3finally:atexit.register(delete_path,log_path)defdelete_path(path):os.remove(path)
By default all logs are sent to System.Console.Error output. To direct output somewhere else, you need to add a handler with a FileLogHandler:
usingMicrosoft.VisualStudio.TestTools.UnitTesting;usingOpenQA.Selenium;usingOpenQA.Selenium.Internal.Logging;usingOpenQA.Selenium.Remote;usingSystem;usingSystem.IO;namespaceSeleniumDocs.Troubleshooting{ [TestClass]publicclassLoggingTest{privateconststringfilePath="Selenium.log"; [TestMethod]publicvoidLogging(){Log.SetLevel(LogEventLevel.Trace);Log.Handlers.Add(newFileLogHandler(filePath));Log.SetLevel(typeof(RemoteWebDriver),LogEventLevel.Debug);Log.SetLevel(typeof(SeleniumManager),LogEventLevel.Info);Warn("this is a warning");Info("this is useful information");Debug("this is detailed debug information");using(varfileStream=File.Open(filePath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite)){using(varstreamReader=newStreamReader(fileStream)){varfileLogContent=streamReader.ReadToEnd();StringAssert.Contains(fileLogContent,"this is a warning");StringAssert.Contains(fileLogContent,"this is useful information");StringAssert.Contains(fileLogContent,"this is detailed debug information");}}} [TestCleanup]publicvoidTestCleanup(){// reset log to defaultLog.SetLevel(LogEventLevel.Info).Handlers.Clear().Handlers.Add(newConsoleLogHandler());}// logging is only for internal usage// hacking it via reflectionprivatevoidDebug(stringmessage){LogMessage("Debug",message);}privatevoidWarn(stringmessage){LogMessage("Warn",message);}privatevoidInfo(stringmessage){LogMessage("Info",message);}privatevoidLogMessage(stringmethodName,stringmessage){vargetLoggerMethod=typeof(Log).GetMethod("GetLogger",System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.NonPublic,newType[]{typeof(Type)});varlogger=getLoggerMethod.Invoke(null,newobject[]{typeof(LoggingTest)});varemitMethod=logger.GetType().GetMethod(methodName);emitMethod.Invoke(logger,newobject[]{message});}}}
By default, logs are sent to the console in stdout. To store the logs in a file:
# frozen_string_literal: truerequire'spec_helper'RSpec.describe'Logging'dodescribe'Options'dolet(:file_name){File.expand_path('selenium.log')}after{FileUtils.rm_f(file_name)}it'logs things'dologger=Selenium::WebDriver.loggerlogger.level=:debuglogger.output=file_namelogger.ignore(:jwp_caps,:logger_info)logger.allow(%i[selenium_managerexample_id])logger.warn('this is a warning',id::example_id)logger.info('this is useful information',id::example_id)logger.debug('this is detailed debug information',id::example_id)expect(File.readlines(file_name).grep(/\[:example_id\]/).size).toeq3endendend
JavaScript does not currently support sending output to a file.
To send logs to console output:
logging.installConsoleHandler()
Content Help
Note: This section needs additional and/or updated content
packagedev.selenium.troubleshooting;importjava.io.IOException;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.Arrays;importjava.util.logging.FileHandler;importjava.util.logging.Handler;importjava.util.logging.Level;importjava.util.logging.Logger;importorg.junit.jupiter.api.Assertions;importorg.junit.jupiter.api.Test;importorg.openqa.selenium.manager.SeleniumManager;importorg.openqa.selenium.remote.RemoteWebDriver;publicclassLoggingTest{@Testpublicvoidlogging()throwsIOException{Loggerlogger=Logger.getLogger("");logger.setLevel(Level.FINE);Arrays.stream(logger.getHandlers()).forEach(handler->{handler.setLevel(Level.FINE);});Handlerhandler=newFileHandler("selenium.xml");logger.addHandler(handler);Logger.getLogger(RemoteWebDriver.class.getName()).setLevel(Level.FINEST);Logger.getLogger(SeleniumManager.class.getName()).setLevel(Level.SEVERE);LoggerlocalLogger=Logger.getLogger(this.getClass().getName());localLogger.warning("this is a warning");localLogger.info("this is useful information");localLogger.fine("this is detailed debug information");byte[]bytes=Files.readAllBytes(Paths.get("selenium.xml"));StringfileContent=newString(bytes);Assertions.assertTrue(fileContent.contains("this is a warning"));Assertions.assertTrue(fileContent.contains("this is useful information"));Assertions.assertTrue(fileContent.contains("this is detailed debug information"));}}
Because logging is managed by module, instead of working with just "selenium", you can specify
different levels for different modules:
importatexitimportloggingimportosimportpytestdeftest_logging():logger=logging.getLogger('selenium')logger.setLevel(logging.DEBUG)log_path="selenium.log"handler=logging.FileHandler(log_path)logger.addHandler(handler)logging.getLogger('selenium.webdriver.remote').setLevel(logging.WARN)logging.getLogger('selenium.webdriver.common').setLevel(logging.DEBUG)logger.info("this is useful information")logger.warning("this is a warning")logger.debug("this is detailed debug information")try:withopen(log_path,'r')asfp:assertlen(fp.readlines())==3finally:atexit.register(delete_path,log_path)defdelete_path(path):os.remove(path)
.NET logging is managed on a per class level, set the level you want to use on a per-class basis:
usingMicrosoft.VisualStudio.TestTools.UnitTesting;usingOpenQA.Selenium;usingOpenQA.Selenium.Internal.Logging;usingOpenQA.Selenium.Remote;usingSystem;usingSystem.IO;namespaceSeleniumDocs.Troubleshooting{ [TestClass]publicclassLoggingTest{privateconststringfilePath="Selenium.log"; [TestMethod]publicvoidLogging(){Log.SetLevel(LogEventLevel.Trace);Log.Handlers.Add(newFileLogHandler(filePath));Log.SetLevel(typeof(RemoteWebDriver),LogEventLevel.Debug);Log.SetLevel(typeof(SeleniumManager),LogEventLevel.Info);Warn("this is a warning");Info("this is useful information");Debug("this is detailed debug information");using(varfileStream=File.Open(filePath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite)){using(varstreamReader=newStreamReader(fileStream)){varfileLogContent=streamReader.ReadToEnd();StringAssert.Contains(fileLogContent,"this is a warning");StringAssert.Contains(fileLogContent,"this is useful information");StringAssert.Contains(fileLogContent,"this is detailed debug information");}}} [TestCleanup]publicvoidTestCleanup(){// reset log to defaultLog.SetLevel(LogEventLevel.Info).Handlers.Clear().Handlers.Add(newConsoleLogHandler());}// logging is only for internal usage// hacking it via reflectionprivatevoidDebug(stringmessage){LogMessage("Debug",message);}privatevoidWarn(stringmessage){LogMessage("Warn",message);}privatevoidInfo(stringmessage){LogMessage("Info",message);}privatevoidLogMessage(stringmethodName,stringmessage){vargetLoggerMethod=typeof(Log).GetMethod("GetLogger",System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.NonPublic,newType[]{typeof(Type)});varlogger=getLoggerMethod.Invoke(null,newobject[]{typeof(LoggingTest)});varemitMethod=logger.GetType().GetMethod(methodName);emitMethod.Invoke(logger,newobject[]{message});}}}
Ruby’s logger allows you to opt in (“allow”) or opt out (“ignore”) of log messages based on their IDs.
Everything that Selenium logs includes an ID. You can also turn on or off all deprecation notices by
using :deprecations.
These methods accept one or more symbols or an array of symbols:
# frozen_string_literal: truerequire'spec_helper'RSpec.describe'Logging'dodescribe'Options'dolet(:file_name){File.expand_path('selenium.log')}after{FileUtils.rm_f(file_name)}it'logs things'dologger=Selenium::WebDriver.loggerlogger.level=:debuglogger.output=file_namelogger.ignore(:jwp_caps,:logger_info)logger.allow(%i[selenium_managerexample_id])logger.warn('this is a warning',id::example_id)logger.info('this is useful information',id::example_id)logger.debug('this is detailed debug information',id::example_id)expect(File.readlines(file_name).grep(/\[:example_id\]/).size).toeq3endendend
# frozen_string_literal: truerequire'spec_helper'RSpec.describe'Logging'dodescribe'Options'dolet(:file_name){File.expand_path('selenium.log')}after{FileUtils.rm_f(file_name)}it'logs things'dologger=Selenium::WebDriver.loggerlogger.level=:debuglogger.output=file_namelogger.ignore(:jwp_caps,:logger_info)logger.allow(%i[selenium_managerexample_id])logger.warn('this is a warning',id::example_id)logger.info('this is useful information',id::example_id)logger.debug('this is detailed debug information',id::example_id)expect(File.readlines(file_name).grep(/\[:example_id\]/).size).toeq3endendend
Content Help
Note: This section needs additional and/or updated content