Jenkins 如何在Slack中显示Robotframework测试结果摘要

Jenkins 如何在Slack中显示Robotframework测试结果摘要,jenkins,jenkins-plugins,robotframework,slack-api,slack,Jenkins,Jenkins Plugins,Robotframework,Slack Api,Slack,我使用RobotFramework在jenkins上执行测试,并使用slack插件在slack上显示测试执行状态 Total Tests : 50 Total Passed : 40 Total Failed : 10 我读了一篇关于在slack上显示cucumber测试结果的好文章,但找不到robotframework的任何文档。 松弛通知与框架和工具无关,这意味着任何适用于cucumber或其他系统的内容都适用于Robot框

我使用RobotFramework在jenkins上执行测试,并使用slack插件在slack上显示测试执行状态

           Total Tests : 50
           Total Passed : 40
           Total Failed : 10
我读了一篇关于在slack上显示cucumber测试结果的好文章,但找不到robotframework的任何文档。

松弛通知与框架和工具无关,这意味着任何适用于cucumber或其他系统的内容都适用于Robot框架

它们提供了一个用于发送消息的方法,我建议它既简单又功能强大——对特定负载的http POST负载在您选择的通道中显示为消息,并支持格式、附件等

下面是一个简单的例子,摘自引用的文档页面:

curl -X POST \
--data-urlencode 'payload={"text": "This is posted to #general and comes from *monkey-bot*.", "channel": "#general", "link_names": 1, "username": "monkey-bot", "icon_emoji": ":monkey_face:"}' \
 https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
最简单的选项是“Slackbot遥控器”,我个人使用它来发送每日的sanity运行通知;简言之,您可以为一个帐户启用它,通过向端点发送POST,一条消息被传递到目标通道——没有json,没有花哨的东西。例如:

curl --data "The full run finished against \`$current_version\`, with $number_of_failed failed cases; full results at http://the_internal_reporting_server/report.html"  \
$'https://yourdomain.slack.com/services/hooks/slackbot?token=XXXXXXXXXXXXXXXXXXXXXXXX&channel=%23automation-results'
如您所见,消息体支持简单的格式设置(转义、*表示粗体等),并且http链接在客户端中自动突出显示。要发送到的通道是端点的参数;再简单不过了:)


这个特定的例子来自一个bash脚本,因此其中的变量。这将导致-如何获取输出数据

这里有两个选项,
robot
/
pybot
运行程序和
reboot
结果解析器将失败案例的数量返回为RC(返回代码),可以很容易地获得它(bash中的
$?
是最后执行的命令/程序的RC)

更“高级”的是解析output.xml文件——它相当简单且结构良好。
有一个顶级标记
,用于保存总体结果,例如:

<total>
<stat fail="22" pass="849">Critical Tests</stat>
<stat fail="22" pass="849">All Tests</stat>
</total>

关键测试
所有测试
因此,如果您解析(或grep)它的“所有测试”
子级,您可以从中获得失败/通过和总计数;运行时也是如此

最后,对于总控制,可以使用 和包,提供对结果的完全访问,从而生成所需的任何输出



我在回答你的问题时没有提到Jenkins Slack插件,原因有两点:a)我没有访问它的权限(但想起来,我应该有一天尝试一下),b)它很可能在相同的Slack api功能上提供了方便的包装器,c)http api是通用的,因此,可以在公司的任何流程中使用。

对于遇到类似问题的任何其他人,这里是我为这种情况找到的解决方案

我利用robotframework中的可用功能来触发我的消息。使用close方法作为slack消息的触发器,使用end_test和end_suite方法在字典中跟踪测试和套件结果

robot命令如下所示,URL和通道在侦听器路径(本例中为RobotListener.py)后用分号分隔符传递:

我的侦听器的代码如下所示:

import os
import json
import requests

from collections import Counter

