qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          大話js代碼靜態(tài)檢查

            1、背景

            首先必須承認(rèn),靜態(tài)代碼檢查不能解決所有問題!比如說,QA不能指望著靠靜態(tài)代碼檢查來發(fā)現(xiàn)rd的代碼邏輯的bug。而對于javascript,可能就是代碼某處少了個(gè)分號,或者是某些編碼的bad –practice。這些問題可能很小很小,但是對用戶體驗(yàn)足以造成巨大影響。因此,如果這種檢查真的能發(fā)現(xiàn)問題,那么還是很有必要的。

            之后的一個(gè)問題是成本:為了發(fā)現(xiàn)一個(gè)潛在的問題,我們要付出多少精力?靜態(tài)檢查給我們的印象是:飛速的掃描一遍代碼然后返回一大堆信息——就像一個(gè)可能蘊(yùn)藏金子的沙堆,我們必須有耐心才能在這個(gè)沙堆中找到有價(jià)值的信息。顯然這一過程的成本由以下兩部分組成:代碼掃描+判別有效性。第一個(gè)過程往往十分迅速,秒級而已。而第二個(gè)過程往往需要人工的介入,這是成本消耗的關(guān)鍵點(diǎn)。試想,如果靜態(tài)檢查返回過多無用信息,導(dǎo)致人工檢查耗時(shí)過長,則這種檢查的收益就得不償失了。

            綜上所述,靜態(tài)代碼檢查面臨的挑戰(zhàn)是:準(zhǔn)確性和低成本。

            2、初識(shí)靜態(tài)檢查規(guī)則與工具

            靜態(tài)檢查工具jslint&jshint

            為了應(yīng)對QA前端js知識(shí)儲(chǔ)備不足的短板,我們除了加強(qiáng)自身的學(xué)習(xí)之外,一個(gè)有效的方法就是“站在巨人的肩膀上”。

            1)jslint

            前端領(lǐng)域的大牛Douglas Crockford編寫了JsLint,將他認(rèn)為的那些重要的js編程實(shí)踐作為靜態(tài)檢查項(xiàng),他提出的某些編程實(shí)踐也確實(shí)被人們所接受,因?yàn)檫@確實(shí)是容易引起問題的關(guān)鍵點(diǎn)(例如,在應(yīng)該使用===的地方不要使用==等)。不過JsLint也存在一些問題,如它的某些檢查過于嚴(yán)苛;遇到for-in語句后會(huì)停止檢測;且非開源。。這些問題都使得人們對JSLint“敬而遠(yuǎn)之”。

            2)jshint

            為解決jslint現(xiàn)存的問題,有了JSHint這個(gè)項(xiàng)目,此開源項(xiàng)目作為JSLint的一個(gè)分支,允許用戶自定義檢查項(xiàng),使用起來更加輕量級。有了JSHint,程序員就可以根據(jù)自己的編程習(xí)慣來定制個(gè)性化的檢查策略。文獻(xiàn)[1] 講述了JSHint與JSLint的區(qū)別。

            JsHint本質(zhì)上是一個(gè)js庫(jshint.js)。筆者也曾膜拜此文件的代碼,發(fā)現(xiàn)它實(shí)際上是一個(gè)js的詞法分析器,里面定義了各種規(guī)則,然后對輸入的代碼字符串做切詞和匹配,每發(fā)現(xiàn)一個(gè)“錯(cuò)誤”(或是壞的編程實(shí)踐)就放到結(jié)果數(shù)組中保存起來。因此,如果你會(huì)寫js代碼的話,完全可以在js文件中引用jshint.js。例如,你可以使用JSHINT函數(shù)來進(jìn)行代碼檢查,如下所示:

            var result = JSHINT(source, options);

            其中JSHINT是一個(gè)全局函數(shù),第一個(gè)參數(shù)source : 必選項(xiàng)。表示需要檢查的代碼,js或者json,可以傳一個(gè)字符串或者一個(gè)數(shù)組。如果傳字符串,需要用’\r’或者’\n’來分隔一行一行的代碼;如果傳數(shù)組,則每一個(gè)數(shù)組元素表示一行的代碼。第二個(gè)參數(shù)option : 可選項(xiàng)。表示代碼檢查的配置項(xiàng),具體的配置項(xiàng)含義參見文獻(xiàn)[2],使用key/value字典表示,key就是要檢查的配置項(xiàng)名稱,value是bool類型。返回值:如果代碼沒有問題,JSHINT會(huì)返回一個(gè)true;否則返回false。當(dāng)返回值是false的時(shí)候可以使用JSHINT.errors獲取出錯(cuò)的原因,JSHINT.data包含了本次檢查更詳細(xì)的信息。另外,使用JSHINT.report可以生成錯(cuò)誤信息的html報(bào)告。

            認(rèn)識(shí)檢查規(guī)則

          propdescription
          bitwise如果是true,則禁止使用位運(yùn)算符
          curly如果是true,則要求在if/while的模塊時(shí)使用TAB結(jié)構(gòu)
          debug如果是true,則允許使用debugger的語句
          eqeqeq如果是true,則要求在所有的比較時(shí)使用===和!==
          evil如果是true,則允許使用eval方法
          forin如果是true,則不允許for in在沒有hasOwnProperty時(shí)使用
          maxerr默認(rèn)是50。 表示多少錯(cuò)誤時(shí),jsLint停止分析代碼
          newcap如果是true,則構(gòu)造函數(shù)必須大寫
          nopram如果是true,則不允許使用arguments.caller和arguments.callee
          nomen如果是true,則不允許在名稱首部和尾部加下劃線
          onevar如果是true,則在一個(gè)函數(shù)中只能出現(xiàn)一次var
          passfail如果是true,則在遇到第一個(gè)錯(cuò)誤的時(shí)候就終止
          plusplus如果是true,則不允許使用++或者- -的操作
          regexp如果是true,則正則中不允許使用.或者[^…]
          undef如果是ture,則所有的局部變量必須先聲明之后才能使用
          sub如果是true,則允許使用各種寫法獲取屬性(一般使用.來獲取一個(gè)對象的屬性值)
          strict如果是true,則需要使用strict的用法,
          詳見http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
          white如果是true,則需要嚴(yán)格使用空格用法。

            不足

            牛人的東西很好,但實(shí)際使用起來發(fā)現(xiàn)有如下的問題:

            (1)靜態(tài)代碼檢查規(guī)則配置需要修改Jshint的Js源代碼,修改代價(jià)較高,且容易出錯(cuò);

            (2)檢查結(jié)果誤報(bào)較多,且可讀性差,找到真正是問題的結(jié)果需要排查幾K的報(bào)錯(cuò)信息,效率較低。

            3、jshunter:一款基于jshint的靜態(tài)代碼檢查工具

            為解決Jshint以上2個(gè)突出問題以及擴(kuò)展更多的特性滿足ECOM WEB類產(chǎn)品JS靜態(tài)代碼檢查的準(zhǔn)確性、有效性,基于Jshint和Rhino開發(fā)了Jshunter這一款工具用于js代碼語法類錯(cuò)誤檢查。

            Jshunter提供的解決方案如下:

            (1)檢查規(guī)則靈活配置。Jshunter支持將所有檢查項(xiàng)放到一個(gè)配置文件中,用戶可以通過true或false來自定義個(gè)性化的檢查項(xiàng),而不必修改Jshint源代碼;

            (2)清晰醒目的結(jié)果報(bào)表。Jshunter從繁雜的檢查結(jié)果字符串中提出關(guān)鍵信息,以Html文件的形式展現(xiàn),對掃描結(jié)果嚴(yán)重程度給出LEVEL標(biāo)識(shí)。非常適用于持續(xù)集成的開發(fā)模式,作為Hudson上的一個(gè)報(bào)表呈現(xiàn);示意圖如下:

            (3)支持Html內(nèi)嵌js代碼的檢查,提高檢查準(zhǔn)確性。業(yè)界的Jshint不支持Html內(nèi)嵌Js代碼檢查,存在漏檢、漏測的風(fēng)險(xiǎn)。Jshunter解決了這個(gè)問題,不但能檢查Js文件,還能檢查Html中內(nèi)嵌的文件;

            (4)掃描結(jié)果過濾,減少冗余信息,提高結(jié)果分析效率。通過黑名單過濾和錯(cuò)誤級別設(shè)定,Jshunter支持用戶設(shè)定結(jié)果提醒級別,目前支持warning,error和ignore,其中被設(shè)定ignore的錯(cuò)誤不會(huì)在報(bào)表中呈現(xiàn),減少冗余信息的查看與分析。

            具體說來,之前困擾的根源就在于我們解析jshint.js的環(huán)境是瀏覽器,受限于瀏覽器的環(huán)境,我們不能進(jìn)行外部文件讀寫。如果需要將jshint命令行化我們需要找到這樣一個(gè)環(huán)境:既能解析js代碼,又能進(jìn)行文件讀寫。因此我們找到了rhino——一個(gè)能解析js代碼的java環(huán)境[4]。利用java環(huán)境,我們讀取外部文件提取待檢查的js代碼,之后利用rhino運(yùn)行大牛寫的jshint.js。

            此工具依賴python環(huán)境,無需安裝。使用也極其簡單,只需要進(jìn)入jshunter的主目錄下運(yùn)行:./hint.py /rest/file/path /path/to/check/*.js就可以了。這里hint.py是主程序的代碼,/rest/file/path是該工具生成的報(bào)表文件名,/path/to/check/*.js是待檢查的文件(支持單個(gè)文件和多個(gè)文件的代碼檢查)。程序運(yùn)行后會(huì)根據(jù)主目錄中的check.cfg配置文件進(jìn)行檢查,該文件各個(gè)檢查項(xiàng)的具體含義見注釋的描述。另外,如果不希望看到某些提示信息,可以將這些信息放到ignore.list黑名單文件中。也就是說,通過check.cfg和ignore.list,用戶可以定制符合自己產(chǎn)品線特點(diǎn)的檢查策略。

            4、小結(jié)

            本文介紹了和js代碼靜態(tài)檢查技術(shù)相關(guān)的內(nèi)容。代碼檢查的成本很低,且確實(shí)能發(fā)現(xiàn)一些潛在的問題。Jshint是業(yè)界一款開源的靜態(tài)代碼檢查工具,但在易用性方面存在2個(gè)突出的問題,針對目前存在的問題,我們基于JSHint開發(fā)的一個(gè)命令行方式的代碼檢查工具jshunter,支持自定義的檢查策略配置和黑名單過濾機(jī)制,并且能生成格式美觀的報(bào)表。


          posted on 2012-08-02 14:10 順其自然EVO 閱讀(1118) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          <2012年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 和顺县| 房产| 德格县| 沧州市| 周宁县| 乳源| 沅江市| 伽师县| 昌宁县| 奉节县| 清远市| 太白县| 太仆寺旗| 海晏县| 依安县| 天门市| 万安县| 桃江县| 南丹县| 虹口区| 河津市| 吉隆县| 盐津县| 青州市| 本溪市| 华亭县| 白水县| 寻乌县| 小金县| 辽阳县| 东兰县| 吉木乃县| 四子王旗| 神农架林区| 资兴市| 个旧市| 堆龙德庆县| 西丰县| 丽水市| 樟树市| 宜春市|