這才是你要的分布式測試

說明

  • 前面文章介紹了如何利用docker搭建selenium grid

  • selenium grid由一個中心Hub節(jié)點和大于等于1個的Node節(jié)點組成鸳谜,所有的Node節(jié)點都要注冊到Hub節(jié)點悦冀。測試執(zhí)行時所有的請求發(fā)送到Hub節(jié)點邻遏,Hub節(jié)點再將執(zhí)行指令分發(fā)到多個注冊的Node節(jié)點髓削,Node節(jié)點是真正執(zhí)行Web測試的節(jié)點驯用,就相當于selenium本機執(zhí)行一樣驼鞭。

  • 網(wǎng)上很多教程都是使用多進程/多線程啟動多個node去執(zhí)行用例,這樣的意義并不大衫贬,如果一個Node中的用例太多德澈,并不會節(jié)約多少時間,如果開啟太多的進程用node去跑用例固惯,無論是管理用例的復(fù)雜性和損耗資源都不是成正比

  • 正確的使用場景是一個node里面再去分布式執(zhí)行用例圃验,其實java中的testng提供這樣的功能,而此次我介紹的是用python缝呕,因此需要集結(jié)合pytest

環(huán)境搭建

  • 本機window10安裝好python3

  • pytest

  • pytest-html 生成測試報告插件

  • pytest-xdist 分布式用例

pip install pytest
pip install pytest-xdist
pip install pytest-html
  • 修改pytest源代碼文件,解決報告亂碼問題
D:\app\Python37\Lib\site-packages\pytest_html\plugin.py

   class TestResult:
        def __init__(self, outcome, report, logfile, config):
            #self.test_id = report.nodeid.encode("utf-8").decode("unicode_escape")
            self.test_id = re.sub(r'(\\u[a-zA-Z0-9]{4})',lambda x:x.group(1).encode("utf-8").decode("unicode-escape"),report.nodeid)
  • 看下我的代碼結(jié)構(gòu)


    image.png
  • 核心目錄是testcase是用例目錄斧散,里面分為了大回歸供常、小回歸、冒煙文件夾鸡捐,用例放不同的用例栈暇,這樣的放的好處非常明顯了,大回歸包含小回歸和冒煙箍镜,小回歸包含冒煙

  • testcase目錄下由conftest.py 這里面對pytestpytest-html可以進行有些設(shè)置

# conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from py._xmlgen import html

_driver = None


# @pytest.fixture()
@pytest.fixture(scope='session', autouse=True)
def driver():
    global _driver
    print(11111)
    ip = "遠程ip"
    server = "http://%s:7777/wd/hub" % ip
    # ip = "localhost"
    _driver = webdriver.Remote(
        command_executor="http://%s:7777/wd/hub" % ip,
        desired_capabilities=DesiredCapabilities.CHROME
    )
    # 返回數(shù)據(jù)
    yield _driver
    # 實現(xiàn)用例后置
    _driver.quit()


@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
    """
    當測試失敗的時候源祈,自動截圖煎源,展示到html報告中
    :param item:
    """
    if not _driver:
        return
    pytest_html = item.config.pluginmanager.getplugin('html')
    outcome = yield
    report = outcome.get_result()
    report.description = str(item.function.__doc__)
    extra = getattr(report, 'extra', [])

    if report.when == 'call' or report.when == "setup":
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
            screen_img = _capture_screenshot()
            if screen_img:
                html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:1024px;height:768px;" ' \
                       'onclick="window.open(this.src)" align="right"/></div>' % screen_img
                extra.append(pytest_html.extras.html(html))
        report.extra = extra


def pytest_html_results_table_header(cells):
    cells.insert(1, html.th('用例名稱'))
    cells.insert(2, html.th('Test_nodeid'))
    cells.pop(2)


def pytest_html_results_table_row(report, cells):
    cells.insert(1, html.td(report.description))
    cells.insert(2, html.td(report.nodeid))
    cells.pop(2)


def pytest_html_results_table_html(report, data):
    if report.passed:
        del data[:]
        data.append(html.div('通過的用例未捕獲日志輸出.', class_='empty log'))


def pytest_html_report_title(report):
    report.title = "pytest示例項目測試報告"

def _capture_screenshot():
    """
    截圖保存為base64
    :return:
    """
    return _driver.get_screenshot_as_base64()
  • 用例編寫
# test_selenium.py

mport os
import time
import pytest

class TestCase(object):
    @pytest.mark.finished
    def test_001(self, driver):
        time.sleep(3)
        driver.get("https://www.baidu.com")
        print(driver.title)
        driver.find_element_by_id("kw").click()
        driver.find_element_by_id("kw").send_keys("你好")
    def test1_001(self, driver):
        time.sleep(3)
        driver.get("https://www.baidu.com")
        print(driver.title)
        driver.find_element_by_id("kw").click()
        driver.find_element_by_id("kw").send_keys("你好")
  • 代碼入口
import os
from multiprocessing import Process

import pytest


