Create PDF test-reports with Python

With only two python libraries and some line of codes, you are able to create very nice test-reports in PDF format. This tutorial should give you a hint. Feel free to improve with your requirements.

Preconditions

Example

matplotlib==1.4.3
reportlab==3.2.0
# -*- coding: utf-8 -*-

import time
import matplotlib.pyplot as plt

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_JUSTIFY
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch


class CreateTestReport(object):
    """Example test report class"""

    def __init__(self, test_results, file_name):
        """Constructor method"""
        self.data = test_results
        self.file_name = file_name

        self.story = list()

        self.styles = getSampleStyleSheet()
        self.styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))

    def __create_overview(self):
        """Create overview graphic and pdf content"""
        requests = list()
        duration = list()

        for lists in self.data:
            requests.append(lists[0])
            duration.append(lists[1])

        plt.plot(duration)

        plt.xlabel('http requests')
        plt.ylabel('response time')
        plt.xticks(range(len(duration)), requests)

        plt.grid(True)
        plt.savefig('overview.png')

        text = '<font size=18>Overview</font>'
        self.story.append(Paragraph(text, self.styles["Heading2"]))
        picture = Image('overview.png', 6*inch, 4*inch, hAlign='LEFT')
        self.story.append(picture)

        text = '<font size=12>Lorem ipsum dolor sit amet, <br/>\
        consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt \
        ut labore et dolore magna aliquyam erat, sed diam voluptua.<br/>\
        At vero eos et accusam et justo duo dolores et ea rebum. <br/>\
        Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum \
        dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing \
        elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore \
        magna aliquyam erat, sed diam voluptua. <br/>\
        At vero eos et accusam et justo duo dolores et ea rebum. <br/>\
        Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum \
        dolor sit amet.</font>'
        self.story.append(Paragraph(text, self.styles["Normal"]))

        self.story.append(Spacer(1, 192))

    def __create_round_trips(self):
        """Create round trip graphics and pdf content"""

        for lists in self.data:
            text = '<font size=18>%s: %s HTTP/1.1</font>' % (lists[3],
                                                             lists[4])
            self.story.append(Paragraph(text, self.styles["Heading2"]))

            text = '<font size=12>Status Code: %s</font>' % lists[2]
            self.story.append(Paragraph(text, self.styles["Normal"]))
            self.story.append(Spacer(1, 12))

            file_name = 'request_' + str(lists[0]) + '.png'
            title = 'Request Circle (' + str(lists[1]) + ' sec.)'
            plt.figure(figsize=(4, 4))
            plt.title(title)
            values = lists[5]
            labels = ['Request', 'Server', 'Response']
            plt.pie(values, labels=labels)
            plt.savefig(file_name)

            picture = Image(file_name, 2.5*inch, 2.5*inch, hAlign='LEFT')
            self.story.append(picture)

            self.story.append(Spacer(1, 24))

    def create_pdf(self, report_title, author, base_url, margins):
        """Create PDF document"""

        formatted_time = time.ctime()
        pdf = SimpleDocTemplate(self.file_name,
                                pagesize=letter,
                                title=report_title,
                                author=author,
                                topMargin=margins[0],
                                leftMargin=margins[1],
                                rightMargin=margins[2],
                                bottomMargin=margins[3])

        # Add headline, created date/time and author
        text = '<font size=24>%s</font>' % report_title
        self.story.append(Paragraph(text, self.styles["Heading1"]))
        self.story.append(Spacer(1, 12))

        text = '<font size=10>%s<br/>by %s<br/>%s</font>' % (formatted_time,
                                                             author,
                                                             base_url)
        self.story.append(Paragraph(text, self.styles["Italic"]))
        self.story.append(Spacer(1, 24))

        # Add overview
        self.__create_overview()

        # Add results
        self.__create_round_trips()

        # Create and store report
        pdf.build(self.story)


if __name__ == '__main__':
    # some test result data
    data = ([1, 0.5, 200, 'GET', '/api/getUser', [40, 40, 20]],
            [2, 0.75, 200, 'POST', '/api/createUser', [50, 30, 20]],
            [3, 0.25, 404, 'PUT', '/api/updateUser', [50, 25, 25]],
            [4, 2, 301, 'GET', '/api/Logout', [25, 50, 25]],
            [5, 0.25, 200, 'POST', '/api/Login', [45, 35, 20]])

    # create report
    CREATE = CreateTestReport(data, 'TestReport.pdf')
    CREATE.create_pdf('Example Test Report',
                      'Lupin3000',
                      'http://example.com',
                      [20, 20, 20, 10])

You can call it simply by

# execute without compile
$ python -B ExampleReport.py