討論: TDD in HTML & JavaScript 之可行性和最佳實踐

作者: Teddy's Knowledge Base  來源: 博客園  發布時間: 2010-08-09 20:50  閱讀: 1177 次  推薦: 0   原文鏈接   [收藏]  

  TDD的背景

  自從03年Beck正式提出(事實上在00年,Beck提出eXtreme Programming時,就已經提出了這個詞)Test-driven design/development這樣一個基于測試優先、重構和迭代的革命性的開發方法以來,無數的實踐已經證明,對于適合進行TDD的領域,TDD能夠極大地提高代碼的可維護性和開發效率。

  在這樣一個迭代的流程中,在寫任何的production code之前,先寫test,再寫production code,并且不斷地對代碼進行清理和重構,并且每次迭代都要進行回歸測試,保證新增的test和production code不會break任何已有的test和production代碼。

  一般來講,支持自動化的回歸測試的工具相對比較容易實現。整個流程中的難點在于:當先行寫test代碼的時候,必然要求先定義被測試的production code的外部接口,對于第一次迭代,自然沒有問題;但是,由于需求的變更,或者整體設計的變更,在后續的迭代過程中,經常會發生,已有的已經實現并且包含完整測試的production code的外部接口需要變更或者說重構;盡管從理論上,絕大多數的重構需求,都有規律甚至是模式可循,但是,如果完全依賴于人工操作,則不僅效率不高,且極易出錯。所以,但凡成功的TDD實踐,其中都不乏很多支持重構的工具。比如,現行絕大多數的集成開發環境,都有很多自動化的代碼重構工具,大大的降低了代碼重構的成本。

  但是還有一些領域,TDD還略微有些力不從心,或者說,至少,至今沒有看到太多比較好的實踐案例。比如:對于Database和UI。

  對于數據庫開發的TDD,到目前為止面臨的主要挑戰是工具的支持。無論是自動化的回歸測試工具,還是重構工具都還遠遠不夠成熟。

  而對于UI的TDD,則是本文的主題。

  TDD in HTML & JavaScript 概述

  談到應用程序的UI,其實包括兩個方面的內容:一方面是純圖形的look & feel;另一方面,則是用戶和應用程序的交互。用戶和應用程序的交互往往同時導致圖形界面的變化,并且,轉換到新的交互行為。

  由于工作實踐中主要是基于WEB的HTML和JavaScript的項目,這里對TDD in UI的討論,將focus在基于HTML和JavaScript的UI。

  同時,一般來講,WEB程序的表現層主要有客戶端代碼和服務端代碼,而服務端代碼,相對來說,更容易被測試。所以,本文討論的重點,主要focus在客戶端代碼。換句話說,這里討論的TDD in HTML & JavaScript指的是對于客戶端的HTML和JavaScript的TDD。

  TDD in HTML & JavaScript 之可行性

  說到可行性,其實可以分兩個層面:理論上的可行性,和實際應用的可行性。

  第一個問題是:純圖形的look & feel理論上可以進行自動化的測試嗎?答案幾乎是否定的。因此,主要用于呈現純圖形的HTML及CSS,也幾乎是很難自動化測試的。

  那么,用戶和應用程序的交互理論上是否可以進行自動化測試呢?答案毫無疑問是肯定的。

  WEB交互的測試其實可以根據WEB程序的架構,分為兩種類型:

  1. 傳統的WEB程序主要基于服務端來呈現內容,用戶和頁面的交互,主要是get,post數據和頁面跳轉。因此,對應的測試方式,主要也是由測試工具模擬需要get或post的數據,并且跟蹤期望的頁面跳轉情況。這種情況下的測試其實相對簡單,因此本文不想過多討論。
  2. 當前的基于AJAX的WEB程序則很大程度上豐富了用戶和頁面交互的方式,用戶和頁面的交互,除了傳統的get,post數據和頁面跳轉,在頁面不刷新的情況下,還通過觸發各種DOM事件,甚至直接觸發JavaScript方法的執行,由JavaScript來改變和呈現內容。此時,傳統的只能模擬需要get或post的數據的測試工具就無能為力了。此時由于所有的邏輯代碼都在JavaScript中,所以,本質上其實是需要對大量的JavaScript代碼進行測試。此正是本文希望討論的重點。

  首先,針對JavaScript的自動化測試工具其實已經有不少了,如:

  Mock工具也有:

  支持直接重構JavaScript代碼的工具相對比較少,提供的功能也都還非常弱:

  從支持工具的現狀,可以說,影響TDD in JavaScript的實際可行性的因素之一是重構工具的缺乏。不過,最近的情況有了一些改變,現在也出現了一些支持JavaScript重構的變通的解決方案,如:

  • Script# - Write C# code,compile C# source code directly to JavaScript code
  • jsc – Write any .NET code, convert .NET assembly to JavaScript, ActionScript, java or PHP code

  這些方案的特點是,利用現有的IDE對流行的編程語言如C#源代碼的完善的coding,尤其是強類型,重構和測試的支持,讓開發人員寫C#,由工具轉換為可直接執行的,格式化的JavaScript代碼。除了充分利用IDE對流行語言的coding支持之外,這類方案的另一個好處是,相對于高薪聘請Senior的JavaScript開發人員,Junior的C#的開發人員要便宜得多,也易招得多,但得益于Script#,已經足夠能用他們熟悉的C#,寫出邏輯復雜和OO的JavaScript代碼,因此,開發成本被大大降低。

  綜上所述,TDD in JavaScript不僅理論上是可行,實際應用上,也是有足夠的工具支持的。尤其是如Script#這樣的工具的出現,極大地提高了JavaScript代碼的開發效率。

  TDD in JavaScript 之最佳實踐

  誰都希望能有最佳實踐。什么是最佳實踐呢?有很多人見不得“best”,“最”這樣的詞,認為,這個世界上沒有“最”的東西。有嗎?當然有!我們首先要略為上升到哲學的高度,對于包含“最”這樣的詞匯的命題,如果想要為“真命題”,則必然是需要加上一個適當的前提條件的。

  比如說:我說“我是這世界上最NB的人”。這毫無疑問是個假命題。因為,缺乏適當的前提條件。你可以自己做個練習,如果覺得這個命題假,想辦法給它加上更多的前提條件,一定能讓它變真。

  所以,所謂最佳實踐,指的是,對一個或者一類特定的問題,在一個相對確定的背景下,所能采取的實際處理的方案典范。加上前提條件,則“最佳實踐”當然是存在的,也是值得討論的。

  通過前面的章節,我們已經把本文重點討論的主題,限制到一個相對小的范圍,那就是對基于AJAX的WEB應用程序中的大量的JavaScript代碼,如何進行TDD?

  并且,我們也收集了足夠的支持TDD需要的各種工具,包括自動化測試工具,Mock工具和重構工具。在這些工具的支持下,很大程度上,WEB程序客戶端JavaScript代碼的TDD和服務端代碼的TDD,不應該有很大的區別。但同時,由于客戶端代碼的特殊性,自然也應該有一些客戶端腳本代碼所特有的實踐模式。

  以下首先列出本人推薦的一些實踐模式,希望大家能一起修正和補缺。

  最佳實踐一:應用MVC模式

  在傳統的非AJAX的WEB程序中,JavaScript往往處于非常輔助性的地位。除了實現一些特效和數據驗證等輔助功能之外,一個頁面的JavaScript代碼,恐怕屈指可數,自然無所謂測試,甚至是TDD了。

  但是在現在的復雜的AJAX應用中,以往必須由多個獨立頁面的get,post和頁面跳轉才能組合實現的功能,通過JavaScript,可以在一個無需刷新瀏覽器的頁面中,輕易實現,不但用戶體驗更佳,速度更快,對服務器的負擔也更小。

  此時,原本傳統WEB程序的服務端需要處理的問題,如數據綁定,事件綁定,邏輯控制等,需要在客戶端進行處理。也因此,原本為了解決WEB程序服務端代碼可測試性問題MVC模式,也就一樣可以良好的應用于客戶端。清晰的將JavaScript代碼分割成M,V,C,將能夠把相同的邏輯職責盡可能集中到一起來管理,從而極大地增加客戶端代碼的可維護性和可測試性。

  下表簡單對比服務端和客戶端MVC下M,V,C的對應職責:

 

