slides631 paulking agile2007 groovy 2 631
Post on 03-Apr-2018
217 Views
Preview:
TRANSCRIPT
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
1/70
Submission631
ASERT2007
Agile 2007 - 1
Groovy Tutorial
Dr Paul King
ASERT, Australia
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
2/70
Agile 2007 - 2
Submission631
ASERT2007
Topics
Introduction
Language Basics Closures
Processing XML
Accessing Databases Other Features
Testing with Groovy
Further Integration
Grails
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
3/70
Agile 2007 - 3
Submission631
ASERT2007
What is Groovy?
Groovy is like a super versionof J ava. It can leverage Java'senterprise capabilities but also
has cool productivity features like closures,
DSL support, builders and dynamic typing.
A slow and steady start but now gaining in
momentum; growing in maturity & mindshare
Groovy
Recipes
PragmaticBookshelf
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
4/70
Agile 2007 - 4
Submission631
ASERT2007
What is Groovy? an agile and dynamic language for the Java Virtual Machine
builds upon the strengths of Java but has additional powerfeatures inspired by languages like Python, Ruby & Smalltalk
makes modern programming features available to Javadevelopers with almost-zero learning curve
supports Domain Specific Languages and other compactsyntax so your code becomes easy to read and maintain
makes writing shell and build scripts easy with its powerfulprocessing primitives, OO abilities and an Ant DSL
increases developer productivity byreducing scaffolding code whendeveloping web, GUI, database orconsole applications
simplifies testing by supporting unittesting and mocking out-of-the-box
seamlessly integrates with all existingJava objects and libraries
compiles straight to Java bytecode so youcan use it anywhere you can use Java
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
5/70
Agile 2007 - 5
Submi
ssion631
ASERT2007
The Landscape of JVM Languages
Java bytecode calls
forstatic types
Dynamic features call
fordynamic types
optional
types
The terms Java Virtual Machine and JVM mean a Virtual Machine for the Java platform.
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
6/70
Agile 2007 - 6
Submission631
ASERT2007
Usages of Scripting for Your Java Platform Project
Super glue
Combine building blocks Groovy glues
infrastructure andbusiness logic together
Melted core
Keep domain modelsadaptable
Groovy supports smartconfigs and DSLs
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
7/70Agile 2007 - 7
Submission631
ASERT2007
Leverage Dynamic Language Features
Meta-Object Protocolcan change structureand behaviour atruntime
Intercepting methodcalls
Compares to AOPor Mixin
Tracing and debuggingMocks and stubs
Enhance the Java
Development Kit (JDK) with
richer functionality (GDK)
No moreincomplete library smell
Behaviour becomes
injectable, even
non-intrusive! Avoid duplication
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
8/70Agile 2007 - 8
Submission631
ASERT2007
Groovy StarterSystem.out.println("Hello, World!"); // optional semicolon,
println 'Hello, World!' // System.out, brackets,// main() method
def name = 'Guillaume' // dynamic typingprintln "$name, I'll get the car." // GString
String longer = """${name}, the caris in the next row.""" // multi-line string
// with static typing
assert 0.5 == 1/2 // BigDecimal equals()
defprintSize(obj) { // optional duck typingprint obj?.size() // safe dereferencing
}
def animals = ['ant', 'bee', 'cat'] // native list syntaxassert animals.every { pet -> // closure support
pet < 'dog' // overloading}
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
9/70Agile 2007 - 9
Submission631
ASERT2007
Java Platforms Dynamic Friend Flat learning curve
Leverage any Java library (JDK)
Syntax like Java (expressive++) Java object and runtime model
Java architecture (threading, security,
debugging)
Compiles down to standard Java bytecode
precompiled or with runtime compilation
No impedance mismatch with parent language!
Supports duck typing and static typing
Only dynamic language to support Annotations
Combined compiler for shared Java/Groovy object model
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
10/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
11/70Agile 2007 - 11
Submission631
ASERT2007
Topics
Introduction
Language Basics
Closures
Processing XML
Accessing Databases Other Features
Testing with Groovy
Further Integration
Grails
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
12/70Agile 2007 - 12
Submission631
ASERT2007
Strings
Several forms Single quotes for
simple strings
Double quotes for
GStrings which
support variable
expansion Slashy strings
behave like GStrings
but preserve
backslashes (greatfor regex and
directory names)
Multi-line versions
// normal strings
deffirstname = 'Kate'defsurname= "Bush"assert firstname * 2 == 'KateKate'
// GStringdeffullname = "$firstname $surname"assert fullname == 'Kate Bush'assert fullname - firstname == ' Bush'assert fullname.padLeft(10) ==
' Kate Bush'
// indexing (including ranges)assert fullname[0..3] == firstnameassert fullname[-4..-1] == surnameassert fullname[5, 3..1] == 'Beta'
S
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
13/70
Strings
Agile 2007 - 13
Submission631
ASERT2007
// slashy string: (almost) no escapingdefpath = /C:\Windows\System32/
defplain = '\n\r\t\b\\\f\$'assert plain.size() == 7defslashy = /\n\r\t\b\\\f\$/
assert slashy.size() == 14
// late binding trick with closuresfullname = "${ -> firstname} $surname"assert fullname == 'Kate Bush'firstname = 'George'
surname = 'Clooney'assert fullname == 'George Bush'
// Multi-line stringsdeftwister = '''\
She sells, sea shellsBy the sea shore'''assert twister.split('\n').size() == 2
defaddress = """$fullname
123 First AveNew York""".trim()assert address.split('\n').size() == 3
println """----------------------
| $fullname |
| 123 First Ave |
| New York |
----------------------
"""
S i
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
14/70
Strings
Agile 2007 - 14
Submission631
ASERT2007
// more substringsstring = 'hippopotamus'assert string - 'hippo' - 'mus' + 'to' == 'potato'
assert string.replace('ppopotam','bisc') == 'hibiscus'
// processing charactersassert 'apple'.toList() == ['a', 'p', 'p', 'l', 'e']//also: 'apple' as String[], 'apple'.split(''), 'apple'.each{}string = "an apple a day"
assert string.toList().unique().sort().join() == ' adelnpy'
// reversing chars/wordsassert 'string'.reverse() == 'gnirts'
string = 'Yoda said, "can you see this?"'
revwords = string.split(' ').toList().reverse().join(' ')assert revwords == 'this?" see you "can said, Yoda'
words = ['bob', 'alpha', 'rotator', 'omega', 'reviver']long_palindromes = words.findAll{ w -> w == w.reverse() && w.size() > 5 }assert long_palindromes == ['rotator', 'reviver]
N b
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
15/70
Numbers
Agile 2007 - 15
Submission631
ASERT2007
def x = 3def y = 4assert x + y == 7assert x.plus(y) == 7
assert x instanceof Integer
assert 0.5 == 1/2 // uses BigDecimal arithmetic as defaultdef a = 2 / 3 // 0.6666666666defb = a.setScale(3, BigDecimal.ROUND_HALF_UP)assertb.toString() == '0.667'
assert 4 + 3 == 7 // 4.plus(3)assert 4 - 3 == 1 // 4.minus(3)assert 4 * 3 == 12 // 4.multiply(12)assert 4 % 3 == 1 // 4.mod(3)assert 4 ** 3 == 64 // 4.power(3)assert 4 / 3 == 1.3333333333 // 4.div(3)assert 4.intdiv(3) == 1 // normal integer division
assert !(4 == 3) // !(4.equals(3))assert 4 != 3 // ! 4.equals(3)assert !(4< 3) // 4.compareTo(3) < 0assert !(4 0
assert 4 >= 3 // 4.compareTo(3) >= 0assert 43 == 1 // 4.compareTo(3)
D t
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
16/70
Dates
Agile 2007 - 16
Submission631
ASERT2007
import static java.util.Calendar.getInstance as nowimport org.codehaus.groovy.runtime.TimeCategory
import java.text.SimpleDateFormat
println now().time
def date = new Date() + 1println date
use(TimeCategory) {
println new Date() + 1.hour + 3.weeks - 2.days}
input = "1998-06-03"df1 = new SimpleDateFormat("yyyy-MM-dd")date = df1.parse(input)
df2 = new SimpleDateFormat("MMM/dd/yyyy")println 'Date was ' + df2.format(date)
Thu Jun 28 10:10:34 EST 2007
Fri Jun 29 10:10:35 EST 2007
Tue Jul 17 11:10:35 EST 2007
Date was Jun/03/1998
Li t M R
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
17/70Agile 2007 - 17
Submission631
ASERT2007
Lists, Maps, Ranges
def empty = []def full = [1, 2, 'J1']
assert full+full == full*2
assert full[0] == 1assert full[0..1]==[1, 2]
full[0..1] = [0, 1, 2, 3]
assert full ==
[0, 1, 2, 3, 'J1']
def empty = [:]def full = [a: 1,b: 2]
assert full['a'] == 1
assert full.a == 1
full.a = 2assert full == [a:2,b:2]
def inclusive = 'a'..'z'
inclusive.each {}
def exclusive = 0..
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
18/70Agile 2007 - 18
Submission631
ASERT2007
Listsassert [1,2,3,4] == (1..4)assert [1,2,3] + [1] == [1,2,3,1]
assert [1,2,3]
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
19/70Agile 2007 - 19
Submis
sion631
ASERT2007
Mapsdefmap = [a:1, 'b':2]
printlnmap // ["a":1, "b":2]printlnmap.a // 1
printlnmap['a'] // 1printlnmap.keySet() // ["a", "b"]
defmap4 = [:]// extend the map through assignment
map4[1] = 'a'; map4[2] = 'b'
map4[true] = 'p'; map4[false] = 'q'map4[null] = 'x'; map4['null'] = 'z'assertmap4 == [1:'a', 2:'b', (true):'p',
(false):'q', (null):'x', 'null':'z' ]
def sb = new StringBuffer()[1:'a', 2:'b', 3:'c'].each{ k, v-> sb "$k:$v" }.join(', ')
assert s == '1:a, 2:b, 3:c'
M
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
20/70Agile 2007 - 20
Submis
sion631
ASERT2007
Mapsassert [
[name:'Clark', city:'London'], [name:'Sharma', city:'London'],[name:'Maradona', city:'LA'], [name:'Zhang', city:'HK'],
[name:'Ali', city: 'HK'], [name:'Liu', city:'HK'],].groupBy{ it.city } == [
London: [[name:'Clark', city:'London'], [name:'Sharma', city:'London'] ],LA: [[name:'Maradona', city:'LA'] ],HK: [[name:'Zhang', city:'HK'], [name:'Ali', city: 'HK'], [name:'Liu', city:'HK'] ],
]
defphrase = 'The quick brown fox jumps over the lazy dog'assert (phrase.toList()*.toLowerCase() - ' ').findAll{ it in 'aeiou'.toList() }. // like WHEREgroupBy{ it }. // like GROUP BYfindAll{ it.value.size() >1 }. // like HAVING
entrySet().sort{ it.key }.reverse(). // like ORDER BYcollect{ "$it.key:${it.value.size()}" }.join(', ') == 'u:2, o:4, e:3'
// single-element list that can't be modifieddef singMap = Collections.singletonMap('a', 1)assert singMap == ['a': 1]
Reg lar E pressions
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
21/70
Agile 2007 - 21
Submis
sion631
ASERT2007
Regular Expressions
Find operator
Match operator Pattern operator
Replace with
calculated
values
if ("Hello World!" =~ /Hello/)
if ("Hello World!" ==~ /Hello\b.*/)~/Hello\b.*/
"1.23".replaceAll(/\d+/){ num->
num.toInteger() + 1}
-> 2.24
"1.23".replaceAll(/\d/){ num->
num.toInteger() + 1
}
-> 2.34
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
22/70
Control Structures
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
23/70
Agile 2007 - 23
Submis
sion631
ASERT2007
Control Structures
switch (10) {case 0 : ; break
case 0..9 :
case [8,9,11] :
case Float :
case {it%3 == 0}: case ~/../ :
default :
}
implementboolean isCase(candidate)
if (1)if (object)
if (list)
for (itemin iterable) { }
myMap.each { key, value ->
println "$key : $value"
}
throw, catch, finallywhile, eachWithIndex,
eachLine
GroovyBeans and GPath
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
24/70
Agile 2007 - 24
Submis
sion631
ASERT2007
GroovyBeans and GPath
class Dir {
String nameList dirs
}
def root =
new Dir (name: '/', dirs: [
new Dir (name: 'a'),
new Dir (name: 'b')
])
root.dirs[0].name == 'a'
root.dirs.name == ['a','b']
root.dirs.name*.size() ==
[1, 1]
Dir.methods.name
.grep(~/(g|s)et/)
->[getName, setName, getDirs,setDirs, ]
find, findAll, grep,
every, any,
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
25/70
Static Imports
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
26/70
Static Imports
Agile 2007 - 26
Submis
sion631
ASERT2007
import staticjava.awt.Color.LIGHT_GRAYimport static Boolean.FALSE as Fimport static Calendar.getInstance as now
import static Integer.*
println LIGHT_GRAY // => java.awt.Color[r=192,g=192,b=192]println !F // => trueprintln now().time // => Sun Apr 29 11:12:43 EST 2007
println "Integers are between $MIN_VALUE and $MAX_VALUE"// => Integers are between -2147483648 and 2147483647
deftoHexString(int val, boolean upperCase) {defhexval = upperCase ? toHexString(val).toUpperCase() : toHexString(val)return '0x' + hexval
}println toHexString(15, true) // => 0xFprintln toHexString(15, false) // => 0xf
import static Math.*println sin(123.456) * cos(456.789)
// => 0.24733809349262376
Works with Java 1.4
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
27/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
28/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
29/70
Using Closures
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
30/70
Agile 2007 - 30
Submis
sion631
ASERT2007
...Using Closures
defpairWise(list, Closure invoke) {
if (list.size() < 2) return []def next = invoke(list[0],list[1])return [next] + pairWise(list[1..-1], invoke)
}
// using min, max, etc. From previous slideassertpairWise(1..5, add) == [3, 5, 7, 9]assertpairWise(1..5, mult) == [2, 6, 12, 20]assertpairWise(1..5, min) == [1, 2, 3, 4]assertpairWise(1..5, max) == [2, 3, 4, 5]
assert 'cbaxabc' == ['a','b','c'].inject('x'){result, item -> item + result + item }
Topics
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
31/70
Agile 2007 - 31
Submis
sion631
ASERT2007
Topics
Introduction
Language Basics
Closures
Processing XML
Accessing Databases Other Features
Testing with Groovy
Further Integration
Grails
XmlSlurper
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
32/70
Agile 2007 - 32
Submis
sion631
ASERT2007
XmlSlurper
Features One-line parsing
GPath Syntax
Efficient lazy evaluation
static defCAR_RECORDS = '''
AustraliaProduction Pickup Truck with speed of 271kph
Isle of ManSmallest Street-Legal Car at 99cm wide and 59 kg in weight
FranceMost Valuable Car at $15 million
'''
XmlSlurper
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
33/70
Agile 2007 - 33
Submis
sion631
ASERT2007
XmlSlurperdefrecords = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS)// 3 records in totalassert 3 == records.car.size()// 10 nested nodes
assert 10 == records.depthFirst().collect{ it }.size()// test properties of the first recorddeffirstRecord = records.car[0]assert 'car' == firstRecord.name()assert 'Holden' == firstRecord.@make.toString()assert 'Australia' == firstRecord.country.text()// 2 cars have an 'e' in the make
assert 2 == records.car.findAll{ it.@make.toString().contains('e') }.size()// 2 cars have an 'e' in the makeassert 2 == records.car.findAll{ it.@make =~ '.*e.*' }.size()// makes of cars that have an 's' followed by an 'a' in the countryassert ['Holden', 'Peel'] == records.car.findAll{ it.country =~ '.*s.*a.*' }.@make.collect{ it.toStrin// types of recordsassert ['speed', 'size', 'price'] == records.depthFirst().grep{ it.@type != '' }.'@type'*.toString()
assert ['speed', 'size', 'price'] == records.'**'.grep{ it.@type != '' }.'@type'*.toString()// check parent() operatordefcountryOne = records.car[1].countryassert 'Peel' == countryOne.parent().@make.toString()assert 'Peel' == countryOne.'..'.@make.toString()// names of cars with records sorted by yeardefnames = records.car.list().sort{ it.@year.toInteger() }.'@name'*.toString()
assert ['Royale', 'P50', 'HSV Maloo'] == names
Topics
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
34/70
Agile 2007 - 34
Submis
sion631
ASERT2007
Topics
Introduction
Language Basics
Closures
Processing XML
Accessing Databases Other Features
Testing with Groovy
Further Integration Grails
Working with Databases
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
35/70
Agile 2007 - 35
Submis
sion631
ASERT2007
Working with Databases
Using standard SQL statements
Using DataSets
import groovy.sql.Sql
deffoo = 'cheese'defsql = Sql.newInstance("jdbc:mysql://localhost:3306/mydb", "user",
"pswd", "com.mysql.jdbc.Driver")
sql.eachRow("select * from FOOD where type=${foo}") {println "Gromit likes ${it.name}"
}
import groovy.sql.Sql
defsql = Sql.newInstance("jdbc:mysql://localhost:3306/mydb", "user","pswd", "com.mysql.jdbc.Driver")
deffood = sql.dataSet('FOOD')defcheese = food.findAll { it.type == 'cheese' }cheese.each { println "Eat ${it.name}" }
DataSets and Lazy Evaluation
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
36/70
DataSets and Lazy Evaluation
Agile 2007 - 36
Submis
sion631
ASERT2007
athleteSet = db.dataSet('Athlete')youngsters = athleteSet.findAll{ it.datexOfBirth > '1970-1-1'}paula = youngsters.findAll{ it.firstname == 'Paula'}
println paula.sql
// => select * from Athlete where dataOfBirth > ? and firstname = ?
println paula.parameters// => [1970-1-1, Paula]
paula.each { println it.lastname } // database called here// => Radcliffe
SQL Database to XML
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
37/70
Agile 2007 - 37
Submission631
ASERT2007
SQL Database to XML
import groovy.sql.Sqlimport groovy.xml.MarkupBuilderdefschema = "PROD"defsql = Sql.newInstance("jdbc:oracle:thin:@hostname:1526:${schema}", "scott", "tiger",
"oracle.jdbc.driver.OracleDriver")
/* Request */defreq = """SELECT id, name, givenname, unit FROM ${schema}.peopleWHEREin_unit=1AND visible=0"""defout = new File('out.xml')defwriter = new FileWriter( out )defxml = new MarkupBuilder( writer )
xml.agents {sql.eachRow( req as String ) {
/* For each row output detail */row ->
xml.agent(id:row.id) {name( row.name )givenname( row.givenname )unit( row.unit )}
}}
ABTI
Jean
Sales
...
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
38/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
39/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
40/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
41/70
ExpandoMetaClass
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
42/70
Agile 2007 - 42
Submission631
ASERT2007
ExpandoMetaClass
String.metaClass.swapCase = {->def sb = new StringBuffer()
delegate.each {sb delegate.size() * 2 }
LinkedList list = []
list
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
43/70
Agile 2007 - 43
Submission631
ASERT2007
ExpandoMetaClass
class Person {String name
}
classMortgageLender {defborrowMoney() {
"buy house"}
}
def lender = newMortgageLender()
Person.metaClass.buyHouse = lender.&borrowMoney
defp = new Person()
assert "buy house" == p.buyHouse()
Constraint Programming
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
44/70
Agile 2007 - 44
Submission631
ASERT2007
Constraint Programming// require(url:'http://www.alice.unibo.it/tuProlog/', jar:'tuprolog.jar', version:'2.1')import alice.tuprolog.*
/** Pretty Printing */defpprint(soln) {
println soln.isSuccess() ?"$soln.query = $soln.solution" :'no solution found'
}
/** Prolog clauses */defgetTheory() {new Theory("""
parent(pam, bob).parent(tom, bob).parent(tom, liz).parent(bob, ann).parent(bob, pat).parent(pat, jim).
female(pam).male(tom).male(bob).female(liz).female(pat).female(ann).male(jim).
mother(X,Y) :- parent(X,Y), female(X).father(X,Y) :- parent(X,Y), male(X).
grandparent(X,Z) :- parent(X,Y),parent(Y,Z).grandmother(X,Y) :- grandparent(X,Y),female(X).grandfather(X,Y) :- grandparent(X,Y),male(X).
sister(X,Y) :-/*different(X,Y), */parent(Z,X),parent(Z,Y),female(X).brother(X,Y) :-/*different(X,Y), */parent(Z,X),parent(Z,Y),male(X).
ancestor(X,Y) :- parent(X,Y).ancestor(X,Z) :- parent(X,Y),ancestor(Y,Z).""")}
defengine = new Prolog()engine.theory = theorypprint engine.solve('ancestor(tom,X).')while(engine.hasOpenAlternatives()) {
pprint engine.solveNext()}
ancestor(tom,X) = ancestor(tom,bob)
ancestor(tom,X) = ancestor(tom,liz)
ancestor(tom,X) = ancestor(tom,ann)
ancestor(tom,X) = ancestor(tom,pat)
ancestor(tom,X) = ancestor(tom,jim)
no solution found
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
45/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
46/70
Using XStream - Annotations
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
47/70
Agile 2007 - 47
Submission631
ASERT2007
Using XStream Annotationsimport com.thoughtworks.xstream.*import com.thoughtworks.xstream.annotations.*
@XStreamAlias("person")class Associate {@XStreamAsAttribute@XStreamAlias('first-name')private String firstname
@XStreamAlias('surname')private String lastname
@XStreamOmitFieldprivate String position
}
msg = new Associate(firstname:'Sarah',lastname:'Connor',position:'Protector')
Annotations.configureAliases(stream, Associate)
println stream.toXML(msg)
Connor
Topics
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
48/70
Agile 2007 - 48
Submission631
ASERT2007
op cs
Introduction
Language Basics
Closures
Processing XML
Accessing Databases
Other Features
Testing GroovyUnit Testing
MocksAcceptance Testing
Further Integration
Grails
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
49/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
50/70
Built-in Mocks for Groovy
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
51/70
Agile 2007 - 51
Submiss
ion631
ASERT2007
y
Handle statics, explicit constructors, etc.
import groovy.mock.interceptor.MockFor
defmocker = new MockFor(Collaborator.class) // create the Mock supportmocker.demand.one(1..2) { 1 } // demand the 'one' method one or two times, returning 1mocker.demand.two() { 2 } // demand the 'two' method exactly once, returning 2mocker.use { // start using the Mock
defcaller = new Caller() // caller will call CollaboratorassertEquals 1, caller.collaborateOne() // will call Collaborator.oneassertEquals 1, caller.collaborateOne() // will call Collaborator.oneassertEquals 2, caller.collaborateTwo() // will call Collaborator.two
} // implicit verify for strict expectation here
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
52/70
JMock 2
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
53/70
Agile 2007 - 53
Submiss
ion631
ASERT2007
import org.jmock.integration.junit4.JMockimport org.jmock.Mockeryimport org.junit.Testimport org.junit.Beforeimport org.junit.runner.RunWithimport org.junit.runner.JUnitCore
@RunWith(JMock)class JMock2Test {
Mockery context = new JUnit4GroovyMockery()defmockReverser, storer
@Before void setUp() throws Exception {mockReverser = context.mock(Reverser.class)storer = new JavaStorer(mockReverser)
}
@Test void testStorage() {expectReverse(123.456, -123.456)expectReverse('hello', 'olleh')checkReverse(123.456, -123.456)checkReverse('hello', 'olleh')
}
defexpectReverse(input, output) {context.checking{
one(mockReverser).reverse(input); will(returnValue(output))}
}
defcheckReverse(value, reverseValue) {storer.put(value)assert value == storer.get()assert reverseValue == storer.getReverse()
}}
JUnitCore.main('JMock2Test')
Popper
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
54/70
Agile 2007 - 54
Submiss
ion631
ASERT2007
pp
@RunWith(Theories)class PopperBetweenTest extends GroovyTheoryContainer {
private int test, total // for explanatory purposes only
@Theory void multiplyIsInverseOfDivide(@Between(first = -4, last = 2) int amount,@Between(first = -2, last = 5) int m
) {total++
assume m != 0assert new Dollar(amount).times(m).divideBy(m).amount == amounttest++
}
@After void dumpLog() {
println "$test tests performed out of $total combinations"}}
JUnitCore.main('PopperBetweenTest')
JUnit version 4.3.1
.49 tests performed out of 56 combinations
Time: 0.234
OK (1 test)
Instinct
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
55/70
Agile 2007 - 55
Submiss
ion631
ASERT2007
import com.googlecode.instinct.marker.annotate.BeforeSpecification as initiallyimport com.googlecode.instinct.marker.annotate.Specification as specimport static com.googlecode.instinct.runner.TextContextRunner.runContexts as check_specs_for
class a_default_storer {
defstorer@initially void create_new_storer() {
storer = new Storer()}
private check_persist_and_reverse(value, reverseValue) {storer.put(value)assert value == storer.get()assert reverseValue == storer.reverse
}
@spec defshould_reverse_numbers() {check_persist_and_reverse 123.456, -123.456
}
@spec defshould_reverse_strings() {check_persist_and_reverse 'hello', 'olleh'
}
@spec defshould_reverse_lists() {check_persist_and_reverse([1, 3, 5], [5, 3, 1])
}}
check_specs_for a_default_storer
a_default_storer- should_reverse_lists
- should_reverse_strings
- should_reverse_numbers
WebTest testing Web Sites
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
56/70
Agile 2007 - 56
Submiss
ion631
ASERT2007
gdefant = new AntBuilder()
defwebtest_home = System.properties.'webtest.home'
ant.taskdef(resource:'webtest.taskdef'){classpath(){
pathelement(location:"$webtest_home/lib")fileset(dir:"$webtest_home/lib", includes:"**/*.jar")
}}
defconfig_map = [:]['protocol','host','port','basepath','resultfile','resultpath', 'summary', 'saveresponse','defaultpropertytype'].each{
config_map[it] = System.properties['webtest.'+it]}
ant.testSpec(name:'groovy: Test Groovy Scripting at creation time'){
config(config_map)steps(){invoke(url:'linkpage.html')for (i in 1..10){
verifyText(description:"verify number ${i} is on pages", text:"${i}")}
}
}
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
57/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
58/70
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
59/70
Integration With Existing Native Apps
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
60/70
Agile 2007 - 60
Submiss
ion631
ASERT2007
g g pp Scriptom allows you to script any ActiveX
or COM Windows component from within
your Groovy scripts
import org.codehaus.groovy.scriptom.ActiveXProxy
def outlook = new ActiveXProxy("Outlook.Application")
defmessage = outlook.CreateItem(0)
def emails = "galleon@codehaus.org;glaforge@codehaus.org"
def rec =message.Recipients.add(emails)
rec.Type = 1
message.Display(true)
Integration With Existing Services
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
61/70
Agile 2007 - 61
Submiss
ion631
ASERT2007
g g WS or XML/RPC allow seamless
connection to existing services
No need to generate stubs,
Complex types are supported
import groovy.net.soap.SoapClient
proxy = new SoapClient("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL" )
rate =proxy.ConversionRate("USD", "EUR")
println rate
Integration with Spring...
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
62/70
g p g
Agile 2007 - 62
Submiss
ion631
ASERT2007
// traditional approach using a beans xml fileimport org.springframework.context.support.ClassPathXmlApplicationContext
defctx = new ClassPathXmlApplicationContext('calcbeans.xml')defcalc = ctx.getBean('calcBean')println calc.doAdd(3, 4) // => 7
// using BeanBuilderdefbb = new grails.spring.BeanBuilder()bb.beans {
adder(AdderImpl)calcBean(CalcImpl2) { adder = adder }
}defctx = bb.createApplicationContext()defcalc = ctx.getBean('calcBean')println calc.doAdd(3, 4) // => 7
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
63/70
Groovy.Net...
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
64/70
y
Agile 2007 - 64
Submiss
ion631
ASERT2007
// To create dlls:// ikvmc -target:library groovy-all-1.1-SNAPSHOT.jar
// Invoking groovy shell via GroovyDotNet.exeusing System;using System.Collections.Generic;
namespace GroovyDotNet {classMainClass {
public static voidMain(string[] args) {groovy.ui.InteractiveShell.main(args);
}}
}
// you can invoke normal groovy[1, 2, 3].each {println it }
// you can also invoke a .NET methodcli.System.Console.WriteLine('hello world {0}', 'from Groovy')
...Groovy.Net
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
65/70
y
Agile 2007 - 65
Submiss
ion631
ASERT2007
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
66/70
SOAP
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
67/70
Agile 2007 - 67
Submiss
ion631
ASERT2007
class MathService {double add(double a, double b) {
a + b
}double square(double c) {c * c
}}
import groovy.net.soap.SoapServer
defserver = new SoapServer('localhost', 6789)server.setNode('MathService')server.start()
import groovy.net.soap.SoapClient
defmath = new SoapClient('http://localhost:6789/MathServiceInterface?wsdl')assert math.add(1.0, 2.0) == 3.0assert math.square(3.0) == 9.0
Mashups
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
68/70
Agile 2007 - 68
Submiss
ion631
ASERT2007
Topics
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
69/70
Agile 2007 - 69
Submission631
ASERT2007
Introduction
Language Basics
Closures
Processing XML
Accessing Databases Other Features
Testing with Groovy
Further IntegrationGrails
-
7/28/2019 Slides631 PaulKing Agile2007 Groovy 2 631
70/70
top related