We shall discuss how to introduce logging to our tests and how logging is important. After execution of test cases if we want to know the failures and how the test execution has taken place, we look at the test reports. However, if we want to investigate why the failures have taken place we should have proper logging in our code.

Introduction to Logging in Python Tests

The logs should describe each step of the test script. So that in case of failures we can find the root cause of the failure easily. There should be a separate file maintained for the logging purpose. Any non-technical person like business analysts, manual test engineers and so on should be able to open the log file and understand which step of the test case failed and for what reason.

As per industry standards, the logging is followed in the below format:

<time stamp> : <Logging levels> : <test case name> : <Log message>

The timestamp of when the actual test step gets executed should be captured in the log file. The logging levels are of different types like DEBUG, INFO, WARNING, ERROR and CRITICAL.  The INFO logging level is used to message the purpose of the test step. The WARNING logging level is used to alert the user of a particular step. However it does not indicate a failure in the test step. If the expected result has not matched with the actual result [for example: failure in assertion], the ERROR logging level is used. If there is a test that is blocking the entire execution, then CRITICAL logging level is used. The DEBUG logging level is used to give debugging information useful for the developer.

The below image shows a sample log file with logging.

Conclusion: Thus we have discussed what logs are and its importance. For more details, you can refer to the link:

https://courses.rahulshettyacademy.com/courses/learn-selenium-automation-in-easy-python-language/lectures/13248498

In the next section we shall discuss the importance of Filehandler in logging.

Importance of Filehandler in Logging tests

To implement logging in Python, we have to import package logging by adding the statement import logging in our code. This is by default available with Python and we don’t have to download any external plugin for that.

Next we have to create an object of the logging class with the help of the getLogger method.

logger = logging.getLogger()

The logger object is responsible for all the loggings. In the log file, it is essential to have the test case name to get its corresponding log information. To capture the test case file name at the run time, we shall pass the argument __name__ to the getLogger method. In this way, the name gets printed in the log file. If the argument is omitted in the getLogger method, the root is printed in the log file.

logger = logging.getLogger(__name__)

Next we shall add the logging levels with the logger object. The ways to use the logging levels are described below.

  • logger.debug("A debug statement is executed") – to produce  DEBUG logging level along with the message A debug statement is executed in the log file.
  • logger.info("An information statement is executed") – to produce INFO logging level along with the message An information statement is executed in the log file.
  • logger.warning("A warning statement is executed") – to produce WARNING logging level along with the message A warning statement is executed in the log file.
  • logger.error("An error statement is executed") – to produce ERROR logging level along with the message An error statement is executed in the log file.
  • logger.critical("A critical statement is executed") – to produce CRITICAL logging level along with the message A critical statement is executed in the log file.

Now the logger object should have the knowledge of the location and the format of the log file where the logging levels along with their message needs to be captured. We shall then call the addHandler method with the help of the logger object.

There is FileHandler class [is a part of the parent logging package] that accepts the location of the log file as an argument. We shall then create a filehandler object of that class and pass that as an argument to the addHandler method. The filehandler object has the knowledge of the location of the log file.

fileHandler = logging.FileHandler('logfile.log')

logger.addHandler(fileHandler)

Now we shall explore how to describe the format of the log file. For this we have to take help of the Formatter class [is a part of the parent logging package] that accepts the format in which the log file as an argument. There are multiple formats to capture the content of the log file. But here we shall discuss the mostly widely used industry standard format of the log file.

First to get the current date and time in the below format in Python, we have to pass the value as %(asctime)s.

Next to describe the logging level in the log file, we have to pass the value as %(levelname)s. Then the test case name or the test file name can be added to the log file by passing %(name)s as an argument to the Formatter class. Finally %(message)s is passed as argument to print the logging message.

To sum up, we shall pass the parameters - %(asctime)s, %(levelname)s, %(name)s and %(message)s one by one separated by : as arguments to the Formatter class.

logging.Formatter("%(asctime)s :%(levelname)s : %(name)s :%(message)s")

Our next task is to pass the Formatter class information to the logger object. For this we shall first store logging.Formatter in an object variable named formatter. We shall then call the setFormatter method with the help of the fileHandler object and pass the formatter object as an argument to that method.

fileHandler.setFormatter(formatter)

Thus our formatter object is now logically connected to the fileHandler object. This fileHandler object is connected to the logger object with the help of the addHandler method. So the logger object holds information of both the log file location and format in which logging information is to be captured.

Finally we have to set the level of logging in the log file. For that we shall call the setLevel method with the help of the logger object. Then pass the logging level as a parameter to that method.

Please note the logging levels follow the below hierarchy:

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

This means if we set the logging level to INFO, then all the logs from the INFO, WARNING, ERROR and CRITICAL shall get captured in the log file. If it is set to ERROR, only the ERROR and CRITICAL logs shall be reflected in the log file.

Code Implementation

import logging

def test_logDemo():

# to get the name of the test case file name at runtime

logger = logging.getLogger(__name__)

# FileHandler class to set the location of log file

fileHandler = logging.FileHandler('logfile.log')

# Formatter class to set the format of log file

formatter = logging.Formatter("%(asctime)s :%(levelname)s : %(name)s :%(message)s")

# object of FileHandler gets formatting info from setFormatter #method

fileHandler.setFormatter(formatter)

# logger object gets formatting, path of log file info with addHandler #method

logger.addHandler(fileHandler) 

# setting logging level to INFO

logger.setLevel(logging.INFO)

# logging debug message with logger object

logger.debug("A debug statement is executed")

# logging info message with logger object

logger.info("An information statement is executed")

# logging warning message with logger object

logger.warning("A warning message is executed")

# logging error message with logger object

logger.error("An error message is executed")

# logging critical message with logger object

logger.critical("A critical message is executed")

Output:

A new file named logfile.log gets created in the project folder. The log file contains the date and time stamp, the logging levels, test case file name pytestDemo.test_p and the logging messages.

As we set the logging level to INFO, INFO, WARNING, ERROR and CRITICAL logging messages are captured. The DEBUG log message is skipped. This is as per the hierarchy of logging levels discussed.

Conclusion

Thus we have discussed the importance of Filehandler in logging in Python. For more details, you can refer to the links:

https://courses.rahulshettyacademy.com/courses/learn-selenium-automation-in-easy-python-language/lectures/13248501

https://courses.rahulshettyacademy.com/courses/learn-selenium-automation-in-easy-python-language/lectures/13248503

https://courses.rahulshettyacademy.com/courses/learn-selenium-automation-in-easy-python-language/lectures/13248505

In the next post, we shall discuss how to interact with excel in Python.


Tags


You may also like

API Basics and Architecture

API Basics and Architecture
Leave a Reply

Your email address will not be published. Required fields are marked

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}