Model

View

Controller

Server Side 返回用于呈現頁面內容的數據的 Domain Objects 代表了一個頁面的抽象,包括頁面的內容呈現,數據,事件定義 處理View上觸發的事件,獲取數據,更新View上的數據,觸發View的內容呈現
Client Side 返回 JSON 數據的 Restful Services 同上 同上

  最佳實踐二:應用依賴注入和IoC容器

  應用MVC模式,本質上是抽象的邏輯職責上的解耦。而依賴注入和IoC容器則是代碼的物理依賴性上的解耦。盡可能的利用構造器注入,設值注入,接口注入或IoC容器來解除具體的實現類之間的直接依賴,自然就能極大的大提高每個具體的實現類的可測試性。

  最佳實踐三:應用模板引擎呈現主體內容

  AJAX應用中的一個需要客戶端呈現的View,必然需要呈現一些HTML,這些HTML往往需要根據Model返回的JSON數據動態構造。一般來講,我們會有三種方式來構造和呈現這些HTML:

  • 在JavaScript中遍歷JSON數據,拼接HTML字符串,呈現到頁面上;
  • 在JavaScript中遍歷JSON數據,動態實例化DOM對象,通過DOM對象的方法,呈現HTML的DOM;
  • 通過如JTemplate這樣的JavaScript模板引擎,將JSON數據綁定到一個HTML模板,由模板引擎呈現最終的HTML;

  本最佳實踐的建議內容就是,對于一個View的主體內容,應該盡可能的通過模板引擎來呈現。為什么呢?因為,對于一個WEB程序來說,最不穩定的,會經常變化的部分,無疑是純圖形的HTML和CSS,使用模板引擎,將能夠使得這些HTML盡可能的集中,并且易于修改,也更易于HTML和JavaScript的整合。

  最佳實踐四:應用Script#

  應用Script#好處前面已經提過了,這里再簡單列舉一下:

  • 充分利用現有的IDE對流行的編程語言如C#源代碼的完善的coding,尤其是強類型,重構和測試的支持;
  • 相對于高薪聘請Senior的JavaScript開發人員,Junior的 C#的開發人員要便宜得多;

  如反對,請列舉我不該用它的理由?

  對于以上幾個最佳實踐的應用實例,請參見我之前的文章:This is jqMVC# – CNBLOGS Google Tracer Sample

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()