一個(gè)困擾3天的狗血技術(shù)問(wèn)題終于被解決了。記錄下來(lái)龍去脈。
問(wèn)題起因:
RobotFramework終于推出了selenium2的Library,垂涎于selenium2性能的大幅度提升和突破瀏覽器沙箱限制這兩個(gè)大亮點(diǎn),下午閑暇之余三下五除二裝上了selenium2Library。裝完后,興沖沖的寫(xiě)了一個(gè)簡(jiǎn)單的demo想運(yùn)行一下,在RIDE上點(diǎn)擊執(zhí)行后,發(fā)現(xiàn)測(cè)試通過(guò),但是IE瀏覽器卻沒(méi)有能夠啟動(dòng)。三天的噩夢(mèng)開(kāi)始了。。。。。
過(guò)程描述:
day1:
1.懷疑寫(xiě)的腳本有問(wèn)題,反復(fù)查看后發(fā)現(xiàn)腳本OK。
2.懷疑selenium2Library安裝有問(wèn)題,卸掉重裝,問(wèn)題依然存在。
3.仔細(xì)閱讀安裝說(shuō)明,卸掉重裝,問(wèn)題依然存在。
4.運(yùn)行slenium2Library自帶的驗(yàn)收測(cè)試和單元測(cè)試腳本,發(fā)現(xiàn)有11個(gè)用例跑不通,查看用例發(fā)現(xiàn)是IEDriver部分有問(wèn)題。
5.google問(wèn)題,沒(méi)有答案,在robotframework社區(qū)發(fā)了技術(shù)請(qǐng)求貼。
6.嘗試FirefoxDriver,能夠打開(kāi)FirefoxDriver實(shí)例,但是無(wú)法進(jìn)行下一步操作,Chrome也無(wú)法打開(kāi)。
7.切換關(guān)鍵詞進(jìn)行搜索,再切換關(guān)鍵詞進(jìn)行搜索,切換搜索引擎到bing,均沒(méi)有答案,在社區(qū)更新了一些出錯(cuò)信息。
8.設(shè)置斷點(diǎn)debug源碼,發(fā)現(xiàn)python的webdriver調(diào)用的是一個(gè)叫做IEdriver.dll的動(dòng)態(tài)鏈接庫(kù)。使用工具見(jiàn)識(shí)IEdriver.dll,發(fā)現(xiàn)python正常調(diào)用IEdriver.dll,但是瀏覽器是起不來(lái)。
9.google IEdriver.dll源碼 無(wú)果(其實(shí)有技術(shù)文檔,但是google關(guān)鍵詞不對(duì),當(dāng)時(shí)沒(méi)有找到)
10.認(rèn)為是python問(wèn)題,將現(xiàn)有python版本切換到2.7.1,問(wèn)題依然存在。。。這時(shí)候已經(jīng)晚上8點(diǎn)了。只能回家吃飯。
晚上吃點(diǎn)兒東西后繼續(xù)嘗試,把家中的python升級(jí)到2.7.2。Bingo!!!問(wèn)題被解決了。當(dāng)時(shí)確認(rèn)為python版本問(wèn)題。高高興興在社區(qū)做了回復(fù)。
Day2:
1.興沖沖打開(kāi)自己電腦,將python升級(jí)到2.7.2,公司電腦上問(wèn)題依舊。
2.繼續(xù)翻看社區(qū)回復(fù),發(fā)現(xiàn)沒(méi)有人回答。
3.認(rèn)為IEDriver.dll版本有問(wèn)題,從java版的jar包里解壓出一個(gè)替換。問(wèn)題依舊。
4.懷疑瀏覽器版本有問(wèn)題,又不能換,把好幾個(gè)同事的機(jī)子折騰了一個(gè)遍,嘗試數(shù)個(gè)IE版本。同事的機(jī)子也是一個(gè)也不行。
5.使用C#調(diào)用webdriver,成功了,大興奮,換出來(lái)C#的版本的IEdriver.dll在python下還是不行(這里讓我認(rèn)為不是代理服務(wù)器的問(wèn)題)。
5.由于當(dāng)天有很多更重要的工作,只能先停滯下來(lái)了。
6.晚上換了老婆的機(jī)子試驗(yàn),竟然又成功了。匪夷所思。
Day3:
1.下午3點(diǎn)鐘開(kāi)始有些閑暇,繼續(xù)深入思索:家里的機(jī)子和單位的機(jī)子有什么區(qū)別呢?C#和python調(diào)用有什么區(qū)別呢?。。?嗨稼は牒蟮贸觯杭依锏臋C(jī)子與單位機(jī)子的一個(gè)區(qū)別是沒(méi)有使用代理服務(wù)器。C#與python調(diào)用的區(qū)別得讀源碼。
2.嘗試去掉代理,失敗。
3.嘗試調(diào)試C#代碼,發(fā)現(xiàn)要下載一堆開(kāi)源工程的源碼,心里一萬(wàn)個(gè)不愿意。都有一點(diǎn)兒放棄了。
4.漫無(wú)目的的google。發(fā)現(xiàn)有人提我一樣的問(wèn)題,興沖沖的點(diǎn)進(jìn)去,TMD是我自己提的!臨近崩潰。
5.后回到社區(qū),突然發(fā)現(xiàn)一個(gè)國(guó)際友人給了回復(fù),她說(shuō),你試試把IE恢復(fù)默認(rèn)值看看。
6.我照做,居然成功了!!!!!
7.在同事的機(jī)子上做。也都成功了!
刨根問(wèn)底:
1.why? Why? Why?
折騰了3天我不想這么放過(guò)去。仔細(xì)對(duì)比了一下瀏覽器還原后和以前的區(qū)別,大的區(qū)別是代理服務(wù)器
。為什么剛才我去掉代理還失敗了呢?仔細(xì)回想,原來(lái)去掉代理后,沒(méi)有使用在python中退出webdriver實(shí)例,那個(gè)dll還在加載中,因此無(wú)效!真是分析問(wèn)題還要更加細(xì)致才行!
2.那為什么代理會(huì)影響IE被load呢?回家后在selenium的wiki上進(jìn)行地毯式搜索,終于找到了下面這篇文章,閱讀大致了解了問(wèn)題所在:
InternetExplorerDriverInternals
原來(lái),IEdriver.dll是一個(gè)客戶端-服務(wù)器端的結(jié)構(gòu),服務(wù)器端代碼使用COM技術(shù)操縱IE,并且會(huì)起一個(gè)mini的Server,客戶端的代碼通過(guò)一種叫做JsonWireProtocol 的協(xié)議和服務(wù)器端通訊,從而達(dá)到操控IE的目的。服務(wù)器端的代碼寫(xiě)的太簡(jiǎn)單,根本沒(méi)有考慮代理的處理,源碼如下:
http://code.google.com/p/selenium/source/browse/trunk/jobbie/src/cpp/InternetExplorerDriver/InternetExplorerDriver.cpp?r=8461
一個(gè)技術(shù)問(wèn)題解決的全過(guò)程(webdriver <wbr>調(diào)用IE <wbr>問(wèn)題)
3.為什么FireFox和Chorme在IE設(shè)置代理時(shí)也出現(xiàn)問(wèn)題呢?
FireFox沒(méi)有嘗試去掉代理的情況;chrome的代理設(shè)置則依賴于系統(tǒng)設(shè)置,也是IE設(shè)置。
4.為什么C#可以調(diào)用成功呢,仔細(xì)琢磨,C#下的IEDriver.dll是動(dòng)態(tài)生成的,生成dll的代碼肯定包含了對(duì)代理服務(wù)器的考慮(搞.net的肯定對(duì)IE機(jī)制熟透了)。
5.為什么網(wǎng)上那么少人有跟我一樣的問(wèn)題? 國(guó)內(nèi)社區(qū)還不成熟,案例少,國(guó)外社區(qū)的家伙們貌似用windows +IE的是小眾。。。。。。 看到n個(gè)回帖的哥們說(shuō),他們?cè)趌inux+firefox上工作良好心理感覺(jué)還怪怪的。
終解決方案:
1.去掉代理。
2.在社區(qū)給作者發(fā)信,請(qǐng)他加入對(duì)代理服務(wù)器的考慮。
總結(jié):
1.要相信開(kāi)源社區(qū)的力量,眾人拾柴火焰高,今后也會(huì)努力的去幫助別人。
2.充分利用搜索引擎里的蛛絲馬跡,但是要仔細(xì)思考,不要被淹沒(méi)在信息中。
3.真正弄懂原理才能真正解決問(wèn)題,總是照貓畫(huà)虎到關(guān)鍵時(shí)刻會(huì)吃虧。
---------------------------------------------------------------------------------------------
補(bǔ)充:
@吳穹adam 提供了兩篇文章:
Webdriver的高級(jí)用法:
給出了用程序顯式設(shè)置proxy的方法:
from selenium import webdriver PROXY = "localhost:8080" webdriver.DesiredCapabilities.INTERNETEXPLORER['proxy'] = { "httpProxy":PROXY, "ftpProxy":PROXY, "sslProxy":PROXY, "noProxy":None, "proxyType":"MANUAL", "class":"org.openqa.selenium.Proxy", "autodetect":False } # you have to use remote, otherwise you'll have to code it yourself in python to # dynamically changing the system proxy preferences driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.INTERNETEXPLORER)
一個(gè)哥們類似問(wèn)題的解決方法:
http://passerbyy.iteye.com/blog/1286292
自己只看了COM互操作的源碼,原來(lái)在外層是可以設(shè)置Proxy的。得繼續(xù)深入學(xué)習(xí)。