def main(path):
    # pytest.main(['%s' %path,'-m finished', '--html=report.html','--self-contained-html', '--capture=sys'])
    pytest.main(['%s' %path,'-n 3', '--html=report.html','--self-contained-html', '--capture=sys'])
    # pytest.main(['%s' %path,'-n=auto', '--html=report.html','--html=report.html', '--html=report.html'])
    # 'pytest -s 大回歸/小回歸/  --workers 1 --tests-per-worker 2 --html=report.html --self-contained-html --capture=sys'
    # 'pytest -s testcase/大回歸/小回歸/冒煙 --th 10 --html=report.html --self-contained-html --capture=sys'
    # 'pytest -s testcase/大回歸/小回歸/冒煙 -n 3 --html=report.html --self-contained-html --capture=sys'


if __name__ == '__main__':
    # 大回歸
    test_case = Process(target=main, args=("d:\\project\\auto_web_ui\\testcase\\大回歸\\",))
    test_case.start()
    test_case.join()
    # 小回歸

    # 冒煙

其他

  • pytest-xdist 經(jīng)過測試,在云服務(wù)器(雙核)上跑香缺,可以正常跑手销,如果指定進程太大,會造成容器內(nèi)存泄漏图张,服務(wù)器出現(xiàn)長期卡死锋拖,所以建議:每次執(zhí)行任務(wù)時,都把容器刪了重建祸轮,同時進程不要指定太大

    • 可以進入到docker 容器中排除內(nèi)存情況:docker exec -it ec3d30bff042 top兽埃,其中ec3d30bff042selenium/node-chrome 的鏡像
  • 測試了pytest-parallel 這個無論是在服務(wù)器還是本地win上跑,都報錯

  • 使用了pytest-multithreading 發(fā)現(xiàn)個問題

    • pytest-html上的記錄日志适袜,會被打亂柄错,因此如果要使用的化,建議在conftest.py中苦酱,記錄日志的代碼去掉

    • 多線程訪問百度網(wǎng)站售貌,會被限制輸入驗證信息

    • 安裝pip install pytest-multithreading -i https://pypi.douban.com/simple

    • 調(diào)用 pytest -s testcase/大回歸/小回歸/冒煙 --th 10 --html=report.html --self-contained-html --capture=sys

總結(jié)

  • 當然如果沒有條件,你對本地搭建selenium grid有興趣的化躏啰,可以參考我之前的這篇文章趁矾,源代碼都提供好了

  • 后續(xù)工作就更加簡單,比如jenkins啟動给僵,我會對接一個可視化平臺實現(xiàn):任務(wù)管理毫捣,報告分析等

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帝际,隨后出現(xiàn)的幾起案子蔓同,更是在濱河造成了極大的恐慌,老刑警劉巖蹲诀,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斑粱,死亡現(xiàn)場離奇詭異,居然都是意外死亡脯爪,警方通過查閱死者的電腦和手機则北,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痕慢,“玉大人尚揣,你說我怎么就攤上這事∫淳伲” “怎么了快骗?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我方篮,道長名秀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任藕溅,我火速辦了婚禮匕得,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜈垮。我一直安慰自己耗跛,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布攒发。 她就那樣靜靜地躺著调塌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惠猿。 梳的紋絲不亂的頭發(fā)上羔砾,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音偶妖,去河邊找鬼姜凄。 笑死,一個胖子當著我的面吹牛趾访,可吹牛的內(nèi)容都是我干的态秧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扼鞋,長吁一口氣:“原來是場噩夢啊……” “哼申鱼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起云头,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捐友,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后溃槐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匣砖,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年昏滴,在試婚紗的時候發(fā)現(xiàn)自己被綠了猴鲫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡谣殊,死狀恐怖拂共,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蟹倾,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站鲜棠,受9級特大地震影響肌厨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豁陆,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一柑爸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盒音,春花似錦表鳍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雄坪,卻和暖如春厘熟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背维哈。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工绳姨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阔挠。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓飘庄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親购撼。 傳聞我的和親對象是個殘疾皇子跪削,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一、Python介紹 Python 是一個高層次的結(jié)合了解釋性份招、編譯性切揭、互動性和面向?qū)ο蟮哪_本語言。 Python...
    成啦過客的青春閱讀 451評論 0 0
  • 1.軟件測試級別锁摔? 單元測試:單元測試是對軟件組成單元進行測試廓旬。其目的是檢驗軟件基本組成單位的正確性。測試的對象是...
    聽聞白依閱讀 1,417評論 0 9
  • 一谐腰、測試筆記 1.軟件定義:數(shù)據(jù)+指令+文檔 2. 軟件分類: 場景:工具...
    _想睡覺_閱讀 338評論 0 0
  • 1.計算機歷史:四個階段 2. 操作系統(tǒng): 1.移動端系統(tǒng):android和ios 2.pc端:Win...
    愛吃香菜的yb閱讀 860評論 0 3
  • 第五單元孕豹、性能測試 1.什么是性能測試 通過自動化的測試工具模擬系統(tǒng)正常、異常十气、峰值的場景對系統(tǒng)的各項性能...
    人間朝與暮閱讀 251評論 0 0