- 浏览: 5176325 次
- 性别:
- 来自: 天津
博客专栏
-
实战 Groovy
浏览量:29446
文章分类
- 全部博客 (639)
- 代码之谜 (6)
- JavaScript quirks (5)
- 程序员 (92)
- Java (93)
- BT编程 (7)
- html/css (64)
- Groovy&Grails (42)
- Android (20)
- C/C++ (5)
- PHP/Perl/Python (46)
- 经典文章 (51)
- CodeIgniter (14)
- JQuery (10)
- 笑话 (4)
- 其他 (32)
- javascript (69)
- 云计算 (0)
- html5 (7)
- 面试 (8)
- google (3)
- nosql (2)
- nodejs (11)
- go (5)
- erlang (1)
- 小常识 (3)
- 冷知识 (5)
- database (4)
- web (12)
- 架构 (12)
- Exception (0)
最新评论
-
jqw1992:
https://www.chromefor.com/libra ...
[福利] 开发者必备的 Chrome 插件——ChromeSnifferPlus -
litjerk:
初步算了一下,目前最最精简的Win98版是5M,他5个小时多敲 ...
让人目瞪口呆的三位世界级电脑大师 -
379855529:
。。似乎重点没说NIO啊,前面基础只是铺垫的很好的,可是我要的 ...
Java NIO与IO的详细区别(通俗篇) -
springmvc_springjpa:
spring mvc demo教程源代码下载,地址:http: ...
一步步开发 Spring MVC 应用 -
匡建武:
Good
四个程序员的一天
测试
自动化测试被看成是Grails中一个重要部分,以 Groovy Tests 为基础执行测试。因此,Grails提供了许多方法,使不管是简单的单元测试,还是高难度的方法测试都能更容易执行。这个章节详细描述了Grails给出的各种不同的测试方法。
你要明白的第一件事是,所有create-*命令,实际上Grails最后都会自动帮它们创建集成好的全部测试实例。
比如你运行下方的create-controller 命令:
grails create-controller simple
Grails不仅在grails-app/controllers/目录下创建了SimpleController.groovy,而且在
test/integration/目录下创建了对它的集成测试实例
SimpleControllerTests.groovy。
,然而Grails不会在这个测试实例里自动生成逻辑代码,这部分需要你自己写。
当你完成这部分逻辑代码,就可以使用test-app执行所有测试实例:
grails test-app
上面的这个命令将输出如下内容:
------------------------------------------------------- Running Unit Tests… Running test FooTests...FAILURE Unit Tests Completed in 464ms … -------------------------------------------------------Tests failed: 0 errors, 1 failures
同时运行结果放在test/reports目录下。你也可以指定名字单独运行一个测试,不需要测试后缀参数:
grails test-app SimpleController
除此之外,你可以以空格隔开同时运行多个实例:
grails test-app SimpleController BookController
1 单元测试
单元测试是对单元块代码的测试。换句话说你在分别测试各个方法或代码段时,不需要考虑它们外层周围代码结构。在Grails框架中,你要特别注意单元测试和集成测试之间的一个不同点,因为在单元测试中,Grails在集成测试和测试运行时,不会注入任何被调用的动态方法。
这样做是有意义的,假如你考虑到,在Grails中各个数据库注入的各自方法(通过使用GORM),和潜在使用的Servlet引擎(通过控制器)。例如,你在
BookController调用如下的一个服务应用:
class MyService { def otherServiceString createSomething() { def stringId = otherService.newIdentifier() def item = new Item(code: stringId, name: "Bangle") item.save() return stringId }
int countItems(String name) { def items = Item.findAllByName(name) return items.size() } }
正如你看到的,这个应用调用了GORM,那么你用在单元测试中怎样处理如上这段代码呢?答案在Grails测试支持类中可以找到。
测试框架
Grails测试插件最核心部分是grails.test.GrailsUnitTestCase类。
它是
GroovyTestCase子类,为Grails应用和组件提供测试工具。这个类为模拟
特殊类型提供了若干方法,并且提供了按Groovy的MockFor和StubFor方式模拟的支持。
正常来说你在看之前所示的MyService例子和它对另外一个应用服务的依赖,以及例子中使用到的动态域类方法会有一点痛苦。你可以在这个例子中使用元类编程和“map as object”规则,但是很快你会发现使用这些方法会变得很糟糕,那我们要怎么用GrailsUnitTestCase写它的测试呢?
import grails.test.GrailsUnitTestCaseclass MyServiceTests extends GrailsUnitTestCase { void testCreateSomething() { // Mock the domain class. def testInstances = [] mockDomain(Item, testInstances)
// Mock the "other" service. String testId = "NH-12347686" def otherControl = mockFor(OtherService) otherControl.demand.newIdentifier(1..1) {-> return testId }
// Initialise the service and test the target method. def testService = new MyService() testService.otherService = otherControl.createMock()
def retval = testService.createSomething()
// Check that the method returns the identifier returned by the // mock "other" service and also that a new Item instance has // been saved. assertEquals testId, retval assertEquals 1, testInstances assertTrue testInstances[0] instanceof Item }
void testCountItems() { // Mock the domain class, this time providing a list of test // Item instances that can be searched. def testInstances = [ new Item(code: "NH-4273997", name: "Laptop"), new Item(code: "EC-4395734", name: "Lamp"), new Item(code: "TF-4927324", name: "Laptop") ] mockDomain(Item, testInstances)
// Initialise the service and test the target method. def testService = new MyService()
assertEquals 2, testService.countItems("Laptop") assertEquals 1, testService.countItems("Lamp") assertEquals 0, testService.countItems("Chair") } }
上面代码出现了一些新的方法,但是一旦对它们进一步解释,你应该很快懂得要使用这些方法是多么容易。首先看testCreateSomething()测试方法里调用的mockDomain()方法,这是
GrailsUnitTestCase类提供的其中一个方法:
def testInstances = [] mockDomain(Item, testInstances)
这个方法可以给给定的类添加所有共同域的方法(实例和静态),这样任何使用它的代码段都可以把它当作一个真正全面的domain 类。举个例子,一旦Item类被模拟了,我们就可以在实例它的时候放心得调用save();那么这时,如果我们调用一个被模拟的domain类的这个方法,要怎么做?很简单,在testInstances数组列表里添加新的实例,这个数组被当成参数传进mockDomain()方法。
下面我们将重点讲解mockFor方法:
def otherControl = mockFor(OtherService)
otherControl.demand.newIdentifier(1..1) {-> return testId }
这段代码功能与Groovy中的MockFor类和StubFor类非常接近,你可以用这个方法模拟任何类。事实上,上述demand语法跟MockFor和StubFor使用的语法一样,所以你在用它时应该不会觉得有差别,当然你要需要频繁注入一个mock实例作为关联,但是你可以简单得调用上述的mock控制对象的createMock()方法,很容易实现。对那些熟悉EasyMock用法的人,它们知道这是otherControl强调了mockFor()返回的对象角色,它是一个控制对象而非mock对象。
testCreateSomething()方法中剩余部分应该很熟悉了,特别是你现在已经知道了save()模拟方法是往testInstances数组里添加实例。我们能确定newIdentifier()模拟方法被调用,因为它返回的值对createSomething()方法返回结果产生直接的影响。那假如情况不是这样呢?我们怎么知道它是否被调用?在MockFor类和StubFor类中,use()方法最后会做这个检查,但是testCreateSomething()方法中没有这个方法,然而你可以调用控制对象的verify()方法。在这个例子中,otherControl对象可以实现。这个方法会执行检查,在newIdentifier()应该被调用但没有被调用的情况下抛出诊断结果。
最后,这个例子中的testCountItems()向我们展示了mockDomain()方法的另外一个特性:
def testInstances = [ new Item(code: "NH-4273997", name: "Laptop"), new Item(code: "EC-4395734", name: "Lamp"), new Item(code: "TF-4927324", name: "Laptop") ] mockDomain(Item, testInstances)
通常手工模拟动态遍历器比较烦人,而且你经常不得不为每次执行设置不同的数组;除了这个之外,假如你决定使用一个不同的遍历器,你就不得不更新测试实例去测试新的方法。感谢mockDomain()方法为一组域实例的动态遍历器提供了一个轻量级的执行实现,把测试数据简单得作为这个方法的第二个参数,模拟遍历器就会工作了。
GrailsUnitTestCase - 模拟方法
你已经看过了一些介绍GrailsUnitTestCase中mock..()方法的例子。
在这部分我们将详细地介绍所有GrailsUnitTestCase中
提供的方法,首先以通用的mockFor()开始。在开始之前,有一个很重要的说明先说一下,使用这些方法可以保证对所给的类做出的任何改变都不会让其他测试实例受影响。这里有个普遍出现且严重的问题,当你尝试通过meta-class编程方法对它自身进行模拟,但是只要你对每个想模拟的类使用任何一个mock..()
方法,这个问题就会消失了。
mockFor(class, loose = false)
万能的mockFor方法允许你对你一个类设置strict或loose请求。
这个方法很容易使用,默认情况下它会创建一个strict模式的mock控制对象,它的方法调用顺序非常重要,你可以使用这个对象详细定义各种需求:
def strictControl = mockFor(MyService) strictControl.demand.someMethod(0..2) { String arg1, int arg2 -> … } strictControl.demand.static.aStaticMethod {-> … }
注意你可以在demand后简单得使用static属性,就可以mock静态方法,然后定义你想mock的方法名字,一个可选的range范围作为它的参数。这个范围决定这个方法会被调用了多少次,所以假如这个方法的执行次数超过了这个范围,偏小或偏大,一个诊断异常就会被抛出。假如这个范围没有定义,默认的是使用“1..1”范围,比如上面定义的那个方法就只能被调用一次。
demand的最后一部分是closure,它代表了这个mock方法的实现部分。closure的参数列表应该与被mock方法的数量和类型相匹配,但是同时你可以随意在closure主体里添加你想要的代码。
像之前提到的,假如你想生成一个你正在模拟类的能用mock实例,你就需要调用mockControl.createMock()。事实上,你可以调用这个方法生成你想要的任何数量的mock实例。一旦执行了test方法,你就可以调用
mockControl.verify()方法检查你想要执行的方法执行了没。
最后,如下这个调用:
def looseControl = mockFor(MyService, true)
将生成一个含有loose特性的mock控制对象,比如方法调用的顺序不重要。
mockDomain(class, testInstances = )
这个方法选一个类作为它的参数,让所有domain类的非静态方法和静态方法的mock实现都可以在这个类调用到。
使用测试插件模拟domain类是其中的一个优势。手工模拟无论如何都是很麻烦的,所以mockDomain()方法帮你减轻这个负担是多么美妙。
实际上,mockDomain()方法提供了domain类的轻量级实现,database只是存储在内存里的一组domain实例。所有的mock方法,save(),get(),findBy*()等都可以按你的期望在这组实例里运行。除了这些功能之外,save()和validate()模拟方法会执行真正的检查确认,包括对唯一的限制条件支持,它们会对相应的domain实例产生一个错误对象。
这里没什么其他要说了,除了插件不支持标准查询语句和HQL查询语句模拟。假如你想使用其中的一个,你可以简单得手工mock相应的方法,比如用mockFor()方法,或用真实的数据测试一个集成实例。
mockForConstraintsTests(class, testInstances = )
这个方法可以对domain类和command对象进行非常详细地模拟设置,它允许你确认各种约束是否按你想要的方式执行。
你测试domain约束了?如果没有,为什么没有?如果你的回答是它们不需要测试,请你三思。你的各种约束包含逻辑部分,这部分逻辑很容易产生bug,而这类bug很容易被捕捉到,特别的是save()允许失败也不会抛出异常。而如果你的回答是太难或太烦,现在这已经不再是借口了,可以用mockForConstraintsTests()解决这个问题。
这个方法就像mockDomain()方法的简化版本,简单得对所给的domain类添加一个validate()方法。你所要做的就是mock这个类,创建带有属性值的实例,然后调用validate()方法。你可以查看domain实例的errors属性判断这个确认方法是否失败。所以假如所有我们正在做的是模拟validate()方法,那么可选的测试实例数组参数呢?这就是我们为什么可以测试唯一约束的原因,你很快就可以看见了。
那么假设我们拥有如下的一个简单domain类:
class Book { String title String authorstatic constraints = { title(blank: false, unique: true) author(blank: false, minSize: 5) } }
不要担心这些约束是否合理,它们在这仅仅是示范作用。为了测试这些约束,我们可以按下面方法来做:
class BookTests extends GrailsUnitTestCase { void testConstraints() { def existingBook = new Book(title: "Misery", author: "Stephen King") mockForConstraintsTests(Book, [ existingBook ])// Validation should fail if both properties are null. def book = new Book() assertFalse book.validate() assertEquals "nullable", book.errors["title"] assertEquals "nullable", book.errors["author"]
// So let's demonstrate the unique and minSize constraints. book = new Book(title: "Misery", author: "JK") assertFalse book.validate() assertEquals "unique", book.errors["title"] assertEquals "minSize", book.errors["author"]
// Validation should pass! book = new Book(title: "The Shining", author: "Stephen King") assertTrue book.validate() } }
你可以在没有进一步解释的情况下,阅读上面这些代码,思考它们正在做什么事情。我们会解释的唯一一件事是errors属性使用的方式。第一,它返回了真实的Spring Errors实例,所以你可以得到你通常期望的所有属性和方法。第二,这个特殊的Errors对象也可以用如上map/property方式使用。简单地读取你感兴趣的属性名字,map/property接口会返回被确认的约束名字。注意它是约束的名字,不是你所期望的信息内容。
这是测试约束讲解部分。我们要讲的最后一件事是用这种方式测试约束会捕捉一个共同的错误:typos in the "constraints" property。正常情况下这是目前最难捕捉的一个bug,还没有一个约束单元测试可以直接简单得发现这个问题。
mockLogging(class, enableDebug = false)
这个方法可以给一个类增加一个mock的log属性,任何传递给mock的logger的信息都会输出到控制台的。
mockController(class)
此方法可以为指定类添加mock版本的动态控制器属性和方法,通常它和ControllerUnitTestCase一起连用。
mockTagLib(class)
此方法可以为指定类添加mock版本的动态tablib属性和方法,通常它和TagLibUnitTestCase
一起连用。
2 集成测试
集成测试与单元测试不同的是在测试实例内你拥有使用Grails环境的全部权限。Grails将使用一个内存内的HSQLDB数据库作为集成测试,清理每个测试之间的数据库的数据。
测试控制器
测试控制器之前你首先要了解Spring Mock Library。
实质上,Grails自动用 MockHttpServletRequest,MockHttpServletResponse,和 MockHttpSession 配置每个测试实例,你可以使用它们执行你的测试用例。比如你可以考虑如下controller:
class FooController {def text = { render "bar" }
def someRedirect = { redirect(action:"bar") } }
它的测试用例如下:
class FooControllerTests extends GroovyTestCase {void testText() { def fc = new FooController() fc.text() assertEquals "bar", fc.response.contentAsString }
void testSomeRedirect() {
def fc = new FooController() fc.someRedirect() assertEquals "/foo/bar", fc.response.redirectedUrl } }
在上面的实例中,返回对象是一个MockHttpServletResponse实例,你可以使用这个实例获取写进返回对象的contentAsString值,或是跳转的URL。
这些Servlet
API的模拟版本全部都很更改,不像模拟之前那样子,因此你可以对请求对象设置属性,比如contextPath等。
Grails在集成测试期间调用actions不会自动执行interceptors,你要单独测试拦截器,必要的话通过functional testing测试。
用应用测试控制器
假如你的控制器引用了一个应用服务,你必须在测试实例里显示初始化这个应用。
举个使用应用的控制器例子:
class FilmStarsController { def popularityServicedef update = { // do something with popularityService } }
相应的测试实例:
class FilmStarsTests extends GroovyTestCase { def popularityServicepublic void testInjectedServiceInController () { def fsc = new FilmStarsController() fsc.popularityService = popularityService fsc.update() } }
测试控制器command对象
使用command对象,你可以给请求对象request提供参数,当你调用没有带参数的action处理对象时,它会自动为你做command对象工作。
举个带有command对象的控制器例子:
class AuthenticationController { def signup = { SignupForm form -> … } }
你可以如下对它进行测试:
def controller = new AuthenticationController() controller.params.login = "marcpalmer" controller.params.password = "secret" controller.params.passwordConfirm = "secret" controller.signup()
Grails把signup()的调用自动当作对处理对象的调用,利用模拟请求参数生成command对象。在控制器测试期间,params通过Grails的模拟请求对象是可更改的。
测试控制器和render方法
render方法允许你在一个action主体内的任何一个地方显示一个定制的视图。例如,考虑如下的例子:
def save = { def book = Book(params) if(book.save()) { // handle } else { render(view:"create", model:[book:book]) } }
上面举的这个例子中,处理对象用返回值作这个模型的结果是不可行的,相反结果保存在控制对象的modelAndView属性当中。modelAndView属性是Spring MVC ModelAndView类的一个实例,你可以用它测试一个action处理后的结果:
def bookController = new BookController()
bookController.save()
def model = bookController.modelAndView.model.book
模拟生成请求数据
如果你测试一个action请求处理对象需要类似REST web应用的请求参数,你可以使用Spring MockHttpServletRequest对象实现。例如,考虑如下这个action,它执行一个进来请求的数据邦定:
def create = {
[book: new Book(params['book']) ]
}
假如你想把book参数模拟成一个XML请求对象,你可以按如下方法做:
void testCreateWithXML() { def controller = new BookController() controller.request.contentType = 'text/xml' controller.request.contents = '''<?xml version="1.0" encoding="ISO-8859-1"?> <book> <title>The Stand</title> … </book> '''.getBytes() // note we need the bytesdef model = controller.create() assert model.book assertEquals "The Stand", model.book.title }
同样你可以通过JSON对象达到这个目的:
void testCreateWithJSON() { def controller = new BookController() controller.request.contentType = "text/json" controller.request.content = '{"id":1,"class":"Book","title":"The Stand"}'.getBytes()def model = controller.create() assert model.book assertEquals "The Stand", model.book.title
}
使用JSON,也不要忘记对class属性指定名字,绑定的目标类型。在XML里,在book节点内这些设置隐含的,但是使用JSON你需要这个属性作为JSON包的一部分。
更多关于REST web应用的信息,可以参考REST章节。
测试Web Flows
测试Web
Flows需要一个特殊的测试工具grails.test.WebFlowTestCase,它继承Spring Web
Flow的
AbstractFlowExecutionTests
类。Testing Web Flows
requires a special test harness called grails.test.WebFlowTestCase
which sub classes Spring Web Flow's AbstractFlowExecutionTests
class.
WebFlowTestCase子类必须是集成测试实例Subclasses of
WebFlowTestCase
must be integration
tests
例如在下面的这个小flow情况下:
class ExampleController { def exampleFlow = { start { on("go") { flow.hello = "world" }.to "next" } next { on("back").to "start" on("go").to "end" } end() } }
接着你需要让测试工具知道使用什么样的flow定义。通过重载getFlow抽象方法可以实现:
class ExampleFlowTests extends grails.test.WebFlowTestCase { def getFlow() { new ExampleController().exampleFlow } … }
假如你需要指定一个flow标识,你可以通过重载getFlowId方法实现,同时默认情况下是一个测试实例:
class ExampleFlowTests extends grails.test.WebFlowTestCase { String getFlowId() { "example" } … }
一旦这在你的测试实例里实现了,你需要用startFlow方法开始启动这个flow,这个方法会返回ViewSelection对象:
void testExampleFlow() { def viewSelection = startFlow()assertEquals "start", viewSelection.viewName … }
如上所示,你可以通过使用ViewSelection对象的viewName属性,检查你是否是正确的。触发事件你需要使用signalEvent方法:
void testExampleFlow() { … viewSelection = signalEvent("go") assertEquals "next", viewSelection.viewName assertEquals "world", viewSelection.model.hello }
这里我们可以给flow发送信号执行go事件,这导致了到next状态的转变。在上面的这个例子中转变的结果把一个hello变量放进flow范围。我们可以检查如上ViewSelection的model属性测试这个变量的值。
测试标签库
其实测试标签库是一件很容易的事,因为当一个标签被当作一个方法执行时,它会返回一个字符串值。所以例如你拥有如下的一个标签库:
class FooTagLib { def bar = { attrs, body -> out << "<p>Hello World!</p>" }def bodyTag = { attrs, body -> out << "<${attrs.name}>" out << body() out << "</${attrs.name}>" } }
相应的测试如下:
class FooTagLibTests extends GroovyTestCase {void testBarTag() { assertEquals "<p>Hello World!</p>", new FooTagLib().bar(null,null) }
void testBodyTag() { assertEquals "<p>Hello World!</p>", new FooTagLib().bodyTag(name:"p") { "Hello World!" } } }
注意在第二个例子的testBodyTag中,我们传递了返回标签主体内容的代码块作为内容,把标签主体内容作为字符串比较方便。
使用GroovyPagesTestCase测试标签库
除了上述简单的标签库测试方法之外,你也可以使用grails.test.GroovyPagesTestCase类测试标签库。
GroovyPagesTestCase类是常见GroovyTestCase的子类,它为GSP显示输出提供实用方法。
GroovyPagesTestCase类只能在集成测试中使用。
举个时间格式化标签库的例子,如下:
class FormatTagLib {
def dateFormat = { attrs, body ->
out << new java.text.SimpleDateFormat(attrs.format) << attrs.date
}
}
可以按如下方法进行测试:
class FormatTagLibTests extends GroovyPagesTestCase { void testDateFormat() { def template = '<g:dateFormat format="dd-MM-yyyy" date="${myDate}" />'def testDate = … // create the date assertOutputEquals( '01-01-2008', template, [myDate:testDate] ) } }
你也可以使用GroovyPagesTestCase的applyTemplate方法获取GSP的输出结果:
class FormatTagLibTests extends GroovyPagesTestCase { void testDateFormat() { def template = '<g:dateFormat format="dd-MM-yyyy" date="${myDate}" />'def testDate = … // create the date def result = applyTemplate( template, [myDate:testDate] )
assertEquals '01-01-2008', result } }
测试Domain类
用GORM API测试domain类是一件很简单的事情,然而你还要注意一些事项。第一,假如你在测试查询语句,你将经常需要flush以便保证正确的状态持久保存到数据库。比如下面的一个例子:
void testQuery() { def books = [ new Book(title:"The Stand"), new Book(title:"The Shining")] books*.save()assertEquals 2, Book.list().size() }
这个测试实际上会失败,因为调用save方法的时候,save方法不会真的持久保存book实例。调用save方法仅仅是向Hibernate暗示在将来的某个时候这些实例应该会被保存。假如你希望立即提交这些改变,你需要flush它们:
void testQuery() { def books = [ new Book(title:"The Stand"), new Book(title:"The Shining")] books*.save(flush:true)assertEquals 2, Book.list().size() }
在这个案例中我们传递了flush的true值作为参数,更新将马上被保存,因此对此后的查询语句也有效。
3 功能测试
功能测试是测试正在运行的应用,经常自动化较难实现。Grails没有发布任何功能测试开箱即用支持,但是通过插件实现了对 Canoo WebTest 的支持。
首先按如下的命令按照Web Test:
grails install-plugin webtest
参考reference on the wiki ,它里面了解释怎么使用Web Test和Grails。 Show details
发表评论
-
实战 Groovy: 用 Groovy 打造服务器端
2010-07-10 11:07 2737Groovlet 和 GroovyServer P ... -
实战 Groovy: 用 Groovy 生成器作标记
2010-07-10 11:07 2079Groovy 生成器让您能够利用诸如 Swing 这样 ... -
实战 Groovy: for each 剖析
2010-07-10 11:07 18217在这一期的 实战 Groovy 中,Scott Davi ... -
实战 Groovy: 用 Groovy 进行 Ant 脚本编程
2010-07-10 11:07 2071Ant 和 Maven 两者在构建处理工具的世界中占统 ... -
实战 Groovy: 在 Java 应用程序中加一些 Groovy 进来
2010-07-10 11:06 4342您有没有想过在自己相对复杂的 Java 程序中嵌入 G ... -
实战 Groovy: Groovy 的腾飞
2010-07-10 11:06 2204随着 Groovy JSR-1(及其后续发行版本)的发 ... -
实战 Groovy: 用 curry 过的闭包进行函数式编程
2010-07-10 11:06 3266在 Groovy 中处处都是闭包,Groovy 闭包惟 ... -
实战 Groovy: 关于 MOP 和迷你语言
2010-07-10 11:06 2080将耳朵贴到地上仔细听 —— MOP 正在前进!了解一下 ... -
实战 Groovy: 用 Groovy 更迅速地对 Java 代码进行单元测试
2010-07-10 11:06 2310不久以前,developerWor ... -
实战 Groovy: 构建和解析 XML
2010-07-10 11:05 7135通过本文,您将了解 ... -
实战 Groovy: 用 Groovy 进行 JDBC 编程
2010-07-10 11:05 5205这个月,随着 Andrew G ... -
实战 Groovy: 美妙的操作符
2010-07-10 11:05 2297Java™ 取消了操作符重载,但是新兴的 Groovy ... -
实战 Groovy: 使用 Groovy 模板进行 MVC 编程
2010-07-10 11:04 2936视图是 MVC 编程的一个重要部分,而 MVC 编程本 ... -
实战 Groovy: 用 Groovy 减少代码冗余
2010-07-10 11:04 2069Groovy 简洁的语法将 ... -
实战 Groovy: Groovy:Java 程序员的 DSL
2010-07-10 11:04 3087Groovy 专家 Scott Davis 将重新开始 ... -
精通 Grails: 构建您的第一个 Grails 应用程序
2010-07-06 09:37 1656Java™ 程序员不需要 ... -
Grails 部署
2010-07-06 09:36 6086部署 Grails可以使用很多种方式来部署,每一种 ... -
Grails 脚手架
2010-07-05 08:20 4085脚手架 根据指定的领域类,脚手架为你自动生成 ... -
Grails Grails 与 Hibernate
2010-07-05 08:19 2708Grails 与 Hibernate 如果 GOR ... -
Grails Grails和 Spring
2010-07-05 08:19 7927Grails和 Spring 这一节适合于高级用户 ...
相关推荐
10. **Grails测试**:了解单元测试、集成测试和功能测试,以及使用Spock框架编写测试的重要性。 11. **Grails插件**:Grails的插件系统允许开发者扩展框架功能,学习如何使用和开发插件。 12. **部署与性能优化**...
10. **Grails 测试** - 提供了全面的测试框架,包括单元测试、集成测试和功能测试。 - 可以使用 Spock 测试框架编写行为驱动的测试用例。 11. **Grails 部署** - Grails 应用可以打包为 WAR 文件部署到 Tomcat ...
8. **测试支持**:Grails提供了全面的测试工具,包括单元测试、集成测试和功能测试,确保代码质量。`grails test-app`命令即可运行所有相关的测试。 9. **国际化与本地化**:Grails内置了i18n支持,允许开发者轻松...
《Grails1.1中文文档》是Grails 1.1版本的官方中文指南,包含了框架的详细介绍、安装指南、基本概念、MVC模式的应用、GORM的使用、服务层、控制器、视图、国际化、测试等方面的内容。通过阅读这份文档,开发者可以...
Grails内置了测试框架,支持单元测试、集成测试和功能测试。通过`test-app` 命令,可以对应用的各个部分进行自动化测试。 十、国际化与本地化 Grails支持多语言环境,通过`messages.properties` 文件实现国际化,...
《Grails CRUD与SwingLibrary在自动化测试中的应用》 在IT行业中,高效且准确的自动化测试是确保软件质量的关键环节。本篇文章将探讨两个重要的工具:Grails CRUD和SwingLibrary,它们分别在Web应用开发和Swing UI...
在Eclipse中,Grails项目的结构和管理将得到很好的支持,包括源代码编辑、构建、测试和调试。 注意,尽管Eclipse对Grails的支持相比IntelliJ IDEA和NetBeans可能稍显不足,但通过Groovy Eclipse插件的配置,开发者...
测试是确保软件质量的关键环节,Grails提供了一套完整的测试框架,包括单元测试、集成测试和功能测试。这些测试可以针对不同的层次和需求来编写,以确保应用程序的各个组件能够正常工作。 安全是一个复杂的话题,...
- **运行和测试应用**:指南涵盖了如何启动、测试和部署Grails应用,包括单元测试和集成测试。 - **部署**:讲解了在各种Java EE容器中部署Grails应用的方法。 2. **配置**: - **基本配置**:讨论了Grails的...
Grails 鼓励全面的测试实践,包括单元测试、集成测试和功能测试。它提供了内置的测试框架,如 Spock,使得编写测试变得简单直观。 **国际化 (i18n) 支持** Grails 提供了对多语言环境的支持,通过 properties 文件...
这意味着您可以使用test-app运行Cucumber功能,并且结果将包含在常规grails测试报告中。 当前,该插件仅将Cucumber测试类型注册到功能测试阶段。 要运行Cucumber功能,可以通过以下命令之一调用grails: grails ...
- **测试Grails应用**:Grails内置了单元测试和集成测试框架,通过`grails test`命令执行各种类型的测试。 6. **部署** Grails应用可以部署到多种Java EE容器,如Tomcat、Jetty等。使用`grails war`命令打包应用...
10. **测试**:文档会覆盖单元测试、集成测试和功能性测试,包括`grails test-app`命令的用法和测试框架的特性。 11. **部署**:最后,文档会介绍如何将Grails应用部署到不同的服务器环境,如Tomcat、Jetty等。 ...
10. **Testing**:了解Grails的测试框架,包括单元测试、集成测试和功能测试,以及如何编写和运行测试。 11. **持续集成与部署**:设置Jenkins或其他CI工具,进行自动化构建和部署,以及Grails应用的发布流程。 书...
Grails提供了完整的测试框架,包括单元测试、集成测试和功能测试。`@Integration`和`@Functional`注解分别用于集成测试和功能测试,确保代码质量。 9. **最佳实践** - 使用Scaffolding快速生成CRUD操作 - 利用...
- **性能对比**:通过测试证明 Grails 的性能远超过 Ruby on Rails。 #### 七、未来展望 - **Groovy 与 Java 7**:随着 Java 7 的推出,Groovy 的发展前景更加明朗。 - **Grails 社区的发展**:随着越来越多的...
8. **测试支持**: Grails 提供了全面的测试框架,包括单元测试、集成测试和行为驱动开发(BDD)测试。这使得开发者可以在开发过程中进行持续测试,确保代码质量。 9. **国际化支持**: Grails 内置了i18n(国际化)...