phantomJs之殤仔粥,chrome-headless之生

技術(shù)雷達快訊:自2017年中以來谴供,Chrome用戶可以選擇以headless模式運行瀏覽器叶骨。此功能非常適合運行前端瀏覽器測試显歧,而無需在屏幕上顯示操作過程边败。在此之前,這主要是PhantomJS的領(lǐng)地棉磨,但Headless Chrome正在迅速取代這個由JavaScript驅(qū)動的WebKit方法子檀。Headless Chrome瀏覽器的測試運行速度要快得多浴韭,而且行為上更像一個真正的瀏覽器客叉,雖然我們的團隊發(fā)現(xiàn)它比PhantomJS使用更多的內(nèi)存诵竭。有了這些優(yōu)勢,用于前端測試的Headless Chrome很可能成為事實上的標準兼搏。

image.png

隨著Google在Chrome 59版本放出了headless模式卵慰,Ariya Hidayat決定放棄對Phantom.js的維護,這也標示著Phantom.js 統(tǒng)治fully functional headless browser的時代將被chrome-headless代替佛呻。

Headless Browser

也許很多人對無頭瀏覽器還是很陌生裳朋,我們先來看看維基百科的解釋:

A headless browser is a web browser without a graphical user interface.

Headless browsers provide automated control of a web page in an environment similar to popular web browsers, but are executed via a command-line interface or using network communication.

對,就是沒有頁面的瀏覽器吓著。多用于測試web再扭、截圖氧苍、圖像對比、測試前端代碼泛范、爬蟲(雖然很慢)、監(jiān)控網(wǎng)站性能等紊撕。

為什么要使用headless測試罢荡?

headless broswer可以給測試帶來顯著好處:

  1. 對于UI自動化測試,少了真實瀏覽器加載css对扶,js以及渲染頁面的工作区赵。無頭測試要比真實瀏覽器快的多。
  2. 可以在無界面的服務(wù)器或CI上運行測試浪南,減少了外界的干擾笼才,使自動化測試更穩(wěn)定。
  3. 在一臺機器上可以模擬運行多個無頭瀏覽器络凿,方便進行并發(fā)測試骡送。

headless browser有什么缺陷?

以phantomjs為例

image.png
  1. 雖然Phantom.js 是fully functional headless browser絮记,但是它和真正的瀏覽器還是有很大的差別摔踱,并不能完全模擬真實的用戶操作。很多時候怨愤,我們在Phantom.js發(fā)現(xiàn)一些問題派敷,但是調(diào)試了半天發(fā)現(xiàn)是Phantom.js自己的問題
image.png
  1. 將近2k的issue,仍然需要人去修復(fù)撰洗。
  2. Javascript天生單線程的弱點篮愉,需要用異步方式來模擬多線程,隨之而來的callback地獄差导,對于新手而言非常痛苦试躏,不過隨著es6的廣泛應(yīng)用,我們可以用promise來解決多重嵌套回調(diào)函數(shù)的問題柿汛。
  3. 雖然webdriver支持htmlunit與phantomjs冗酿,但由于沒有任何界面,當我們需要進行調(diào)試或復(fù)現(xiàn)問題時络断,就非常麻煩裁替。

那么Headless Chrome與上面提到fully functional headless browser又有什么不同呢?

什么是Headless Chrome貌笨?

Headless Chrome 是 Chrome 瀏覽器的無界面形態(tài)弱判,可以在不打開瀏覽器的前提下,使用所有Chrome支持的特性锥惋,在命令行中運行你的腳本昌腰。相比于其他瀏覽器开伏,Headless Chrome 能夠更加便捷的運行web自動化測試、編寫爬蟲遭商、截取圖等功能固灵。

有的人肯定會問:看起來它的作用和phantomjs沒什么具體的差別?

對劫流,是的巫玻,Headless Chrome 發(fā)布就是來代替phantomjs。

我們憑什么換用Headless Chrome祠汇?

  1. 我爸是Google,那么就意味不會出現(xiàn)phantomjs近2k問題沒人維護的尷尬局面仍秤。 比phantomjs有更快更好的性能。
  2. 有人已經(jīng)做過實驗可很,同一任務(wù)诗力,Headless Chrome要比現(xiàn)phantomjs更加快速的完成任務(wù),且占用內(nèi)存更少
    image.png

    image.png

    https://hackernoon.com/benchmark-headless-chrome-vs-phantomjs-e7f44c6956c
  1. chrome對ECMAScript 2017 (ES8)支持我抠,同樣headless隨著chrome更新苇本,意味著我們也可以使用最新的js語法來編寫的腳本,例如async屿良,await等圈澈。
  2. 完全真實的瀏覽器操作,chrome headless支持所有chrome特性尘惧。
  3. 更加便利的調(diào)試康栈,我們只需要在命令行中加入--remote-debugging-port=9222,再打開瀏覽器輸入localhost:9222(ip為實際運行命令的ip地址)就能進入調(diào)試界面喷橙。[圖片上傳失敗...(image-a57d6f-1516155651895)]

能帶給QA以及項目什么好處啥么?

前端測試改進

以目前的項目來說,之前的前端單元測試以及組件測試是用karma在phantomjs運行的贰逾,非常不穩(wěn)定悬荣,在遠端CI上運行時經(jīng)常會莫名其妙的掛掉,也找不出來具體的原因疙剑,自從Headless Chrome推出后氯迂,我們將phantomjs切換成Headless Chrome,再也沒有出現(xiàn)過異常情況言缤,切換也非常簡單嚼蚀,只需要把karma.conf.js文件中的配置改下就OK了。如下

