Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML Logger in python

Tags:

python

logging

I am using python logging module for logging to console and text file. I am using HTMLTestRunner for logging in html file. I guess I am using HTMLTestRunner 0.8.0

However problem is that HTMLTestRunner prints only print statements and logging module does not print print statements. Is there any way I can get logging statement inside html file

Below is the htmlrunner code

runner = HTMLTestRunner.HTMLTestRunner(
                stream=outfile,
                title='Test Report',
                description='Regression Test Suite',
                verbosity=3
                )
result = runner.run(suite)

Edited : I am using import unittest, and for logging I am using import logging. For HTML runner I am using import HTMLTestRunner

For printing statements on the console, I am using logging.info and logging.debug. If I use print statements using python print, then I am neither getting this output in the console nor in the logs. But for HTML logging, I am having only print statements and stderr.

My query : Is there someway that HTMLTestRunner.HTMLTestRunner will have statements which are printed on the console using logging.debug and logging.info

like image 822
Sumit Avatar asked Dec 21 '17 11:12

Sumit


1 Answers

The HTMLTestRunner module that you are currently using is about 6 years old and is seriously out of date. There are better options - starting from the html-testRunner or, even a better one - pytest with the HTML reporting plugin enabled.

But, if you are ready to patch/change the HTMLTestRunner implementation, here is what we need to do to make the logging work and messages displayed in the report (this is just one way to do it):

  • add a new logger argument to the HTMLTestRunner class constructor and attach a new handler to the logger:

    class HTMLTestRunner(Template_mixin):
        def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None, logger=None):  # CHANGE HERE
            # ...
    
            # CHANGE BELOW
            self.log_capture = None
            if logger:
                self.log_capture = StringIO.StringIO()
    
                ch = logging.StreamHandler(self.log_capture)
                ch.setLevel(logging.DEBUG)
    
                formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
                ch.setFormatter(formatter)
    
                logger.addHandler(ch)
    
  • edit the HEADING_TMPL template and add a placeholder for the logging messages:

    HEADING_TMPL = """<div class='heading'>
    <h1>%(title)s</h1>
    %(parameters)s
    <p class='description'>%(description)s</p>
    Logging output:
    <p class='logs'>%(logs)s</p>
    </div>
    """ # variables: (title, parameters, description)
    
  • change the _generate_heading() method and fill out the logs placeholder:

    heading = self.HEADING_TMPL % dict(
        title = saxutils.escape(self.title),
        parameters = ''.join(a_lines),
        description = saxutils.escape(self.description),
        logs='<br>'.join(self.log_capture.getvalue().split("\n")) if self.log_capture else ""
    )
    
  • don't forget the import logging

Now, if you have, for instance, this kind of test with a logger instance writing log messages in the tests, you can pass the logger into the HTMLTestRunner which would then dump the log messages into the report:

import logging
import unittest

import HTMLTestRunner

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)


class BasicTestCase(unittest.TestCase):
    def test_one(self):
        logger.info('Test message 1!')
        self.assertEqual(1, 1)

    def test_two(self):
        """Extended description"""
        logger.error('Test message 1!')
        self.assertEqual(2, 2)


if __name__ == '__main__':
    import sys
    logging.basicConfig(stream=sys.stderr)

    with open('report.html', 'w') as report_file:
        runner = HTMLTestRunner.HTMLTestRunner(
            stream=report_file,
            title='Test Report',
            description='Regression Test Suite',
            verbosity=3,
            logger=logger
        )

        suite = unittest.TestLoader().loadTestsFromTestCase(BasicTestCase)

        result = runner.run(suite)
        print(result)

Contents of the report.html after running the test:

enter image description here

like image 92
alecxe Avatar answered Oct 13 '22 20:10

alecxe