class RobotListener(object):
    ROBOT_LISTENER_API_VERSION = 3
    HEADERS = {'Content-Type': 'application/json'}

    def __init__(self, webhook_url, channel, icon=':squirrel:'):
        self.webhook_url = webhook_url
        self.channel = channel
        self.icon = icon
        self._suite_status = dict()
        self._test_status = dict()

    def end_test(self, data, result):
        self._test_status[data] = result.passed

    def end_suite(self, data, result):
        self._suite_status[data] = self._test_status
        self._test_status = dict()

    def close(self):
        attachments = self._build_overall_results_attachment()
        self._send_slack_request(attachments)

    def _build_overall_results_attachment(self):
        results = {k: v for test_results in self._suite_status.values() for k, v in test_results.iteritems()}
        return [
        {
            "pretext": "*All Results*",
            "color": "good" if all(results.values()) else "danger",
            "mrkdwn_in": [
                "pretext"
            ],
            "fields": [
                {
                    "title": "Tests Passed",
                    "value": Counter(results.values())[True],
                    "short": True
                },
                {
                    "title": "Total Tests",
                    "value": len(results.values()),
                    "short": True
                },
                {
                    "title": "Pass Percentage",
                    "value": "{0:.2f}%".format(float((Counter(results.values())[True])/float(len(results))) * 100),
                    "short": True
                },
                {
                    "title": "Results",
                    "value": os.environ['bamboo_resultsUrl'],
                    "short": True} if os.environ.get('bamboo_resultsUrl', False) else None,
            ],
        }]

    def _send_slack_request(self, attachments):
        try:
            data = {"channel": "@{0}".format(self.channel), "username": "ufgatestbot", "attachments": attachments,
                "icon_emoji": self.icon}

            response = requests.post(url=self.webhook_url, data=json.dumps(data), headers=self.HEADERS)
            if response.status_code != 200:
                print 'Error in sending data to Slack - Status Code: {0}, Text: {1}'.format(response.status_code,
                                                                                        response.content)
        except Exception as e:
            print str(e)
目前,它被配置为提供指向Atlassain竹子测试结果的链接,但可以轻松更新为指向Jenkins测试结果的链接

import os
import json
import requests

from collections import Counter

class RobotListener(object):
    ROBOT_LISTENER_API_VERSION = 3
    HEADERS = {'Content-Type': 'application/json'}

    def __init__(self, webhook_url, channel, icon=':squirrel:'):
        self.webhook_url = webhook_url
        self.channel = channel
        self.icon = icon
        self._suite_status = dict()
        self._test_status = dict()

    def end_test(self, data, result):
        self._test_status[data] = result.passed

    def end_suite(self, data, result):
        self._suite_status[data] = self._test_status
        self._test_status = dict()

    def close(self):
        attachments = self._build_overall_results_attachment()
        self._send_slack_request(attachments)

    def _build_overall_results_attachment(self):
        results = {k: v for test_results in self._suite_status.values() for k, v in test_results.iteritems()}
        return [
        {
            "pretext": "*All Results*",
            "color": "good" if all(results.values()) else "danger",
            "mrkdwn_in": [
                "pretext"
            ],
            "fields": [
                {
                    "title": "Tests Passed",
                    "value": Counter(results.values())[True],
                    "short": True
                },
                {
                    "title": "Total Tests",
                    "value": len(results.values()),
                    "short": True
                },
                {
                    "title": "Pass Percentage",
                    "value": "{0:.2f}%".format(float((Counter(results.values())[True])/float(len(results))) * 100),
                    "short": True
                },
                {
                    "title": "Results",
                    "value": os.environ['bamboo_resultsUrl'],
                    "short": True} if os.environ.get('bamboo_resultsUrl', False) else None,
            ],
        }]

    def _send_slack_request(self, attachments):
        try:
            data = {"channel": "@{0}".format(self.channel), "username": "ufgatestbot", "attachments": attachments,
                "icon_emoji": self.icon}

            response = requests.post(url=self.webhook_url, data=json.dumps(data), headers=self.HEADERS)
            if response.status_code != 200:
                print 'Error in sending data to Slack - Status Code: {0}, Text: {1}'.format(response.status_code,
                                                                                        response.content)
        except Exception as e:
            print str(e)