美文网首页
RobotFramework二次开发——实时日志

RobotFramework二次开发——实时日志

作者: 点点寒彬 | 来源:发表于2017-12-06 14:04 被阅读967次

    背景

    基于RobotFramework的二次开发,少不了要打印实时日志出来,比如广泛应用的工具ride中,在执行用例时会把执行过程中的log全部打印出来,如果二次开发的时候,执行用例只能静默等待执行完毕,那只能算是一个半成品。

    结果在最后,不想看过程的可以直接跳到最后

    思路

    RobotFramework的日志有好几种,一个是执行后的log文件,这个文件可以作为数据留存,但是没办法实时获取,因为文件是在执行完毕之后才生成的。

    第二种是命令行执行时留存的记录,我们在命令行执行RobotFramework的时候,会有很多日志打印出来,但是,这个日志经过观察,可获取的信息少,而且实时的程度不够

    第三种是类似ride的日志显示,这种目前来看是最友好的显示方式,因此目标是用ride的实现方式来实现此功能。

    开工前准备

    应该来说,基于ride的方式是比较麻烦的,我用Google搜了一下这方面的资料,几乎为0,想要折腾出来,就只能自己去看ride的源码,所以,准备工作就是要吧ride的源码拿出来。

    定位功能

    首先用ride执行一条用例,可以发现,ride执行的时候是以命令行的形式来执行的,如下所示:

    pybot.bat  -v ENV:PRE -v PID:30911 --argumentfile c:\users\hetong~1\appdata\local\temp\RIDExvh51x.d\argfile.txt --listener C:\Python27\lib\site-packages\robotide\contrib\testrunner\TestRunnerAgent.py:64337:False E:\本地脚本
    

    执行的功能后续会新增文章来说明,这里我们看这一段:

    --listener C:\Python27\lib\site-packages\robotide\contrib\testrunner\TestRunnerAgent.py:64337:False E:\本地脚本
    

    可以发现一个东西,执行的时候,加了一个--listener的参数,这个参数用到了ride里面的一个叫TestRunnerAgent.py的文件,后面还带了两个参数,分别是64337False,这个时候,再检查一下本地的端口情况。

    image

    这个端口被打开了,并且处于Listening状态,那么就可以推断,这应该是一个本地的socket通讯。有了这个发现,就可以去源码全局搜索socket了。在testrunner.py文件中发现了这样的代码:

        def _send_socket(self, data):
            if self._port is None:
                return  # Silent failure..
            sock = None
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect(('localhost', self._port))
                sock.send(data)
            finally:
                sock.close()
    

    和这样的代码:

    # The following two classes implement a small line-buffered socket
    # server. It is designed to run in a separate thread, read data
    # from the given port and update the UI -- hopefully all in a
    # thread-safe manner.
    class RideListenerServer(SocketServer.TCPServer):
        """Implements a simple line-buffered socket server"""
        allow_reuse_address = True
        def __init__(self, RequestHandlerClass, callback):
            SocketServer.TCPServer.__init__(self, ("",0), RequestHandlerClass)
            self.callback = callback
    
    class RideListenerHandler(SocketServer.StreamRequestHandler):
        def handle(self):
            decoder = TestRunnerAgent.StreamHandler(self.request.makefile('r'))
            while True:
                try:
                    (name, args) = decoder.load()
                    self.server.callback(name, *args)
                except (EOFError, IOError):
                    # I should log this...
                    break
    
    

    注释说的很明白了,这两个类就用来监听执行的日志,并且根据端口来更新UI。

    这个时候再来看看命令中的TestRunnerAgent.py

        def start_test(self, name, attrs):
            self._send_socket("start_test", name, attrs)
    
        def end_test(self, name, attrs):
            self._send_socket("end_test", name, attrs)
    
        def start_suite(self, name, attrs):
            self._send_socket("start_suite", name, attrs)
    
        def end_suite(self, name, attrs):
            self._send_socket("end_suite", name, attrs)
    

    这里从字面意思就能看出来,是在发送socket通讯,在TestRunnerAgent初始化的时候,就开启了socket通讯。

    重写监听类

    从上面我们就可以得出,ride是通过--listener方法来监听实时数据,然后以socket的方式推给UI端,然后UI端再试试更新界面。那么我们只要把监听的数据拿出来,就可以以自己的方式来随意模拟一个ride的实现。第一步就是重写监听类

    打开RobotFrameworkUser Guide我们可以找到Listener参数的相关解释,点我直达。我们可以它的API说明。根据说明文档,我这里简单写了一个可用的类,如有需要,可以根据文档自己重写。

    # ecoding=utf-8
    # Author: Sven_Weng
    # Email : sven_weng@wengyb.com
    # Web   : http://wybblog.applinzi.com
    
    
    class RobotListener(object):
        ROBOT_LISTENER_API_VERSION = 2
    
        def start_suite(self, name, args):
            print "Starting Suite : " + name + "  " + args['source']
    
        def start_test(self, name, args):
            print "Starting test : " + name
            if args['template']:
                print 'Template is : ' + args['template']
    
        def end_test(self, name, args):
            print "Ending test:  " + args['longname']
            print "Test Result is : " + args['status']
            print "Test Time is: " + str(args['elapsedtime'])
    
        def log_message(self, message):
            print message['timestamp'] + " :   " + message['level'] + " : " + message['message']
    

    执行结果如下:

    image

    打印日志会和命令返回的结果重叠在一起,如果要看到完整的日志信息,可以把结果导出到一个文件。

    相关文章

      网友评论

          本文标题:RobotFramework二次开发——实时日志

          本文链接:https://www.haomeiwen.com/subject/flnkixtx.html