play手把手教你创建一个博客项目0完整的应用程序测试.docx
《play手把手教你创建一个博客项目0完整的应用程序测试.docx》由会员分享,可在线阅读,更多相关《play手把手教你创建一个博客项目0完整的应用程序测试.docx(10页珍藏版)》请在冰豆网上搜索。
play手把手教你创建一个博客项目0完整的应用程序测试
10.完整的应用程序测试
现在,我们已经结束了博客引擎的编码工作,但对项目来说还没有完成,为了让我们的代码能够完全正确的工作,我们还需要对项目进行测试。
当然,我们之前已经为yabe的模型层功能书写的单元测试,并且确信博客引擎的核心功能已经进行了完好的测试,但是对于一个web应用程序来说模型层只是其中的一部分,我们还需要确定web接口能否按预期的目标一样正常工作。
也就是说还需要测试yabe博客引擎的控制器层,甚至需要对UI自身进行测试,比如我们的JavaScript代码。
测试控制器部分
Play提供了一种功能,就是使用JUnit来直接测试应用程序的控制器。
我们把这些测试叫做‘功能性测试’,这是因为我们打算测试web应用程序的完整功能。
基本上,一个功能性测试将直接调用Play的ActionInvoker,和一个HTTP请求相似。
因此我们需要给出一个HTTP方法、一个URI和多个HTTP参数。
Play之后会路由这些请求,调用相应的action,并且回发到填写的响应(filledresponse)。
之后,你就可以对之进行分析,以检查响应内容是否你所预期的。
接下来让我们书写第一个功能性测试代码,打开yabe/test/ApplicationTest.java单元测试:
importorg.junit.*;
importplay.test.*;
importplay.mvc.*;
importplay.mvc.Http.*;
importmodels.*;
publicclassApplicationTestextendsFunctionalTest{
@Test
publicvoidtestThatIndexPageWorks(){
Responseresponse=GET("/");
assertIsOk(response);
assertContentType("text/html",response);
assertCharset("utf-8",response);
}
}
现在看,它还是一个标准的JUnit测试。
请注意,在这里我们使用Play的FunctionalTest超类,主要是为了得到所有可用的工具。
这个测试只对应用程序的主页进行了测试(/URL渲染一个HTML响应,以‘200OK’作为状态代码)。
接下来,我们将检查管理区域(administrationarea)的安全工作能否正常工作。
在ApplicationTest.java里添加下面这个新测试:
…
@Test
publicvoidtestAdminSecurity(){
Responseresponse=GET("/admin");
assertStatus(302,response);
assertHeaderEquals("Location","/login",response);
}
…
现在,用playtest命令把yabe应用程序运行于测试模式,打开,选择ApplicationTest.java测试并运行。
是绿色的吗?
当然!
通过这种方式,我们可以对所有的应用程序功能性进行测试,但把这用于测试一个基于html的web应用程序时,这并不是最好的方式。
对于我们的博客引擎项目来说,直接在真实的浏览器进行测试可能会更好。
这就是play的‘Seleniumtests’测试要干的事。
这种基于“功能性测试”的JUnit仍旧很有用,特别是用于测试一个返回非html响应(比如JSON或XML)的Webservices时。
书写Selenium测试代码
是一个专用于测试web应用程序的测试工具。
这个工具最酷的就是Selenium允许我们在一个浏览器里直接运行测试套件,由于它使用的是真实的浏览器,因此,我们可以确定测试通过后,项目就可以在生产环境下完美的运行。
一个Selenium测试套件就是一个特殊的html文件。
HTMLsyntaxrequiredbySelenium必须使用的HTML语句比较单调(使用HTML表格元素进行数据格式化显示),好消息是play将使用play模板引擎和一系列支持简单Selenium表示语法的标签来帮助你生成这些元素)。
使用模板最有趣的特点是你根本不需要‘staticscenarios’,并且可以使用play模板强大的功能(如循环、条件块)来书写更复杂的测试。
然而,你仍旧可以继续在模板里使用原始的HTMLSelenium语法,如果需要的话,还可以忘记特定的Selenium标签。
如果你使用多个用于生成testscenarios(比如)的Selenium工具中的一个,这将变得非常有趣。
新创建的play应用程序的默认测试套件已经包含了一个Selenium测试,打开yabe/test/Application.test.html文件:
*{YoucanuseplainSeleniumcommandsusingtheseleniumtag}*
#{selenium}
//Openthehomepage,andcheckthatnoerroroccurred
open('/')
waitForPageToLoad(1000)
assertNotTitle('Applicationerror')
#{/selenium}
运行这个测试应该不会有任何问题。
它只打开了主页,并检测页面内容是否包含了‘Applicationerror’文本。
然而,和任何复杂的测试一样,在导航到应用程序并进行测试之前,你需要设置一系列众所周知的数据,我们当然需要重用fixture概念,并且在开始测试之前使用yabe/test/data.yml文件,#{fixture/}标签导入这些测试数据:
#{fixturedelete:
'all',load:
'data.yml'/}
#{selenium}
//Openthehomepage,andcheckthatnoerroroccurred
open('/')
waitForPageToLoad(1000)
assertNotTitle('Applicationerror')
#{/selenium}
另外一个重要的事情就是我们要在测试启动时检查我们是否有一个最新的用户session。
这个session将存储在浏览器的临时cookie里,你应该在两个连续的测试运行操作期间保持同一个session,因此,让我们用一个特定的命令开始测试:
#{fixturedelete:
'all',load:
'data.yml'/}
#{selenium}
clearSession()
//Openthehomepage,andcheckthatnoerroroccurred
open('/')
waitForPageToLoad(1000)
assertNotTitle('Applicationerror')
#{/selenium}
运行这个测试,并确定没有错误发生,结果应该是绿色的。
接下来我们将书写很特殊的测试,测试打开主页后检查默认的博文是否显示出来:
#{fixturedelete:
'all',load:
'data.yml'/}
#{selenium'Checkhomepage'}
clearSession()
//Openthehomepage
open('/')
//Checkthatthefrontpostispresent
assertTextPresent('Aboutthemodellayer')
assertTextPresent('byBob,14Jun09')
assertTextPresent('2comments,latestbyGuest')
assertTextPresent('Itisthedomain-specificrepresentation')
//Checkolderposts
assertTextPresent('TheMVCapplication')
assertTextPresent('JustatestofYABE')
#{/selenium}
在这里,我们使用了标准的Selenium语法,它叫。
运行它(你可以运行于一个不同的浏览器窗口里)。
我们现在就可以测试评论窗体了,只需要添加一个#{selenium/}到模板里即可:
#{selenium'Testcomments'}
//Clickon'TheMVCapplicationpost'
clickAndWait('link=TheMVCapplication')
assertTextPresent('TheMVCapplication')
assertTextPresent('nocomments')
//Postanewcomment
type('content','Hello')
clickAndWait('css=input[type=submit]')
//Shouldgetanerror
assertTextPresent('nocomments')
assertTextPresent('Authorisrequired')
type('author','Me')
clickAndWait('css=input[type=submit]')
//Check
assertTextPresent('ThanksforpostingMe')
assertTextPresent('1comment')
assertTextPresent('Hello')
#{/selenium}
再次才能,哦,失败了!
这里有一个严重的问题出现。
我们事实上不能正确测试captcha验证码机制,因此,我们必须搞一些欺骗手段。
在测试模式下,我们将验证任何代码作为一个正确的验证码。
我们知道当框架a.Weknowthatwe’reintestmodewhentheframeworkidistest.Solet’smodifythepostCommentactionintheyabe/app/controllers/Application.javafiletoskipthisvalidationintestmode:
…
if(!
Play.id.equals("test")){
validation.equals(code,Cache.get(randomID)).message("Invalidcode.Pleasetypeitagain");
}
…
Nowjustmodifythetestcasetotypeanycodeinthetextfield,asis:
…
type('author','Me')
type('code','XXXXX')
clickAndWait('css=input[type=submit]')
…
Andnowrunthetestagain,itshouldwork.
Measuringcodecoverage
Ofcoursewehaven’twrittenallrequiredtestcasesfortheapplication.Butit’senoughforthistutorial.Nowinareal-worldproject,howcanweknowifwehavewrittenenoughtestcases?
Weneedsomethingcalled‘codecoverage’.
Thegeneratescodecoveragereportsusingthetool.Installthemoduleusingtheinstallcommand:
playinstallcobertura-{version}
Weneedtoenablethismoduleonlyfortestmode.Soaddthislinetotheapplication.conffile,andrestarttheapplicationintestmode.
#Importthecoberturamoduleintestmode
%test.module.cobertura=${play.path}/modules/cobertura
NowreopenthebrowserattheURL,selectalltestsandrunthem.Allshouldbegreen.
Whenalltestsarepassed,stoptheapplicationandcoberturawillthengeneratethecodecoveragereport.Youcanthenopentheyabe/test-result/code-coverage/index.htmlinyourbrowserandcheckthereport.
Ifyoustarttheapplicationagain,youcanalsoviewitat.
Asyouseewe’refarfromtestingalloftheapplication’scases.Agoodtestingsuiteshouldapproach100%,evenifitisofcoursenearlyimpossibletocheckallthecode.Typicallybecauseweoftenneedtohackintestmode,likewedidforthecaptcha.