登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

杨柳千丝,绊惹春风

普通人日记

 
 
 

日志

 
 
关于我

性格还算开朗,为人还算不错。 长相一般,身高一般,能力一般,人是一般。 不会浪漫,不会情调,不会唱歌,不会跳舞,不会吸烟,不爱喝酒,不会开车,爱听老歌

Groovy 和Grails从入门到精通 第四章 grails 介绍(五)  

2010-07-30 20:54:57|  分类: 技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

创建域类

      到日前为止,该应用程序还未做任何实际工作,因此你还需要增加一些类来使应用程序成型。通常先创建一个域类然后再与控制类进行关联。Grails是使用“create-domain-class”命令来创建域类的。该命令在grails-app/domain目录中创建一个新的Grails域类,同是在test/integration目录中创建一个集成测试(integration test)。

注意:create-domain-class创建的是一个整体测试而不是单元测试,因为域类是依赖数据库的,第六章将详细讲解原因。通过把域类测试放入到test/integration目录从而形成一个集成测试,这样能使测试能进入到整个Grails环境中,包括数据库。如果没有这一点,域类不能成为有效的持久性动态域类(Without this, the domain class would not have access to the dynamic methods available to domain classes for persistence

           使用“create-domain-class”创建域类需要提供一个可选的类名,如下所示

> grails create-domain-class todo

      如果没有提供类名,将会在运行时提示输入一个类名。

      执行“create-domain-class”命令输出如下信息:

 

Running script C:\devl\java\grails-1.0\scripts\CreateDomainClass.groovy

[copy] Copying 1 file to C:\devl\workspace\collab-todo\grails-app\domain

Created for Todo

[copy] Copying 1 file to C:\devl\workspace\collab-todo\test\integration

Created Tests for Todo

 

      注意到使用可选的类名运行“create-domain-class”命令,你可以使用小字字母开头,但Grails将自动将其转换成大写字母,这是遵循

标准的Groovy类名规约。列表4-1列出了创建的Todo域类:

 

4-1 Grails创建的Todo域类

                 class Todo {

}

4-1列出的Todo域类看起来只是一个最基础的Groovy类,但如果你学完接下来的两小节和后面的两章,你将会发现这个域类所提供(功能)的比看起来要多得多。

 

实现集成测试(Integration Tests

      正如您在上一节看到的,Grails是通过在每次创建一个域类时生成一个相应的集成测试来忠于其测试规约。列4-2列出了为Todo域类生成的集成测试。

 

4-2 Grails创建的为Todo域类生成的集成测试

class TodoTests extends GroovyTestCase {

void testSomething() {

}

}

注意列4-2的集成测试是从标准Groovy测试用例中扩展出来的,Groovy测试用例是从JUnit测试用例中扩展出现,并加上断言方法(assert methods)规约。生成的集成测试同时包含了一个测试方法模板。

注意:同JUnit测试用例,任何以test为前缀的方法将被当做一个测试方法对待,当测试工具(test harness)运行时,该方法将被执行。

      4-3 列出了Todo集成测试的两个更新测试:一个测试ToString()方法,另一个测试Todo对你的持久性。

 

4-3 Todo集成测试

1 class TodoTests extends GroovyTestCase {

2

3 void setUp() {

4 Todo.list()*.delete()

5 }

6

7 void testPersist() {

8 new Todo(name: "1", createdDate:new Date(), priority: "", status:"").save()

9 new Todo(name: "2", createdDate:new Date(), priority: "", status:"").save()

10 new Todo(name: "3", createdDate:new Date(), priority: "", status:"").save()

11 new Todo(name: "4", createdDate:new Date(), priority: "", status:"").save()

12 new Todo(name: "5", createdDate:new Date(), priority: "", status:"").save()

13

14 assert 5 == Todo.count()

15 }

16

17 void testToString() {

18 def todo = new Todo(name: "Pickup laundry")

19 assertToString(todo, "Pickup laundry")

20 }

21 }

 

列表4-3集成测试包含三个方法。在3-5行的setUp()方法是标准JUnit生命周期(life-cycle方法,它被调用在任何以test为前缀的方法前,经常用来设定测试到一个已知状态。在本例中,这个已知状态是确保数据库中无Todos数据,这是通过Todo类的动态的(dynamiclist()方法实现的。从以上你会发现Grails域类要比看起来要复杂。

      Grails域类中,GROM提供了list()方法,返回一个链表包含了数据库中所有的该类型的数据。     setup()方法中,删除了所有返回在链表中的Todos。你可以通过Groovy扩展操作符(*.)来调用列表中的每个对象的delete()方法,而不需要迭代(iterate)列表中的每个对象。delete()方法从数据库中删除对象实例。

 

=========================================================================

注意:使用list()方法时要注意,因为list()返回数据库中指定类型的所有记录,在数据量大时会引起大量占用内存。

    

     7-15行的testPersist()方法创建了5Todo域类实例,并使用Grails域类动态方法save()保存到数据库中。在testPersist()方法最后使用了Grails域类的另一动态方法count()测试了保存到数据库中的Todo实例个数,在这里使用了assert关键字保证个数的有效。

 ---------------------------------------------------------------------------------------------------------------------------------

示:无论是运行单元测试或是默认启动程序,都会加载一个在内存数据库HSQLDB。这个内存数据库不会保存在硬盘上,所以每次运行测试或启动程序,都会加载一个新的、无数据的内存数据库。在内存数据库中,Hibernate是使用域类创建或更新数据结构。

 ---------------------------------------------------------------------------------------------------------------------------------

      17-20行的testToString()测试方法是一个基础的自我解释型方法,用来测试Todo域类的toString()方法。这里唯一值得关注的是 assertToString()方法,你没有在标准的Junit断言方法(Junit assert method中见到过,这是因为它是在GroovyTestCase类中实现的。

 

运行这个测试工具(Test Harness

      现在可以运行这个测试工具了。测试理所当然的失败了,这是因为现在还没有实现Todo类。看到错误提示后,我们不断增加Todo类的功能和实现,直到测试通过。

      运行测试工具,只需简单执行test-app命令,这个命令执行所有的单元或集成测试,并且为每个测试返回结果。如有错误,还将会产生几个诊断报告。(译注:HTMLXMLText三个版本的测试报告,保存到相应的测试报告目录)。

>grails test-app

现在该命令的输出信息如下:

...

Running script C:\devl\java\grails-1.0\scripts\TestApp.groovy

...

No tests found in test/unit to execute ...

-------------------------------------------------------

Running 2 Integration Tests...

Running test TodoTests...

testPersist...SUCCESS

testToString... FAILURE

Integration Tests Completed in 711ms

-------------------------------------------------------

[junitreport]

Processing C:\devl\workspace\collab-todo\test\reports\TESTS-TestSuites.xml

[junitreport]

Loading stylesheet jar:file:/C:/devl/java/grails-1.0/lib/ant-junit.jar

!/org/apache/tools/ant/taskdefs/optional/junit/xsl/junit-frames.xsl

[junitreport] Transform time: 751ms

Tests failed: 0 errors, 1 failures, 0 compilation errors. View reports in

C:\devl\workspace\collab-todo/test/reports

      测试工具返回信息显示没有进行单元测试,因为没有单元测试添加到test/unit文件夹。同时显示运行了两个集成测试:一个成功,一个失败。因为现在Todo类还没有任何实现,你预想中两个测试都应该是失败。因此,你要考虑并理解为什么testPersist测试能通过,并且改进testPersist方法以确保在没有实现Todo类之前测试是不能通过的。

      列表4-4再次将原来的testPersist测试列举出来

列表4-4 原始的testPersist测试

void testPersist() {

new Todo(name: "1", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "2", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "3", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "4", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "5", createdDate:new Date(), priority: "", status:"").save()

assert 5 == Todo.count()

}

 

列表4-4中,5Todo保存到数据库中,并且确定插入的数据个数是正确的。现在工作正常是因为即使没有实现TodoTodo也可以被保存到数据库中。然而,看一下数据库,你将发现这些记录没有name, createdDate, priority, status属性,因为这些属性还不存在,参数化的构造函数接收参数但并没有映射到属性上(The parameterized constructor happily accepts parameters that do not map to properties,因此这个测试能正确通过。为了让测试更有用,应该至少检测一个属性的返回值是否正确,如列表4-5

列表4-5 改进后的testPersist

void testPersist() {

new Todo(name: "1", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "2", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "3", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "4", createdDate:new Date(), priority: "", status:"").save()

new Todo(name: "5", createdDate:new Date(), priority: "", status:"").save()

assert 5 == Todo.count()

def actualTodo = Todo.findByName('1')

assert actualTodo

assert '1' == actualTodo.name

}

      列表4-5中是在列表4-4的最后加了三行。在保存和确定插入数据个数正确后,使用动态方法findByName(),用名称来查找Todo,关于findByName()方法我们将在第六章讨论。这时再使用断言测试返回的对象是不为null,以及其值正确。

      现在再运行测试工具,两个集成测试都失败了。此外,测试工具提供了JUnit HTML测试报告,可以在test/reports/html目录中找到这个报告,它可以帮助你确定测试为什么会失败。图4-9HTML测试报告。

 

Groovy 和Grails从入门到精通 第四章 grails 介绍(五) - 虹 - 杨柳千丝,绊惹春风

 

                  图4-9测试报告例子

      再研究一下TodoTests,你发看到testPersist错误是因为没有在Todo中找到name属性,所以findByName()不能被正确调用。同样你可以看到testToString()失败是因为返回值不等于期望值。在你重载Todo类的toString()之前,这个类返回的是Grails域类默认的toString()

      此外,除了一个图4-9显示的HTML报告外,还生成了一个textXML报告分别保存在test/reports/plain test/reports目录。
  评论这张
 
阅读(1537)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018