{"id":11927,"date":"2019-12-23T06:31:00","date_gmt":"2019-12-23T11:31:00","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=11927"},"modified":"2021-09-07T01:13:46","modified_gmt":"2021-09-07T05:13:46","slug":"email-your-pytest-results-as-html-report","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/email-your-pytest-results-as-html-report\/","title":{"rendered":"Email your pytest results as html report"},"content":{"rendered":"<p>We have noticed that sometimes we want to see test results in our email inbox even though good reporting tools are being used. We at <a href=\"https:\/\/qxf2.com\/\" target=\"_blank\" rel=\"noopener\">Qxf2 Services<\/a>, use pytest as our test runner. A simple utility email_pytest_reports.py has been added to our framework which can send pytest results as simple HTML reports. This blog is on how we built an email utility to send pytest results to any email address.<\/p>\n<hr \/>\n<h3>Steps to build and run the utility<\/h3>\n<p style=\"text-align: left;\"><strong>Step 1: Created a email_conf to get the email details <\/strong><br \/>\nYou can add the email credentials, sender\u00a0and target details in email_conf.py<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_conf.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-11930\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_conf-300x157.png\" alt=\"\" width=\"663\" height=\"347\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_conf-300x157.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_conf-768x401.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_conf.png 985w\" sizes=\"auto, (max-width: 663px) 100vw, 663px\" \/><\/a><\/p>\n<p><strong>Step 2:\u00a0Install pytest-html plugin:<\/strong><\/p>\n<div>\n<pre lang=\"python\"> pip install pytest-html<\/pre>\n<\/div>\n<p><strong>Step 3: Added the required functions to send email in email_pytest_report util file<\/strong><br \/>\nWe need to write functions to create the html report, make it as an attachment and finally send the email with the attachment.<\/p>\n<p>a. Creating html report is accomplished by <strong>get_test_report_data<\/strong> function<\/p>\n<div>\n<pre lang=\"python\"> \r\ndef get_test_report_data(self,html_body_flag= True,report_file_path= 'default'):\r\n        \"get test report data from pytest_report.html or pytest_report.txt or from user provided file\"\r\n        if html_body_flag == True and report_file_path == 'default':\r\n            #To generate pytest_report.html file use following command e.g. py.test --html = log\/pytest_report.html\r\n            test_report_file = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','log','pytest_report.html'))#Change report file name &amp; address here\r\n        elif html_body_flag == False and report_file_path == 'default':\r\n            #To generate pytest_report.log file add \"&gt;pytest_report.log\" at end of py.test command e.g. py.test -k example_form -r F -v &gt; log\/pytest_report.log\r\n            test_report_file = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','log','pytest_report.log'))#Change report file name &amp; address here\r\n        else:\r\n            test_report_file = report_file_path\r\n        #check file exist or not\r\n        if not os.path.exists(test_report_file):\r\n            raise Exception(\"File '%s' does not exist. Please provide valid file\"%test_report_file)\r\n            \r\n        with open(test_report_file, \"r\") as in_file:\r\n            testdata = \"\"\r\n            for line in in_file:\r\n                testdata = testdata + '\\n' + line\r\n\r\n        return testdata\r\n<\/pre>\n<\/div>\n<p>b. Get and attach the report file<\/p>\n<div>\n<pre lang=\"python\"> \r\ndef get_attachment(self,attachment_file_path = 'default'):\r\n        \"Get attachment and attach it to mail\"\r\n        if attachment_file_path == 'default':\r\n            #To generate pytest_report.html file use following command e.g. py.test --html = log\/pytest_report.html\r\n            attachment_report_file = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','log','pytest_report.html'))#Change report file name &amp; address here\r\n        else:\r\n            attachment_report_file = attachment_file_path\r\n        #check file exist or not\r\n        if not os.path.exists(attachment_report_file):\r\n            raise Exception(\"File '%s' does not exist. Please provide valid file\"%attachment_report_file)\r\n\r\n        # Guess encoding type\r\n        ctype, encoding = mimetypes.guess_type(attachment_report_file)\r\n        if ctype is None or encoding is not None:\r\n            ctype = 'application\/octet-stream'  # Use a binary type as guess couldn't made\r\n            \r\n        maintype, subtype = ctype.split('\/', 1)\r\n        if maintype == 'text':\r\n            fp = open(attachment_report_file)\r\n            attachment = MIMEText(fp.read(), subtype)\r\n            fp.close()\r\n        elif maintype == 'image':\r\n            fp = open(attachment_report_file, 'rb')\r\n            attachment = MIMEImage(fp.read(), subtype)\r\n            fp.close()\r\n        elif maintype == 'audio':\r\n            fp = open(attachment_report_file, 'rb')\r\n            attachment = MIMEAudio(fp.read(), subtype)\r\n            fp.close()\r\n        else:\r\n            fp = open(attachment_report_file, 'rb')\r\n            attachment = MIMEBase(maintype, subtype)\r\n            attachment.set_payload(fp.read())\r\n            fp.close()\r\n            # Encode the payload using Base64\r\n            encoders.encode_base64(attachment)\r\n        # Set the filename parameter\r\n        attachment.add_header('Content-Disposition',\r\n                   'attachment',\r\n                   filename=os.path.basename(attachment_report_file))\r\n        \r\n        return attachment\r\n\r\n<\/pre>\n<\/div>\n<p>c. Finally write the send email function like below<br \/>\nTo run the utility using python command and to see the full file, please check the <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\/blob\/master\/utils\/email_pytest_report.py\" target=\"_blank\" rel=\"noopener\">file<\/a> in our framework<\/p>\n<div>\n<pre lang=\"python\">  \r\ndef send_test_report_email(self,html_body_flag = True,attachment_flag = False,report_file_path = 'default'):\r\n        \"send test report email\"\r\n        #1. Get html formatted email body data from report_file_path file (log\/pytest_report.html) and do not add it as an attachment\r\n        if html_body_flag == True and attachment_flag == False:\r\n            testdata = self.get_test_report_data(html_body_flag,report_file_path) #get html formatted test report data from log\/pytest_report.html\r\n            message = MIMEText(testdata,\"html\") # Add html formatted test data to email\r\n            \r\n        #2. Get text formatted email body data from report_file_path file (log\/pytest_report.log) and do not add it as an attachment\r\n        elif html_body_flag == False and attachment_flag == False:\r\n            testdata = self.get_test_report_data(html_body_flag,report_file_path) #get html test report data from log\/pytest_report.log\r\n            message  = MIMEText(testdata) # Add text formatted test data to email\r\n\r\n        #3. Add html formatted email body message along with an attachment file\r\n        elif html_body_flag == True and attachment_flag == True:\r\n            message = MIMEMultipart()\r\n            #add html formatted body message to email\r\n            html_body = MIMEText('''Hello,Please check the attachment to see test built report.<strong>Note: For best UI experience, download the attachment and open using Chrome browser.<\/strong>''',\"html\") # Add\/Update email body message here as per your requirement\r\n            message.attach(html_body)\r\n            #add attachment to email\r\n            attachment = self.get_attachment(report_file_path)\r\n            message.attach(attachment)\r\n            \r\n        #4. Add text formatted email body message along with an attachment file\r\n        else:\r\n            message = MIMEMultipart()\r\n            #add test formatted body message to email\r\n            plain_text_body = MIMEText('''Hello,\\n\\tPlease check attachment to see test built report.\r\n                                       \\n\\nNote: For best UI experience, download the attachment and open  using Chrome browser.''')# Add\/Update email body message here as per your requirement\r\n            message.attach(plain_text_body)\r\n            #add attachment to email\r\n            attachment = self.get_attachment(report_file_path)\r\n            message.attach(attachment)\r\n        \r\n        message['From'] = self.sender\r\n        message['To'] = ', '.join(self.targets)\r\n        message['Subject'] = 'Script generated test report' # Update email subject here\r\n\r\n        #Send Email\r\n        server = smtplib.SMTP_SSL(self.smtp_ssl_host, self.smtp_ssl_port)\r\n        server.login(self.username, self.password)\r\n        server.sendmail(self.sender, self.targets, message.as_string())\r\n        server.quit()<\/pre>\n<\/div>\n<p>d. Conftest.py changes<\/p>\n<p><span>In\u00a0<\/span><a title=\"\" href=\"https:\/\/docs.pytest.org\/en\/latest\/\">pytest<\/a><span>, there is a provision to run scripts\/code after the execution of all tests.\u00a0<\/span><code>pytest_sessionfinish<\/code><span>\u00a0plugin hook executes after the whole test run finishes. So we used\u00a0<\/span><code>pytest_sessionfinish<\/code><span>\u00a0plugin hook\u00a0auto-email the report every time you run the test. To achieve this we added a method\u00a0<strong>pytest_terminal_summary<\/strong>\u00a0in conftest.<\/span>\u00a0This method will be run only after tests are exited which means after the execution of <strong>self.driver.quit(),<\/strong> this method will be called.<\/p>\n<pre lang=\"python\">\r\n#Contents of conftest.py\r\nfrom utils.email_pytest_report import Email_Pytest_Report\r\n\r\n#Test arguments\r\n@pytest.fixture\r\ndef email_pytest_report(request):\r\n\"pytest fixture for device flag\"\r\nreturn request.config.getoption(\"--email_pytest_report\")\r\n \r\n#Command line options:\r\nparser.addoption(\"--email_pytest_report\",\r\ndest=\"email_pytest_report\",\r\nhelp=\"Email pytest report: Y or N\",\r\ndefault=\"N\")\r\n\r\ndef pytest_terminal_summary(terminalreporter, exitstatus):\r\n    \"add additional section in terminal summary reporting.\"\r\n    if not hasattr(terminalreporter.config, 'workerinput'):\r\n        if terminalreporter.config.getoption(\"--email_pytest_report\").lower() == 'y':\r\n            #Initialize the Email_Pytest_Report object\r\n            email_obj = Email_Pytest_Report()\r\n            # Send html formatted email body message with pytest report as an attachment\r\n            email_obj.send_test_report_email(html_body_flag=True,attachment_flag=True,report_file_path= 'default')\r\n<\/pre>\n<p><strong>Step 4: Running the utility<\/strong><br \/>\nYou can run the test using below command<\/p>\n<pre lang=\"python\">pytest --email_pytest_report Y --html=log\/pytest_report.html --self-contained-html --capture=sys\r\n<\/pre>\n<p>After running the command you will see console output as shown below and an email with an HTML report attached.<\/p>\n<p><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_pytest_report.v2-1.png\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-11994 aligncenter\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_pytest_report.v2-1-300x47.png\" alt=\"\" width=\"882\" height=\"138\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_pytest_report.v2-1-300x47.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_pytest_report.v2-1-768x121.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2019\/12\/email_pytest_report.v2-1-1024x161.png 1024w\" sizes=\"auto, (max-width: 882px) 100vw, 882px\" \/><\/a><\/p>\n<p>I hope this blog has helped you get started with emailing your pytest reports.<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>We have noticed that sometimes we want to see test results in our email inbox even though good reporting tools are being used. We at Qxf2 Services, use pytest as our test runner. A simple utility email_pytest_reports.py has been added to our framework which can send pytest results as simple HTML reports. This blog is on how we built an [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38,107],"tags":[],"class_list":["post-11927","post","type-post","status-publish","format-standard","hentry","category-automation","category-pytest"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11927","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=11927"}],"version-history":[{"count":25,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11927\/revisions"}],"predecessor-version":[{"id":15518,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/11927\/revisions\/15518"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=11927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=11927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=11927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}