python分佈式自動化測試框架

先介紹下該測試框架

基本架構

基本功能

        當要在同一臺主機上進行多條測試用例的並行時,對於CPU和內存的消耗比較大,因此,當需要模擬數以千計的併發用戶時,使用單臺機器模擬所有的併發用戶就有些力不從心,甚至會引起內存溢出錯誤。爲了讓該測試框架提供更大的負載能力,有了使用多臺機器同時產生負載的機制。

        該使用測試框架時,測試人員可自行開發自動化測試用例,編寫完成後,上傳至我的服務端進行審覈,審覈通過後,會下發到與服務端連接的多臺slave從機,用戶可通過網頁客戶端,對用例進行分配,在多臺slave從機上進行測試。

  那麼,是如何實現多臺負載機同時運行的呢?當然不會多個人坐在多臺負載機面前,一喊開始,大家同時啓動用例。這種方式很笨,也很難達到真正的同步。其實,我們通過單個服務端就可以控制多個遠程的slave從機,使它們同步的對服務器進行壓力測試或多用例並行測試。

  通過遠程調用測試框架,測試人員可以跨越多臺低端計算機複製測試,這樣就可以模擬一個比較大的服務器壓力,一個服務端端實例,理論上可以控制任意多的遠程slave實例,並通過他們收集測試數據。這樣一樣,就有了如下特性:

*   保存測試採樣數據到本地機器

*   通過單臺機器管理多個執行引擎。

*   沒有必要將測試計劃複製到每一臺機器,服務端會將它發往每一臺slave從機

*   每一臺slave從機都執行相同的測試計劃,服務端不會在執行期間做負載均衡,每一臺slave從機都會完整地運行測試計劃。

  在1.4G Hz3GHz CPU 1GB 內存的 slave從機上,可以處理線程 100300。但是Web Service 例外。XML處理是 CPU 運算密集的,會迅速消耗掉所有的CPU 。一般來說,以XML技術爲核心的應用系統,其性能將是普通Web 應用的 10%25% 。另外,如果所有負載由一臺機器產生,網卡和交換機端口都可能產生瓶頸,所以一個slave從機線程數不應超過 10 0 。 

  採用遠程模式並不會比獨立運行相同數目的非GUI 測試更耗費資源。

使用多臺機器產生負載的操作步驟如下:

(1)在所有期望運行slave的負載生成器的機器上運行slave腳本。然後運行所有slave 機器上的server_client.py 文件

以下是server_client.py部分代碼

import socket  
import threading
import os
import json
from ClientLog import for_test,for_test1,for_test2
from ClientLog import Send
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
sock.bind(('192.168.1.102', 5550))  
  
sock.listen(5)  
print('Server', socket.gethostbyname('192.168.1.102'), 'listening ...')  
mydict = dict()  
mylist = list()  

def subThreadIn(myconnection, connNumber):
    data = myconnection.recv(1024).decode('utf-8')
    print("data: " + data)
    client_data = json.loads(data)
    print("client_data:" + client_data['nickName'] + "  user_id" + str(client_data['user_id']))
    #nickname = myconnection.recv(1024).decode()
    nickname = client_data['nickName']
    user_id = client_data['user_id']
    mydict[myconnection.fileno()] = nickname  
    mylist.append(myconnection)  
    print('connection', connNumber, ' has nickname :', nickname)  
    tellOthers(connNumber, '【系統提示:'+mydict[connNumber])  
    while True:  
        try:  
            recvedMsg = myconnection.recv(1024).decode()  
            if recvedMsg:
                print(mydict[connNumber], ':', recvedMsg)
                if recvedMsg == "for_test":
                    for_test.for_test(user_id,recvedMsg)
                    Send.send(user_id,"準備測試: " + "for_test")
                elif recvedMsg == "for_test1":
                    for_test1.for_test(user_id,recvedMsg)
                    Send.send(user_id,"準備測試: " + "for_test1")
                elif recvedMsg == "for_test2":
                    for_test2.for_test(user_id,recvedMsg)
                    Send.send(user_id,"準備測試: " + "for_test2")
                tellOthers(connNumber, mydict[connNumber]+' :'+recvedMsg)  
  
        except (OSError, ConnectionResetError) as e:
            Send.send(user_id,"測試結束: " + str(e))
            try:  
                mylist.remove(myconnection)  
            except:  
                pass  
            print(mydict[connNumber], 'exit, ', len(mylist), ' person left')  
            tellOthers(connNumber, '【系統提示:'+mydict[connNumber]')  
            myconnection.close()  
            return  
  

(2)測試人員通過網頁規劃測試用例,服務端發送測試計劃到slave從機執行測試

 

以下是服務端核心代碼:

zhujidict = dict()
zhujidict["主機1"] = "192.168.1.102" #爲了方便測試框架,選用的是同一臺slave從機
zhujidict["主機2"] = "192.168.1.102"
zhujidict["主機3"] = "192.168.1.102"
def send_case(request):
    user = request.user
    if not user.is_authenticated():
        logger.error(
        u'[CommentView]當前用戶非活動用戶:[{}]'.format(user.username)
        )
        request.session['LoginForm'] = request.META.get('HTTP_REFERER', '/')
        return render(request,'users/login.html')
    testcase = request.POST.getlist("test_case")
    zhuji = request.POST.getlist("zhuji")
    times = int(request.POST["times"])
    Update.objects.create(
            text =user.username  +  '  :   測試用例  '+ str(testcase) + '    測試主機:     '+ str(zhuji),
            user = user,
    )
    for i in range(times):
        for case_1 in testcase:
            for zhuji_1 in zhuji:
                zhuji_ip = zhujidict[zhuji_1]
                try:
                    sendjson(case_1,zhuji_ip,user.id)
                except Exception as e:
                    Update.objects.create(
                    text =user.username  +  '  :   測試被迫中止,異常:    ' + str(e),
                    user = user,
                    )
        Update.objects.create(
        text =user.username  +  '   :   這是第 ' + str(i+1) + '    次執行測試',
        user = user,
        )
    return redirect('update')

def sendjson(taskName,zhuji,user_id):
    try:
        data = {
            'nickName':'SERVER_TASK',
            'user_id':user_id,
        }
        json_str = json.dumps(data)
        print("JSON對象:",json_str)
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        sock.connect((zhuji,5550))
        sock.send(b'1')
        print(sock.recv(1024).decode())
        sock.send(json_str.encode('utf-8'))
        time.sleep(1)
        sock.send(taskName.encode())
        sock.close()
    except (OSError,ConnectionResetError):
        print(OSError)


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章