5

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

Sumit
  • 1,953
  • 6
  • 32
  • 58
  • 3
    I'd love to try to help, but I don't see enough information to go on. Which `HTMLTestRunner` are you using: https://pypi.python.org/pypi/HTMLTestRunner, or https://pypi.python.org/pypi/html-testRunner/, or something else? Show us an example fixture, with an example of the logger statements, what you want to see from `HTMLTestRunner`, and what you actually see. – Jim DeLaHunt Dec 27 '17 at 07:02
  • 1
    @JimDeLaHunt: I have edited the question. Please let me know if it is still unclear – Sumit Dec 29 '17 at 07:09
  • The additional detail helps. But please also show us an actual test case, with actual logging and `print` statements. Show us the output you get, and the output you expect. – Jim DeLaHunt Dec 29 '17 at 08:35
  • "print statements" don't do anything special. They just write to stdout. What you want is adding a `logging` handler so that it prints everything on stdout (you may not want to enable this during normal execution of your program, just tests) – Bakuriu Jan 02 '18 at 18:07

1 Answers1

7

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

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • I tried your solution it worked. But all the logging info output is getting printed outside the table. Like in your case too, you have 2 test cases but logging info is getting printed at the top of the table. Is it possible to get the logging.info of respective test case in the table. Example: if I click detail of basicTestCase, then logging info related to test case 1 should be displayed in testcase1 detail. same for test case-2. Is it possible – Sumit Jan 03 '18 at 09:48
  • @Nitesh yeah, put it into the header for sample purposes. To have logs in the table rows, you should first of all modify the [`REPORT_CLASS_TMPL` template](https://github.com/tungwaiyip/HTMLTestRunner/blob/master/HTMLTestRunner.py#L462) to allow for logs written into a table row - you would need a placeholder for logs. Then, you would need to fill out the placeholder [here](https://github.com/tungwaiyip/HTMLTestRunner/blob/master/HTMLTestRunner.py#L740). Okay, but that's just a preparation step. – alecxe Jan 03 '18 at 22:11
  • @Nitesh then, you would need to figure out a way to group logging messages per test method. You can probably construct log message strings so that they would contain a test method name - check out [this thread](https://stackoverflow.com/q/10973362/771848). Then, you would need the output of the `self.log_capture.getvalue().split("\n")` to be parsed and grouped per test method. I hope you can understand my thinking here. I suggest you start a new topic on SO if you need help with implementing the idea. That said, again, switching to a more modern reporter would be easier. Thanks. – alecxe Jan 03 '18 at 22:14