• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    跨越邊界: 在集成框架中進行測試,第 2 部分

    發布: 2007-5-24 22:39 | 作者: Bruce Tate | 來源: IBM | 查看: 58次 | 進入軟件測試論壇討論

    領測軟件測試網 在由兩篇文章組成的這一系列的 第 1 部分 中,介紹了如何用 Ruby on Rails 進行單元測試,并展示了如何利用這種方式的某些方面改進 Java™ 的單元測試。Java 開發人員對更高級測試的選擇更加有限。在這篇文章中,將繼續研究 Rails,體會用于功能測試和集成測試的集成框架的優勢。

    超越單元測試的擴展

    關于本系列

    跨越邊界 系列中,作者 Bruce Tate 提出了這樣一個觀點:如今的 Java 程序員可以通過學習其他方法和語言得到很好的其他思路。自從 Java 明顯成為所有開發項目的最佳選擇以來編程前景已經改變。其他的框架正影響構建 Java 框架的方式,從其他語言學到的概念可以影響您的 Java 編程。您編寫的 Python(或 Ruby、Smalltalk ... )代碼可以改變您處理 Java 編碼的方式。

    本系列為您介紹與 Java 開發根本不同,但也可以直接應用于 Java 開發的編程概念和技術。在一些例子中,需要對技術進行集成以利用它。在另外一些例子中,您將能夠直接應用這些概念。單獨的工具不及其他語言和框架能夠影響 Java 社區中的開發人員、框架甚至基本方法的思想那么重要。

    在這由兩部分組成的迷你系列的 第 1 部分 中,了解了如何用動態語言促進單元測試。本文將展示集成環境在功能測試和集成測試中的優勢。單元測試包括對小的代碼片斷(例如方法)的測試,而且經常要把它們與周圍的元素隔離開。功能測試和集成測試所測試的應用程序部分越來越多。功能測試用于測試單一特性(通常涉及一個接口)、執行任務的業務代碼,以及與中間件服務交互的代碼(例如數據庫)。集成測試用于測試應用程序的多個不同特性。(功能測試在不太嚴謹的情況下通常也被稱為集成測試。)

    Java 開發人員在解決單元測試問題上已經獲得了令人注目的成果,但在集成測試上則沒有帶來太多令人興奮的消息。多數 Java 測試框架(如 JUnit 或 TestNG)主要側重于單元測試。Java 編程中缺乏集成測試框架的一個原因是缺乏集中的架構或開發哲學。在后面的小節中,我將繼續使用 Ruby on Rails 示例,這次的重點放在功能測試和新的 Rails 集成測試框架上。您將看到,在使用集成測試框架時,進行測試要容易得多。

    運行測試

    如果還沒有閱讀 第 1 部分,那么請先閱讀它。然后,如果想跟隨這篇文章一起編寫代碼,那么請確保您已經獲得一個可工作的 Rails 應用程序。在第 1 部分中,實現了一個簡單的單元測試和幾個 fixture。如果您跟隨第 1 部分一起編寫了代碼,但是記不清是否使應用程序處于工作狀態,那么您可以利用測試用例,先切換到項目目錄,然后運行 rake 即可。清單 1 顯示了我的結果:


    清單 1. 用 rake 運行所有測試
    > bruce-tates-computer:~/rails/trails batate$ rake
                (in /Users/batate/rails/trails)
                /usr/local/ror/bin/ruby -Ilib:test
                "/usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader.rb"
                "test/functional/trails_controller_test.rb"
                Loaded suite /usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader
                Started
                EEEEEEEEEEEEEEEE
                Finished in 0.070797 seconds.
                1) Error:
                test_create(TrailsControllerTest):
                Errno::ENOENT: No such file or directory - /tmp/mysql.sock
                /usr/local/ror/lib/ruby/gems/1.8/gems/activerecord-1.14.0/
                lib/active_record/vendor/mysql.rb:104:in 'initialize'
                /usr/local/ror/lib/ruby/gems/1.8/gems/activerecord-1.14.0/
                lib/active_record/vendor/mysql.rb:104:in 'real_connect'
                /usr/local/ror/lib/ruby/gems/1.8/gems/activerecord-1.14.0/
                lib/  active_record/connection_adapters/mysql_adapter.rb:331:in 'connect'
                ...results deleted...
                8 tests, 0 assertions, 0 failures, 16 errors
                /usr/local/ror/bin/ruby -Ilib:test "/usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/
                lib/rake/rake_test_loader.rb"
                rake aborted!
                Test failures
                (See full trace by running task with --trace)
                

    可以看到有一些問題存在:rake 生成了 16 個錯誤。跟蹤顯示,Rails 無法建立連接。我忘記啟動數據庫引擎了。我將啟動數據庫引擎,然后再次運行 rake。這次我得到了清單 2 所示的結果:


    清單 2. 在 rake 內通過測試
    rake
                (in /Users/batate/rails/trails)
                /usr/local/ror/bin/ruby -Ilib:test
                "/usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader.rb"
                "test/unit/trail_test.rb"
                Loaded suite /usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader
                Started
                ...
                Finished in 0.09541 seconds.
                3 tests, 5 assertions, 0 failures, 0 errors
                /usr/local/ror/bin/ruby -Ilib:test
                "/usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader.rb"
                "test/functional/trails_controller_test.rb"
                Loaded suite /usr/local/ror/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader
                Started
                ........
                Finished in 0.169756 seconds.
                8 tests, 28 assertions, 0 failures, 0 errors
                

    這樣就好多了。測試正常運行,而我們準備構建更多測試用例。如果仔細查看清單 2 就會發現,rake 生成了兩組結果。第一組(第 1 部分的單元測試)看起來應當熟悉。下一組是從框架中自動生成的功能測試。





    回頁首


    控制器和視圖快速入門

    在查看測試代碼之前,需要對 Rails 的用戶界面層有更好的理解。在第 1 部分中,用 script/generate scaffold Trail Trails 生成框架代碼時,Rails 根據數據庫的內容為應用程序創建了一個控制器和系列視圖?刂破鞯拇a位于 app/controller/trails_controller.rb,視圖則全部位于 app/views/trails 下的不同目錄中。這個應用程序包含:

    • 默認 Web 頁面實現,顯示路線(trail)列表(叫做 list
    • 路線的細節信息的顯示頁面
    • 路線的通用表單
    • 創建或編輯路線的頁面

    要了解這些是如何組合在一起的,請參見 trails_controller.rb 中的 list 方法,如清單 3 所示:


    清單 3. app/controllers/trails_controller.rb 中的部分代碼清單
    def list
                @trail_pages, @trails = paginate :trails, :per_page => 10
                end
                

    傳入的超文傳輸協議(HTTP)請求進入控制器。(HTTP 是支持瀏覽器、Rails 和所有基于瀏覽器的應用程序的底層協議)。在這篇文章后面,您將看到功能測試如何通過使用 HTTP 命令來調用功能測試用例。清單 3 的代碼設置了 Rails 顯示線路的分頁列表時需要的實例變量。視圖需要一個分頁器對象,即 Rails 分配給 @trail_pages 的分頁器對象,還需要 @trails 中的路線列表。默認情況下,Rails 使用與控制器方法相同的名稱呈現視圖。要查看視圖,請參閱 app/views/trails/list.rhtml 中的表格定義,如清單 4 所示:


    清單 4. list.rhtml 的部分代碼清單
    <table>
                <tr>
                <% for column in Trail.content_columns %>
                <th><%= column.human_name %></th>
                <% end %>
                </tr>
                <% for trail in @trails %>
                <tr>
                <% for column in Trail.content_columns %>
                <td><%=h trail.send(column.name) %></td>
                <% end %>
                <td><%= link_to 'Show', :action => 'show', :id => trail %></td>
                <td><%= link_to 'Edit', :action => 'edit', :id => trail %></td>
                <td><%= link_to 'Destroy', { :action => 'destroy', :id => trail },
                :confirm => 'Are you sure?', :post => true %></td>
                </tr>
                <% end %>
                </table>
                

    Rails 中的視圖策略是:創建一個簡單字符串,然后做一些替換。這個策略叫做建模,它構成了大多數現代 Web 框架的基礎,包括 Java 框架(例如 Tapestry、JavaServer Faces(JSF)、JavaServer Pages (JSP) 和 WebWork)。在這個示例中,Rails 做了以下工作:

    1. 執行 <%%> 之間的代碼段(被稱為語句),并用代碼段的執行輸出替代這一部分。語句可能不存在。

    2. 執行 <%=%> 之間的代碼段(被稱為表達式),并用代碼段返回的值替代這一部分。

    3. 處理布局、偏好、幫助程序以及其他類型的代碼片斷時。這些特性允許使用不同的復合部件構建復雜的 Web 頁面。在這里,我就不對細節做過多介紹了。

    在有了模板策略之后,現在再來看一下 清單 4。您可以看到訪問活動記錄 Trail 模型并用 <% for trail in @trails %> 命令在 @trails 中的每條路線上循環的 list.rhtml 視圖。(您已經填充了控制器中的 @trails 實例變量)。對于每條路線,該視圖都將得到 Trail.content_columns,它是 trails_development 數據庫中 trails 表的列的列表。然后,該視圖通過在列表中的每個列上進行循環,提供數據庫中每一列的值。trail.send(column_name) 命令把 name、difficultydescription 方法發送給 trail。

    現在是在屏幕上查看結果的時候了。如果回憶一下,應當記得您已經在第 1 部分的示例中鍵入了一些 fixture 形式的測試數據。要把它們加載到開發環境(fixture 默認裝入測試環境)中,則只需鍵入 rake load_fixtures 即可。啟動 Rails 服務器(在 Unix 上用 script/server,在 Windows 上用 ruby script/server),把瀏覽器指向 localhost:3000/trails/list 就可以看到結果。在這個 URL 中,trails 是控制器的名稱,list 是動作的名稱,由 list 控制器方法實現。圖 1 顯示了結果:


    清單 1. 列出路線

    正如所期望的那樣,可以看到一個包含每條路線的名稱、說明和難度的表。接下來,我將介紹 Rails 的功能測試框架如何只通過一條 HTTP put 命令訪問 Web 頁面。





    回頁首


    分解功能測試

    回憶一下就可以知道,Rails 單元測試只處理模型。Rails 中的功能測試調用 Web 頁面,然后檢查結果,從上到下地測試某一特性(包括模型、視圖和管制器)。這種級別的集成測試很重要,因為可以確保系統的主要元素之間的交互與您對所提供的每個特性的預期一樣。

    Rails 的每個功能測試用例都要進行 HTTP putget。它們調用控制器的動作;控制器訪問模型和視圖,并呈現 Web 頁面和結果。要獲得詳細的工作示例,請參見 Rails 在框架中生成的測試用例:


    清單 5. 來自 test/functional/trails_controller_test.rb 的 test_list
    def test_list
                get :list
                assert_response :success
                assert_template 'list'
                assert_not_nil assigns(:trails)
                end
                

    清單 5 中的測試用例利用 get :list 命令執行了一個簡單的 HTTP get。然后,測試用例運行了三個斷言:

    • assert_response :success:HTTP 命令成功完成。
    • assert_template 'list':控制器動作呈現 list 模板。
    • assert_not_nil assigns(:trails):控制器把 @trails 實例變量分配給一些非 null 的值。

    使用單元測試框架,如果斷言為 ture,沒有錯誤出現,那么測試用例就通過;否則,測試用例失敗。

    test_list 測試用例可以聲明 :success 響應,但是它應當聲明 :redirect (代表 HTTP 重定向)、:missing (代表 not_found),或代表單個 HTTP 返回代碼的整數。請參閱 參考資料,獲得 HTTP 返回代碼的詳盡列表,F在請看 test_create,它使用了一個 HTTP put。請將 test_create 更改成如清單 6 所示:


    清單 6. 測試表單
    def test_create
                num_trails = Trail.count
                post :create, :trail => {:name => "Hermosa Creek", :description =>
                "Lots of altitude, all down", :difficulty => "Medium"}
                assert_response :redirect
                assert_redirected_to :action => 'list'
                assert_equal num_trails + 1, Trail.count
                end
                

    trails_controller_test.rb 中自動生成的這個測試用例的版本包括 post :create, :trail => {},它調用 create 方法,空哈希表表示新路線。這個代碼應當創建一條新路線,該路線有一個所有屬性都為 null 的 Trail 對象。清單 6 修改了代碼,以傳遞代表路線屬性的哈希映射表。這個哈希映射表接口對于在測試框架中指定對象而言非常有用。然后,測試用例用 Trail 模型確保創建了新路線。

    清單 5 和清單 6 中的測試用例不像第 1 部分中的單元測試那樣處理每個細節。但是它們可以保證調用了業務邏輯,保證控制器邏輯沒有檢測到任何錯誤,并保證得到了正確的 HTTP 響應。

    Rails 還提供了另一種測試用例:集成測試。





    回頁首


    集成測試

    功能測試用于測試單一特性,而集成測試可能觸及許多不同的頁面。例如,購物車單元測試可以測試出您可能通過模型 API 將一件商品添加到購物車中。購物車的功能測試可以確保您能夠通過登錄某一 Web 頁面將商品添加到購物車中。而集成測試則可以保證能夠登錄、添加商品和結賬。

    在 “Running Your Rails App Headless”(請參閱 參考資料)中,Mike Clark(Rails 社區領先的測試專家之一)詳細介紹了集成測試框架。開始進行討論時,他介紹了如何運行沒有 Web 頁面的(即 headless)應用程序。這項功能使得搜集編寫集成測試的足夠信息變得更容易。從 Rails 1.1 開始,可以直接從控制臺調用控制器。不需要瀏覽器,只要調用 app 對象的 putget 方法,就可以訪問應用程序的 Web 頁面。

    請啟動控制臺,鍵入清單 7 中的命令,通過 HTTP get 發出列表動作:


    清單 7. 從控制臺使用 Rails 集成測試框架
    > script/console Loading development environment.
                >> app.class
                => ActionController::Integration::Session
                >> app.get('trails', 'list')
                => 200
                >> app.get("trails/list")
                => 200
                >> app.response =~ /Barton Creek/
                => false
                >> app.response =~ /Emma Long/
                => false
                >> app.response.body =~ /Emma Long/
                => 331
                >>
                

    在清單 7 中,從控制臺以兩種形式發送請求,調用 trails 控制器的 list 動作。然后,通過與正則表達式 /Emma Long/ 匹配,可以看到生成的 HTML 頁面中包含 Emma Long(一條路線)。您可以繼續運行 postget


    清單 8. 通過 post 實現刪除
    >> app.post("trails/destroy/1")
                => 302
                >> Trail.find_all
                => [#<Trail:0x25a8e34 @attributes={"name"=>"Bear Creek", "id"=>"2",
                "description"=>"Too many downed trees.", "difficulty"=>"easy"}>]
                >> Trail.find_all.size
                => 1
                >> app.response.redirect_url
                => "http://www.example.com/trails/list"
                >>
                

    通過控制臺集成測試 API,現在有了構建集成測試的足夠信息。請使用 script/generate integration_test DestroyAndShow 生成一個集成測試,并將它編輯成清單 9 那樣:


    清單 9. test/integration/destroy_and_show.rb
    require "#{File.dirname(__FILE__)}/../test_helper"
                class DestroyAndShowTest < ActionController::IntegrationTest
                fixtures :trails
                def test_multiple_actions
                get "trails/list"
                assert_response :success
                post "trails/destroy/1"
                assert_response :redirect
                assert_nil(response.body =~ /Emma Long/)
                assert_equal(2, Trail.find_all.size)
                follow_redirect!
                assert_response :success
                get "trails/show/2"
                assert_response :success
                end
                end
                

    這個示例使用的集成框架與前面通過 Rails 控制臺使用的框架相同,使用的斷言模型也與功能測試和單元測試框架的模型相同?梢杂 rake 運行測試用例,也可以單獨運行每個測試用例。通過以一致的方式使用控制臺和集成框架,可以嘗試應用程序的各個方面,獲得控制臺中的結果,并用這些結果在自動測試用例中提供您的斷言。





    回頁首


    在 Ruby 中測試與在 Java 語言中測試的對比

    現在可以開始查看集成框架中的集成測試有什么不同了。對于這個示例,可以使用 fixture,它們在集成測試框架中工作。斷言和表示想法的方式(例如請求和響應)都有統一的形式。

    基本 Ruby 語言中的某些功能讓 Rails 的測試更強大?梢允褂 Ruby 做類似 mock 和存根所做的事。在編寫這篇文章時,我正在使用 Rails 進行一些自動集成測試。我有一個依賴于當前日期的類。我只是打開了用于 Date 的現有 Ruby 類,并重新定義了 today 方法,讓它返回 Date.civil(2, 2, 2006),如清單 10 所示:


    清單 10. 用 Rails 創建存根
    require "#{File.dirname(__FILE__)}/../test_helper"
                class Date
                def self.today
                return Date.civil(2006, 2, 2)
                end
                end
                class NameOfTest ...continue test case here...
                

    對于我的測試用例,我什么都不需要做,F在,不論測試用例什么時候運行,today 都會是美國的假日土拔鼠日。只使用了五行代碼,我就有了一個可工作的存根。在這個示例中,這個 mock 對象只能用于測試用例。如果需要將這個 mock 對象用于多個測試用例,那么可以給這個 mock 對象添加測試和模擬的代碼,并重新使用它。

    總之,我對 Ruby 的測試體驗的評價是:非常必要(因為動態語言容易出錯的特性),并且更強大。其中部分力量來自通過 Rails 使得代碼生成、斷言、數據庫支持,以及診斷工具無縫地在一起工作的集成體驗。

    但是 Java 技術確實有自己的優勢。在將測試集成到開發環境方面它做得更好,它還有更好的持續集成工具。也可以找到模擬最常見企業特性的更多框架。Java 開發人員有另一個理論優勢:他們可以在沒有數據庫支持的情況下,更容易地運行應用程序。沒有數據庫支持就測試 Rails 應用程序幾乎沒有意義,因為許多 Rails 值是通過元編程(metaprogramming)把 SQL 特性編織起來而得到的。所以,Java 測試套件通常運行得更快,因為套件中的測試用例不需要訪問數據庫。

    如果使用 Java 代碼生成,Rails 可以為您提供一些關于如何使用測試生成增強您的代碼生成的好主意。如果正在補充自己的測試框架,那么 Rails 的測試 API 既簡單又漂亮。如果對超越 Java 編程語言感興趣,那么 Rails 可以為輕量級的、數據庫支持的應用程序提供一些真正的價值。

    在這個系列的下一篇文章中,我將不再介紹 Rails,而是查看基于 Web 的建模策略。您將看到如何將代碼生成用于動態語言。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>