Test Observability & Engineering effectiveness
“Engineering Effectiveness” has been a central topic of discussion and focus this year
Testing across all interfaces, platforms and architectural components
Product test engineering, Shift-Left testing and digital transformation
Automate tests across all interfaces, platforms and horizontal scaling
Generative AI, Flutter, React Native, Micro-services, Micro-frontends & TestOps
Measure and enhance the efficiency & effectiveness of testing teams & solutions
Offshore Testing Setup as a Service, platform engineering and Modernisation
Integrating Slack for Test Reporting using Python
Publishing results of automated test execution is as vital as running the tests continuously. This helps in building visibility and credibility of test automation within fast-paced agile teams. One of the primary methods in the industry of publishing test reports is to send automated emails with attached reports post each test run.
However, creating & maintaining the code for sending email notifications is time-consuming and tedious. Moreover, sending emails for highly frequent test runs would, almost, be like spamming inboxes and hence, eventually get ignored.
So, we tried to tackle this problem by automating the process of sending the reports using one of the most popular communication medium used across the industry — SLACK.
Now we need to address some questions to facilitate the implementation:
Basically, we can achieve this using the Incoming Webhooks added for respective Slack workspaces
The diagram below shows the workflow of Slack Webhook URL creation; refer to this page for the steps involved in the process.
The following chart shows what happens once we obtain the Webhook URL:
Now let’s address the second question we mentioned above:
We can push the notification to slack using the POST network call with payload representing the slack message.
Slack provides us with a variety of message formats that can be used to compose our own slack message template as required.
Now the question arises,
Post Execution of all test cases.
Generated allure report
Enough of theory and let’s get our hands dirty with code. We have divided the complete code into 3 sections, namely
from datetime import date
class SlackHelperMethods:
@classmethod
def __get_current_date():
"""
Returns:
Date with following format - DD-MM-YYYY
"""
today = date.today()
return f"{today.day}-{today.month}-{today.year}"
@classmethod
def __convert_time_from_milli(millis):
"""
Args:
millis -> milli-seconds
Returns:
Converted time of milli seconds to hour-minute-second format - 1h 03m 23s
"""
construct_time = ""
seconds = int((millis/1000) % 60)
minutes = int((millis/(1000*60)) % 60)
hours = int((millis/(1000*60*60)) % 24)
for [time, param] in zip([hours, minutes, seconds], ["h", "m", "s"]):
if time == 0:
continue
else:
construct_time += f"{time}{param} "
if construct_time == "":
return "Time is less than a second"
return construct_time.strip()
@classmethod
def __helper_to_extract_module_wise_failed_count(cls):
if len(SlackTemplate.RESULTS['module_wise_failure']) == 0:
return "No Module Wise Failures Found"
resulting_string = ""
index = 1
for key, value in SlackTemplate.RESULTS["module_wise_failure"].items():
resulting_string += f"{index+1}. {key}: {value}\n"
return resulting_string
@classmethod
def __get_results_from_allure_report(cls):
# Implementation to extract the details from allure report (or any other reporting tool that you might be utilizing)
class SlackTemplate:
# The following data is extracted from Allure Reports ( NOT HARD CODED )
RESULTS = SlackHelperMethods.__get_results_from_allure_report()
@classmethod
def __slack_header(cls):
return [
{
"type": "header",
"text": {
"type": "plain_text",
"text": f"ENV - {SlackTemplate.RESULTS['env']} - Test Execution Summary ( {SlackTemplate.RESULTS['platform']} ) - {SlackHelperMethods.__get_current_date()}",
}
}
]
@classmethod
def __slack_body(cls):
return [
{
"text": f"Passed Count: *{SlackTemplate.RESULTS['passed']}*",
"mrkdwn_in": [
"text"
],
"color": "good"
},
{
"text": f"Broken Count: *{SlackTemplate.RESULTS['broken']}*",
"mrkdwn_in": [
"text"
],
"color": "warning"
},
{
"text": f"Failed Count: *{SlackTemplate.RESULTS['failed']}*",
"mrkdwn_in": [
"text"
],
"color": "danger"
},
{
"text": "",
"footer": f"_Total Execution Time: *{SlackHelperMethods.__convert_time_from_milli(SlackTemplate.RESULTS['total_execution_time'])}*_",
"color": "#87ceeb",
"mrkdwn_in": [
"footer"
]
},
{
"title": "Module Wise Failed / Broken Count",
"color": "danger",
"text": f"{SlackHelperMethods.__helper_to_extract_module_wise_failed_count()}",
"mrkdwn_in": [
"text"
]
}
]
@staticmethod
def constructed_message_format():
return {
"blocks": SlackTemplate.__slack_header(),
"attachments": SlackTemplate.__slack_body()
}
import requests
import json
WEBHOOK_URL = "https://hooks.slack.com/services/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"
class SlackNotification:
@staticmethod
def send_slack_notification():
response = requests.post(
WEBHOOK_URL, data=json.dumps(
SlackTemplate.constructed_message_format()),
headers={'Content-Type': 'application/json'}
)
return response
if __name__ == "__main__":
SlackNotification.send_slack_notification()
Below is the final message sent which contains details like environment (QA, PRE-PROD or PROD), platform name (API, Mobile or Web), number of test cases passed, failed & broken, total time of execution, date of execution, module wise test case failure count that were extracted from reports
With this approach, we were successful in sending the Slack message to the respective channels using the Webhooks that connects our test framework and slack.
Hope our blog helps and reduces the time to spend on integrating Slack with your application.
Happy Learning!!!
“Engineering Effectiveness” has been a central topic of discussion and focus this year
With us, you’re not just a part of a company; you’re part of a movement dedicated to pushing boundaries, breaking barriers, and achieving the extraordinary.
Otaku 2.0 sought to redefine the way we approach testing, celebrate the spirit of innovation, and pave the way for a brighter future in tech.