Tuesday, November 1, 2016

WebDriver - log4net C# Examples

WebDriver - log4net C# Examples

log4net is a logging tool for .Net. log4net is a tool to help coders output log messages to different output targets. We will look at how to use log4net with WebDriver using C#. If you are new to log4net then you are at the right place. Below are two very simple & detailed examples of log4net in order to give it a start.

Example 1 of log4net - logging output to console

In Visual Studio (I am using Visual Studio version 12) open a new project (Unit Test Project).

Install NuGet packages for Selenium WebDriver and Selenium WebDriver Support Classes.

Add a reference for log4net.

After adding all the references, the Solution Explorer looks like as seen below:

We will use below code for our example:

Output (console) after running the above code is:

Lets go through the code used above and see what exactly we have done. We are using an ILog interface to log messages. LogManager is being used to obtain logger instances that implement this interface.
LogManager.GetLogger method retrieves or creates a named logger.

Then we are using the BasicConfigurator class's 'Configure' method to initializes the log4net logging system. BasicConfigurator class allows very simple programmatic configuration of log4net. BasicConfigurator.Configure initializes the log4net logging system using a ConsoleAppender that will write to Console.Out.

From the log4net message levels (ERROR, WARN, DEBUG, INFO etc) we are using INFO level, which logs INFO level messages.

Then with the help of Firefox we are opening www.google.com and again printing using logger.info in the last line.

In the output, the log messages are formatted using the PatternLayout layout object with the DetailConversionPattern layout style.
Default is %r [%t] %p %c %x - %m%n
r = Equivalent to timestamp. The milliseconds between the start of the application and the time the log entry was made.
t = Used to output the name of the thread that generated the logging event. Uses the thread number if no name is available.
p = Equivalent to level e.g. ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF
c = Equivalent to logger
x = Equivalent to ndc
A Nested Diagnostic Context, or NDC
m = Equivalent to message
n = Equivalent to newline

Another way to write th above pattern is:
%timestamp [%thread] %level %logger %ndc - %message%newline

If you observe the output of the above code, it shows null before text "Here is a ...". So in order to make sure that it does not show null in the output we can add the following line in the code.

Output (console) after running the above code is:

Here we are using NDC in the above newly added line of code. NDC, in short, is an instrument to distinguish interleaved log output from different sources. Log output is typically interleaved when a server handles multiple clients near-simultaneously. Interleaved log output can still be meaningful if each log entry from different contexts had a distinctive stamp. This is where NDCs come into play.

Example 2 of log4net - logging "success" message to console as well as log file

Here, instead of using BasicConfigurator, we are using XmlConfigurator. XmlConfigurator initializes the log4net environment using an Xml tree. In this example we are opening button.html file and asserting if the button with ID as 2 is enabled. If the button is enabled, we are logging a success message else we are throwing an exception.

XML file used with the above code is:
(In Solution Explorer, right-click on the project name, click Add and then choose New Item to add this XML file to the project.)

Button.html when opened in a browser looks as shown below. I right-clicked on button and selected Inspect Element:

Output (console) after running the above code is:

Output (log file) after running the above code is:

For accessing the log file (generated on running the code) right click on the project and select 'Open Folder in File Explorer'. Then go to folder 'bin' and then folder 'Debug'. Here your log file will be created.

Let's talk a little bit about XML file used above:

Firstly we are registering the log4net section handler. The log4net section of the configuration file needs to have a section handler registered. This is the section handler used. It simply returns the XML element that is the root of the section.

Here you have the ability to selectively enable or disable logging requests based on their logger. Log4net allows logging requests to print to multiple destinations. In log4net's language, an output destination is called an appender. Appenders must implement the log4net.Appenders.IAppender interface.

More than one appender can be attached to a logger. Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy. The first appender we have used is the RollingFileAppender. RollingFileAppender can roll log files based on size or date or both depending on the setting of the RollingStyle property. When set to Size the log file will be rolled once its size exceeds the MaximumFileSize. MaxSizeRollBackups gets or sets the maximum number of backup files that are kept before the oldest is erased. If set to zero, then there will be no backup files and the log file will be truncated when it reaches MaxFileSize. StaticLogFileName gets or sets a value indicating whether to always log to the same file. true if always should be logged to the same file, otherwise false.

ConsoleAppender Appends logging events to the console.

The root logger resides at the top of the logger hierarchy.

You need to have one root section to house your top-level logger references. These are the loggers that inherit information from your base logger (root). The only other thing that the root section houses is the minimum level to log. Since everything inherits from the root, no appenders will log information below that specified here. This is an easy way to quickly control the logging level in your application. Only one root logger element may only be defined and it must be a child of "log4net" element. The root logger is the root of the logger hierarchy. All loggers ultimately inherit from this logger.

As you can see that our code ran successfully and logged the success message both on the console and in the log file.

Example 2-A of log4net - logging an exception to console as well as log file

Below we have used the same code as above. The only difference is in the Id in the FindElement statement. This ID of 3 is some dummy ID that we have NOT actually used in our button.html file. We have used ID as 3 here so as to throw an exception intentionally.

Output (console) after running the above code is:

Output (log file) after running the above code is: