[翻譯]Play框架1.2.7版本教程(10) - 完成應用測試

完成應用測試

咱們已經完成了咱們想要建立的博客引擎。不過這個項目還沒有徹底結束。爲了保證代碼的質量,咱們須要添加更多的測試。css

固然咱們已經完成了測試全部模型層的功能。因此博客引擎的核心功能已經被測試過了。可是一個Web應用並不僅有模型層。咱們須要確保Web交互界面是否無缺。這須要測試引擎的控制層。可是咱們甚至須要測試UI界面,好比咱們的Javascript代碼。html

測試控制層

經過JUnit,你能夠直接測試應用的控制層。咱們將這些測試稱之爲功能測試。由於咱們會測試應用完整的功能。java

一個功能測試會調用Play的ActionInvoker,模擬一個HTTP請求。咱們須要提供HTTP方法,一個URI和HTTP參數。Play會根據這個請求,找到路由,接着調用對應的action,最後返回一個響應。你能夠分析它,看看響應是否在乎料之中。segmentfault

先寫第一個功能測試。打開yabe/test/ApplicationTest.java瀏覽器

import org.junit.*;
import play.test.*;
import play.mvc.*;
import play.mvc.Http.*;
import models.*;

public class ApplicationTest extends FunctionalTest {

    @Test
    public void testThatIndexPageWorks() {
        Response response = GET("/");
        assertIsOk(response);
        assertContentType("text/html", response);
        assertCharset("utf-8", response);
    }

}

看上去像是通常的JUnit測試。注意咱們使用Play的Functionaltest父類來獲取輔助函數。這個測試僅僅是用於檢測主頁是否正常(通常/URL會渲染一個HTML文件,並返回‘200 OK’狀態碼)。安全

如今咱們將檢測管理面板的安全是否禁得住考驗。給ApplicationTest.java添加新的測試:cookie

…
@Test
public void testAdminSecurity() {
    Response response = GET("/admin");
    assertStatus(302, response);
    assertHeaderEquals("Location", "/login", response);
}
…

使用play test命令運行你的yabe應用,打開http://localhost:9000/@tests,選擇ApplicationTest.java用例,而後運行它。mvc

變綠了嗎?app

green

如今,咱們能夠對應用的所有功能進行一樣的測試,但這並非測試一個基於HTML的Web應用的最佳方式,咱們的博客引擎須要在Web瀏覽器中執行,若是可以在真實的瀏覽器中進行測試,這就是Play的Selenium測試所作的事情。框架

一個Selenium測試套件通常是個HTML文件。Selenium所使用的HTML語法有點使人乏味(就像是一個HTML表格元素同樣)。好消息是,Play可讓你使用模板引擎以及一些支持簡化的Selenium語法的標籤來生成它。這也意味着,你能夠利用Play模板的表達能力(條件語句,循環語句等等)來生成許多複雜的測試。

固然,若是須要的話,你也能夠不用模板的生成功能,直接撰寫Selenium頁面。其實,使用Selenium專用工具,好比Selenium IDE,來生成Selenium測試頁面也是不錯的選擇。

一個剛建立的Play應用已經自帶了一個Selenium測試。打開yabe/test/Application.test.html

*{ You can use plain Selenium commands using the selenium tag }*

#{selenium}
    // Open the home page, and check that no error occurred
    open('/')
    waitForPageToLoad(1000)
    assertNotTitle('Application error')
#{/selenium}

在yabe上運行這個測試應該不會出現任何問題。它只是打開主頁,而後檢測頁面中是否包括"Application error"文本。

不過,一如任何複雜的測試,在瀏覽應用並進行測試以前,你都須要設置一些初始數據。咱們將重用以前用過的Fixture和yabe/test/data,yml。要在測試開始以前引入數據,僅需使用#{fixture /}標籤:

#{fixture delete:'all', load:'data.yml' /}

#{selenium}
    // Open the home page, and check that no error occurred
    open('/')
    waitForPageToLoad(1000)
    assertNotTitle('Application error')
#{/selenium}

還須要檢查另外一個重要的事情,就是在每一個測試開始以前要有一個新的用戶會話。這個會話將保持在瀏覽器的持久cookie中,若是不作清理,它會在兩個連續的測試之間保持。

因此咱們的測試以前,先添加一個特殊的命令:

#{fixture delete:'all', load:'data.yml' /}

#{selenium}
    clearSession()

    // Open the home page, and check that no error occurred
    open('/')
    waitForPageToLoad(1000)
    assertNotTitle('Application error')
#{/selenium}

運行這個測試,確保一切安好。應該會是全綠的結果。

因此咱們能夠開始寫更復雜的測試了。打開主頁面,檢查是否展現了默認的文章。

#{fixture delete:'all', load:'data.yml' /}

#{selenium 'Check home page'}
    clearSession()

    // Open the home page
    open('/')

    // Check that the front post is present
    assertTextPresent('About the model layer')
    assertTextPresent('by Bob, 14 Jun 09')
    assertTextPresent('2 comments , latest by Guest')
    assertTextPresent('It is the domain-specific representation')

    // Check older posts
    assertTextPresent('The MVC application')
    assertTextPresent('Just a test of YABE')
#{/selenium}

咱們使用的是標準的Selenium語法,叫作Selenese

運行它。(經過在新的標籤頁打開連接,你能夠在一個不一樣的窗口中運行)。

run

如今咱們開始測試評論框。添加一個新的#{selenium /}標籤到模板中:

#{selenium 'Test comments'}

    // Click on 'The MVC application post'
    clickAndWait('link=The MVC application')
    assertTextPresent('The MVC application')
    assertTextPresent('no comments')

    // Post a new comment
    type('content', 'Hello')
    clickAndWait('css=input[type=submit]')

    // Should get an error
    assertTextPresent('no comments')
    assertTextPresent('Author is required')
    type('author', 'Me')
    clickAndWait('css=input[type=submit]')

    // Check
    assertTextPresent('Thanks for posting Me')
    assertTextPresent('1 comment')
    assertTextPresent('Hello')
#{/selenium}

而後運行它。啊,出錯了;看來這裏有點問題。

test

原來是驗證碼的問題。這個可模擬不了……只好做弊了嘿嘿。在測試模式中,咱們可須要把任何針對驗證碼的輸入都當作正確的。而在測試模式下,框架的id是test。因此修改掉yabe/app/controllers/Application.javapostComment action來跳過測試模式下的驗證:

…
if(!Play.id.equals("test")) {
    validation.equals(code, Cache.get(randomID)).message("Invalid code. Please type it again");
}
…

如今修改下測試用例。驗證碼那一欄就隨便亂寫好了:

…
type('author', 'Me')
type('code', 'XXXXX')
clickAndWait('css=input[type=submit]')
…

而後從新運行測試,這下應該經過了。

評估代碼覆蓋率

固然咱們尚未完成應用所需的全部測試用例。可是對於咱們的教程來講已經足夠了。在現實的應用中,咱們怎麼知道是否已經寫了足夠的測試用例?咱們須要一個代碼覆蓋率的概念。

Cobertura 模塊使用Cobertura工具生成代碼覆蓋率報告。使用install命令安裝這個模塊:

play install cobertura-{version}

咱們僅需在測試模式下啓動這個模塊。因此在application.conf文件下添加這一行:

# Import the cobertura module in test mode
%test.module.cobertura=${play.path}/modules/cobertura

如今在測試模式下從新啓動應用,打開http://localhost:9000/@tests,選中全部測試並運行。應該是綠光滿面的節奏。

all green

在全部的測試結束後,中止應用,cobertura將生成代碼覆蓋率報告。接着你能夠在瀏覽器打開yabe/test-result/code-coverage/index.html,看一下那份報告。

report

若是從新啓動應用,你也能夠在http://localhost:9000/@cobertura看到它。

如你所見,咱們遠遠沒有完成對應用的全面測試。一個好的測試覆蓋率應該儘可能達到100%,即便檢查全部的代碼是幾乎不可能的。畢竟咱們有時候不得不在測試模式下作一些變通,正如咱們曾對驗證碼作過的同樣。

相關文章
相關標籤/搜索