customLaunchers: { myChrome: { base: 'ChromeHeadless', flags: ['--no-sandbox', '--disable-gpu', '--remote-debugging-port=9222'] } },

browsers: ['myChrome'],  

UI功能測試改進

原因一管挟,Chrome-headless能夠完全像真實瀏覽器一樣完成用戶所有操作轿曙,再也不用擔心跑測試時,瀏覽器受到干擾,造成測試失敗
原因二导帝,之前如果我們像要在CI上運行UI自動化測試守谓,非常麻煩。必須使用Xvfb幫助才能在無界面的Linux上 運行UI自動化測試您单。(Xvfb是一個實現(xiàn)了X11顯示服務(wù)協(xié)議的顯示服務(wù)器斋荞。 不同于其他顯示服務(wù)器,Xvfb在內(nèi)存中執(zhí)行所有的圖形操作睹限,不需要借助任何顯示設(shè)備譬猫。)現(xiàn)在也只需要在webdriver啟動時,設(shè)置一下chrome option即可羡疗,以capybara為例:

Capybara.register_driver :selenium_chrome do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome,
                                   desired_capabilities: {
                                       "chromeOptions" => {
                                           "args" => [ "--incognito",
                                                       "--allow-running-insecure-content",
                                                       "--headless",
                                                       "--disable-gpu"
                                       ]}
                                   })
    end

無縫切換,只需更改下配置别洪,就可以提高運行速度與穩(wěn)定性叨恨,何樂而不為。

Google終極大招

Google 最近放出了終極大招——Puppeteer(Puppeteer is a Node library which provides a high-level API to control headless Chrome over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome.)

類似于webdriver的高級別的api挖垛,去幫助我們通過DevTools協(xié)議控制無界面Chrome痒钝。

在puppteteer之前,我們要控制chrome headless需要使用chrome-remote-interface來實現(xiàn)痢毒,但是它比 Puppeteer API 更接近低層次實現(xiàn)送矩,無論是閱讀還是編寫都要比puppteteer更復(fù)雜。也沒有具體的dom操作哪替,尤其是我們要模擬一下click事件栋荸,input事件等,就顯得力不從心了凭舶。

我們用同樣2段代碼來對比一下2個庫的區(qū)別晌块。

首先來看看 chrome-remote-interface

const chromeLauncher = require('chrome-launcher');
    const CDP = require('chrome-remote-interface');
    const fs = require('fs');
    function launchChrome(headless=true) {
    return chromeLauncher.launch({
    // port: 9222, // Uncomment to force a specific port of your choice.
     chromeFlags: [
    '--window-size=412,732',
    '--disable-gpu',
       headless ? '--headless' : ''
    ]
    });
    }
    (async function() {
      const chrome = await launchChrome();
      const protocol = await CDP({port: chrome.port});
      const {Page, Runtime} = protocol;
      await Promise.all([Page.enable(), Runtime.enable()]);
      Page.navigate({url: 'https://www.github.com/'});
      await Page.loadEventFired(
          console.log("start")
      );
      const {data} = await Page.captureScreenshot();
      fs.writeFileSync('example.png', Buffer.from(data, 'base64'));
      // Wait for window.onload before doing stuff.  
       protocol.close();
       chrome.kill(); // Kill Chrome.

再來看看 puppeteer

const puppeteer = require('puppeteer');
    (async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://www.github.com');
    await page.screenshot({path: 'example.png'});
    await browser.close();
    })();

對,就是這么簡短明了帅霜,更接近自然語言匆背。沒有callback,幾行代碼就能搞定我們所需的一切身冀。

總結(jié)

目前Headless Chrome仍然存在一些問題钝尸,還需要不斷完善,我們應(yīng)該擁抱變化搂根,適應(yīng)它珍促,讓它給我們的工作帶來更多幫助。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兄墅,一起剝皮案震驚了整個濱河市踢星,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖沐悦,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件成洗,死亡現(xiàn)場離奇詭異,居然都是意外死亡藏否,警方通過查閱死者的電腦和手機瓶殃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來副签,“玉大人遥椿,你說我怎么就攤上這事∠ⅲ” “怎么了冠场?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長本砰。 經(jīng)常有香客問我碴裙,道長,這世上最難降的妖魔是什么点额? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任舔株,我火速辦了婚禮,結(jié)果婚禮上还棱,老公的妹妹穿的比我還像新娘载慈。我一直安慰自己,他們只是感情好珍手,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布办铡。 她就那樣靜靜地躺著,像睡著了一般珠十。 火紅的嫁衣襯著肌膚如雪料扰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天焙蹭,我揣著相機與錄音晒杈,去河邊找鬼。 笑死孔厉,一個胖子當著我的面吹牛拯钻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撰豺,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼粪般,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了污桦?” 一聲冷哼從身側(cè)響起亩歹,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后小作,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亭姥,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年顾稀,在試婚紗的時候發(fā)現(xiàn)自己被綠了达罗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡静秆,死狀恐怖粮揉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抚笔,我是刑警寧澤扶认,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站殊橙,受9級特大地震影響蝠引,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛀柴,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望矫夯。 院中可真熱鬧鸽疾,春花似錦、人聲如沸训貌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽递沪。三九已至豺鼻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間款慨,已是汗流浹背儒飒。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留檩奠,地道東北人桩了。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像埠戳,于是被迫代替她去往敵國和親井誉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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