使用QT4S开源框架做云api的自动化测试(二)

以下是腾讯的QTA自动化框架

QTAF(自动化基础库): https://github.com/Tencent/QTAF
QT4A( Android UI自动化): https://github.com/Tencent/QT4a
QT4i( iOS UI自动化):https://github.com/Tencent/QT4i
QT4W(支持多种平台的Web自动化):https://github.com/tencent/qt4w
QT4S(后台测试自动化框架):https://github.com/qtacore/QT4S

本文的代码来源于https://github.com/qtacore/QT4SDemoProj,

这里只是针对该源码做简要的分析,实际项目使用还得根据情况来。

demo工程的层级结构如下图所示:

要介绍的重点是hello_test.py中通过调用服务接口的方式来做自动化测试,如下图中红色框框所示

# encoding: utf-8

from testbase.testcase import TestCase
from lib.hello_lib import HelloChannel, HelloService, HelloRequest
from server.hello_server import HelloTcpServer

import threading
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


class HelloTestBase(TestCase):
    '''HelloTest基类
    '''

    def add_cleanup(self, callee, *args, **kwargs):
        # 添加关闭通道的方法 HelloChannel.close(),最后在post_test中调用
        self.clean_ups.append((callee, args, kwargs))

    def pre_test(self):
        self.clean_ups = []
        # --------------------------------------
        self.start_step('先启动一个多线程tcp服务')
        self.server = HelloTcpServer()
        threading.Thread(target=self.server.serve_forever).start()

    def post_test(self):
        # --------------------------------------
        self.start_step('关闭通道链接')
        for clean_up in self.clean_ups:
            try:
                callee, args, kwargs = clean_up
                # 调用关闭通道的方法 HelloChannel.close()
                callee(*args, **kwargs)
            except:
                self.log_info("invoke %s with %s and %s failed" % (callee, str(args), str(kwargs)))

    def clean_test(self):
        # --------------------------------------
        self.start_step('关闭tcp服务,这个可能需要2分钟左右')
        super(HelloTestBase, self).clean_test()
        self.server.shutdown()

 

 hello_lib.py封装的是对外提供的HelloService接口服务,testcase里面可直接调用。

# -*- coding: utf-8 -*-
'''
示例lib层,这里用到的都是qt4s的框架层要求定义,
可以通过注释其中的代码,从报错的堆栈信息进入底层代码
'''

from qt4s.channel.sock import SocketChannel, RequestBase, ResponseBase
from qt4s.message.definition import Field, String, Uint32
from qt4s.message.serializers.binary import BinarySerializer
from qt4s.service import Service, Method


class HelloResponse(ResponseBase):
    """hello response definition
    """
    _struct_ = [
        Field('len', Uint32),
        Field('seq', Uint32),
        Field('result', String, byte_size=0)
    ]
    _serializer_ = BinarySerializer()
    _length_field_ = "len"

    def get_sequence_id(self):
        return self.seq


class HelloRequest(RequestBase):
    """hello request definition
    """
    _struct_ = [
        Field('len', Uint32),
        Field('seq', Uint32),
        Field('username', String, byte_size=0)
    ]
    _serializer_ = BinarySerializer()
    _length_field_ = "len"
    response_class = HelloResponse

    def get_sequence_id(self):
        return self.seq

    def pre_process(self, channel):
        self.seq = channel.create_seq()


class HelloChannel(SocketChannel):
    '''hello channel
    '''
    request_class = HelloRequest

    def call_method(self, method_name, req, rsp_cls, timeout):
        if method_name == "hello":
            print "Client send message {}".format(req)
            response = self.send(req)
            return response


class HelloService(Service):
    '''对外发布的服务,供客户端访问
    '''
    _methods_ = [
         Method("hello", HelloRequest, HelloResponse)
    ]


if __name__ == '__main__':
    pass

hello_server.py里面ThreadingTCPServer是一个异步多线程的tcp服务器,用来处理客户端发起的tcp通信交互

# -*- coding: utf-8 -*-
'''异步多线程的TCP服务器
'''

import socket
import select
import struct
import traceback

from SocketServer import TCPServer, ThreadingTCPServer, StreamRequestHandler
from qt4s.message.serializers.binary import BinarySerializer
from lib.hello_lib import HelloResponse, HelloRequest


class RequestHandler(StreamRequestHandler):
    '''定义连接内部的处理过程
    '''

    def handle(self):
        recvbuf = ""
        try:
            while True:
                can_read, _, _ = select.select([self.connection, ], [], [], 1)
                if self.connection in can_read:
                    buf = self.connection.recv(1000)
                    if not buf:
                        break
                    recvbuf += buf
                    buflen = len(recvbuf)
                    if buflen >= 4:
                        reqlen = struct.unpack("!I", recvbuf[0:4])[0]
                        if buflen >= reqlen:
                            body = recvbuf[:reqlen]
                            req = HelloRequest()
                            req.loads(body)
                            self.on_request(req)
                            print "receive from %s@%s: %s" % (self.client_address[0], self.client_address[1], recvbuf)
        except socket.error, e:
            if e.errno == 10054:
                self.connection.close()
        except:
            print ("%s" % traceback.format_exc())
        print "End handling with client %s:%s" % (self.client_address[0], self.client_address[1])

    def on_request(self, req):
        rsp = HelloResponse()
        rsp.result = "Hello, %s!" % req.username
        rsp.seq = req.seq
        rsp.len = 8 + len(rsp.result)
        rspbuf = rsp.dumps(BinarySerializer())
        sent_size = 0
        while sent_size < rsp.len:
            sent_size += self.connection.send(rspbuf[sent_size:])


class HelloTcpServer(ThreadingTCPServer):
    '''自定义tcp服务端
    '''

    def __init__(self):
        server_address = ('localhost', 8091)
        TCPServer.__init__(self, server_address, RequestHandler)


if __name__ == "__main__":
    server = HelloTcpServer()
    server.serve_forever(1)

 

posted @ 2022-01-26 15:32  阿昭  阅读(444)  评论(0编辑  收藏  举报