SlideShare a Scribd company logo
1 of 62
Download to read offline
Spock and Geb in Action
Christian Baranowski
Tools
Groovy
Tools
Groovy Spock
www.spockframework.org
Tools
Groovy Spock Geb
www.spockframework.org
www.gebish.org
Tools
Groovy Spock Geb
WebDriver
Selenium
www.spockframework.org
www.gebish.org
Warum Spock?
Warum Spock?
1. Spock ist ein einfaches
BDD Werkzeug für die JVM
weitere Argumente ...
2. Spock biete ausdrucksstarke DSL zur
Spezifikation von Tests, insbesondere für
Parametrisierte Tests und Mocking
weitere Argumente ...
2. Spock biete ausdrucksstarke DSL zur
Spezifikation von Tests, insbesondere für
Parametrisierte Tests und Mocking
3. Spock kann sowohl für Unit- wie Systemtests
genutzt werden
weitere Argumente ...
2. Spock biete ausdrucksstarke DSL zur
Spezifikation von Tests, insbesondere für
Parametrisierte Tests und Mocking
3. Spock kann sowohl für Unit- wie Systemtests
genutzt werden
4. JUnit Kompatibel - Zur Ausführung wird JUnit
genutzt, Integration in IDEs, Build-Tools (Ant,
Maven, Gradle...) und CI (Jenkins)
weitere Argumente ...
2. Spock biete ausdrucksstarke DSL zur
Spezifikation von Tests, insbesondere für
Parametrisierte Tests und Mocking
3. Spock kann sowohl für Unit- wie Systemtests
genutzt werden
4. JUnit Kompatibel - Zur Ausführung wird JUnit
genutzt, Integration in IDEs, Build-Tools (Ant,
Maven, Gradle...) und CI (Jenkins)
5. Spock vereint die besten Features aus
bewährten Tools wie JUnit und RSpec
weitere Argumente ...
Spock Given When Then
Spock Given When Then
def	
  "spock	
  test	
  with	
  given	
  when	
  then	
  block"()	
  {
	
  	
  	
  given:	
  "Array	
  with	
  one	
  element"
	
  	
  	
  	
  	
  	
  	
  def	
  data	
  =	
  ["Some	
  Data"]
	
  	
  	
  when:	
  "Pop	
  a	
  element	
  from	
  the	
  array"
	
  	
  	
  	
  	
  	
  	
  data.pop()
	
  	
  	
  then:	
  "Size	
  of	
  the	
  array	
  is	
  zero"
	
  	
  	
  	
  	
  	
  	
  data.size()	
  ==	
  0
}
Spock Blocks
given:
when:
then:
and:
setup:
expect:
cleanup:
Vorbedingung, Data Fixtures, Setup
Zustand SUT wird verändert
Assertions, Prüfung des neuen Zustands
Kurzvariante für when & then
Unterteilung in weitere Blöcke
Alias für den given Block
Cleanup innerhalb eines Tests
Spock Blocks in Action
def	
  "spock	
  test	
  with	
  some	
  blocks"()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  given:	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  basar	
  =	
  Mock(Basar)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  basar.getTotal()	
  >>	
  100L
	
  	
  	
  	
  	
  	
  	
  	
  when:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  total	
  =	
  basar.getTotal()
	
  	
  	
  	
  	
  	
  	
  	
  then:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  total	
  ==	
  100L
	
  	
  	
  	
  	
  	
  	
  	
  and:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  user	
  =	
  basar.findUserWithId(100)
	
  	
  	
  	
  	
  	
  	
  	
  then:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  user	
  ==	
  null
	
  	
  	
  	
  	
  	
  	
  	
  cleanup:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  basar	
  =	
  null
}
Vier Phasen Test (Four-Phase Test)
SUT
xUnit Test Patterns - Gerard Meszaros
Vier Phasen Test (Four-Phase Test)
Setup Fixure
1
def	
  setupSpec()	
  {}
def	
  setup()	
  {}
SUT
xUnit Test Patterns - Gerard Meszaros
Vier Phasen Test (Four-Phase Test)
Setup
Exercise
SUT
Fixure
1
2
def	
  setupSpec()	
  {}
def	
  setup()	
  {}
when:
def	
  "spock	
  test"()	
  {	
  
SUT
xUnit Test Patterns - Gerard Meszaros
Vier Phasen Test (Four-Phase Test)
Setup
Verify
Exercise
SUT
Fixure
1
2
3
def	
  setupSpec()	
  {}
def	
  setup()	
  {}
when:
def	
  "spock	
  test"()	
  {	
  
then:
}
SUT
xUnit Test Patterns - Gerard Meszaros
Vier Phasen Test (Four-Phase Test)
Setup
Verify
Teardown
Exercise
SUT
Fixure
1
2
3
4
def	
  setupSpec()	
  {}
def	
  setup()	
  {}
when:
def	
  cleanup()	
  {}
def	
  cleanupSpec()	
  {}
def	
  "spock	
  test"()	
  {	
  
then:
}
SUT
xUnit Test Patterns - Gerard Meszaros
Spock Lifecycle
class	
  LifecycleSpec	
  extends	
  Specification	
  {
	
  	
  	
  	
  def	
  setupSpec()	
  {	
  	
  println	
  "01	
  -­‐	
  setup	
  Spec"	
  }
	
  	
  	
  	
  def	
  setup()	
  {	
  println	
  "02	
  -­‐	
  setup"	
  }
	
  	
  	
  	
  def	
  "simple	
  spock	
  test"()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  given:
println	
  "02	
  -­‐	
  setup	
  test"	
  
expect:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  def	
  data	
  =	
  []
	
  	
  	
  	
  data	
  ==	
  []
cleanup:
println	
  "04	
  -­‐	
  cleanup	
  test"
	
  	
  	
  	
  }
	
  	
  	
  	
  def	
  cleanup()	
  {	
  println	
  "04	
  -­‐	
  cleanup"	
  }
	
  	
  	
  	
  def	
  cleanupSpec()	
  {	
  println	
  "04	
  -­‐	
  cleanup	
  Spec"	
  }
}
def	
  christian	
  =	
  new	
  User(id:	
  1,	
  name:	
  "Christian")
def	
  martin	
  =	
  new	
  User(id:	
  	
  1,	
  name:	
  "Martin")
assert	
  christian.name	
  ==	
  martin.name
christian.name	
  ==	
  martin.name
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  |	
  	
  	
  	
  	
  	
  |
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  |	
  	
  	
  	
  	
  	
  Martin
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  User{id=1,	
  basarNumber='null',	
  name='Martin',	
  email='null',	
  lastname='null'}
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  false
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  5	
  differences	
  (44%	
  similarity)
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  (Ch)r(is)ti(a)n
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  (Ma)r(-­‐-­‐)ti(-­‐)n
|	
  	
  	
  	
  	
  	
  	
  	
  	
  Christian
User{id=1,	
  basarNumber='null',	
  name='Christian',	
  email='null',	
  lastname='null'}
Groovy Power Assertion
def	
  christian	
  =	
  new	
  User(id:	
  1,	
  name:	
  "Christian")
def	
  martin	
  =	
  new	
  User(id:	
  	
  1,	
  name:	
  "Martin")
assert	
  christian.name	
  ==	
  martin.name
christian.name	
  ==	
  martin.name
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  |	
  	
  	
  	
  	
  	
  |
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  |	
  	
  	
  	
  	
  	
  Martin
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  |	
  	
  User{id=1,	
  basarNumber='null',	
  name='Martin',	
  email='null',	
  lastname='null'}
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  false
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  5	
  differences	
  (44%	
  similarity)
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  (Ch)r(is)ti(a)n
|	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  (Ma)r(-­‐-­‐)ti(-­‐)n
|	
  	
  	
  	
  	
  	
  	
  	
  	
  Christian
User{id=1,	
  basarNumber='null',	
  name='Christian',	
  email='null',	
  lastname='null'}
Im then: block Kurzschreibweise
möglich ohne assert
Groovy Power Assertion
Mocking
Setup
Verify
Teardown
Exercise
Mock
Object
Create
Install
Expections
Indirect
Inputs
SUT
Record
Verify
xUnit Test Patterns - Gerard Meszaros
Mocking
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
Mocking
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
cardinality
cardinality
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
(0..1)	
  *	
  mockService.findByName(	
  'max'	
  )
(1.._)	
  *	
  mockService.findByName(	
  'max'	
  )
_	
  *	
  mockService.findByName(	
  'max'	
  )
Mocking
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
cardinality method constraint
cardinality
method constraint
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
(0..1)	
  *	
  mockService.findByName(	
  'max'	
  )
(1.._)	
  *	
  mockService.findByName(	
  'max'	
  )
_	
  *	
  mockService.findByName(	
  'max'	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService._(	
  *_	
  )
0	
  *	
  	
  	
  	
  	
  	
  mockService._
Mocking
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
cardinality method constraint argument constraint
cardinality
method constraint
argument constraint
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  'max'	
  )
(0..1)	
  *	
  mockService.findByName(	
  'max'	
  )
(1.._)	
  *	
  mockService.findByName(	
  'max'	
  )
_	
  *	
  mockService.findByName(	
  'max'	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  _	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  !null	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  !'max'	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService.findByName(	
  {	
  it.size()	
  >	
  0	
  }	
  )
1	
  *	
  	
  	
  	
  	
  	
  mockService._(	
  *_	
  )
0	
  *	
  	
  	
  	
  	
  	
  mockService._
def	
  "only	
  the	
  first	
  call	
  should	
  be	
  forwarded"()	
  {
	
  	
  given:
	
  	
  	
  	
  def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  def	
  cache	
  =	
  new	
  SimpleCache(target:	
  mockService)	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  when:	
  "invoke	
  two	
  times	
  the	
  cached	
  method"
	
  	
  	
  	
  cache.findByName('max')
	
  	
  	
  	
  cache.findByName('max')
	
  	
  then:	
  "target	
  method	
  was	
  invoked	
  one	
  time"
	
  	
  	
  	
  1	
  *	
  mockService.findByName('max')
}
Mocking Example
Stubbing
Setup
Verify
Teardown
Exercise
Stub
Create
Install
Return
Values
Indirect
Inputs
SUT
xUnit Test Patterns - Gerard Meszaros
Stubbing
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
Stubbing
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'
method constraint
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
Stubbing
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'
method constraint argument constraint
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
Stubbing
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'	
  >>	
  'ERR'
mockService.findByName(	
  'max'	
  )	
  >>>	
  ['OK',	
  'ERROR',	
  'ups']	
  	
  
mockService.findByName(	
  'max'	
  )	
  >>	
  {	
  throw	
  new	
  InternalError()	
  }
mockService.findByName(	
  _	
  )	
  >>	
  'OK'
mockService.findByName(	
  _	
  )	
  >>	
  {name	
  -­‐>	
  name.size()	
  >	
  1	
  ?	
  'OK'	
  :	
  'ERR'}
mockService.findByName(	
  'max'	
  )	
  >>	
  'OK'
method constraint argument constraint
response generator
responsegenerator
def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
 def	
  "cache	
  should	
  return	
  result	
  of	
  the	
  target"()	
  {
	
  	
  	
  given:	
  "a	
  mock	
  service	
  object	
  that	
  returns	
  OK"
	
  	
  	
  def	
  mockService	
  =	
  Mock(SellerService)	
  	
  	
  	
  
	
  	
  	
  mockService.findByName('max')	
  >>	
  'OK'	
  >>	
  {	
  throw	
  exception()	
  }
	
  	
  	
  and:	
  "cache	
  with	
  the	
  mock	
  object	
  as	
  target"
	
  	
  	
  def	
  cache	
  =	
  new	
  SimpleCache(target:	
  mockService)	
  	
  	
  
	
  	
  	
  when:	
  "invoke	
  cache	
  the	
  first	
  time"
	
  	
  	
  def	
  result	
  =	
  cache.findByName('max')
	
  	
  	
  then:	
  "result	
  is	
  OK"
	
  	
  	
  result	
  ==	
  'OK'
	
  	
  	
  when:	
  "invoke	
  cache	
  the	
  second	
  time"
	
  	
  	
  result	
  =	
  cache.findByName('max')
	
  	
  	
  then:	
  "result	
  is	
  OK"
	
  	
  	
  result	
  ==	
  'OK'
}
Stubbing Example
Parameterized Test (I)
Parameterized Test (I)
@Unroll
def	
  "edit	
  seller	
  '#basarNumber',	
  '#name'	
  and	
  '#lastname'"()	
  {
	
  	
  	
  when:
	
  	
  	
  	
  	
  def	
  updatedUser	
  =	
  updateUser(basarNumber,	
  name,	
  lastname)
	
  	
  	
  then:
	
  	
  	
  	
  	
  updatedUser.basarNumber	
  ==	
  basarNumber
	
  	
  	
  	
  	
  updatedUser.name	
  ==	
  name
	
  	
  	
  	
  	
  updatedUser.lastname	
  ==	
  lastname
	
  	
  	
  where:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  basarNumber	
  	
  |	
  name	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  lastname
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "ABC"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  ""	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  ""
}
@Unroll
def	
  "edit	
  seller	
  '#basarNumber',	
  '#name'	
  and	
  '#lastname'"()	
  {
	
  	
  ...	
  
	
  	
  where:
	
  	
  	
  	
  	
  	
  	
  	
  basarNumber	
  	
  |	
  name	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  lastname
	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  "ABC"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  ""	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  "Baranowski"
	
  	
  	
  	
  	
  	
  	
  	
  "100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  |	
  	
  	
  ""
}
Parameterized Test (I)
@Unroll
def	
  "create	
  a	
  #user"()	
  {
	
  	
  	
  when:
	
  	
  	
  	
  	
  basar.saveUser(user)
	
  	
  	
  then:
	
  	
  	
  	
  	
  basar.findUserWithId(user.id)	
  ==	
  user
	
  	
  	
  where:
	
  	
  	
  	
  	
  user	
  <<	
  [new	
  User(id:	
  1),	
  new	
  User(id:	
  2),	
  new	
  User(id:	
  3)]
}
Parameterized Test (II)
Warum Geb?
•Geb bietet eine Abstraktion undVereinfachung der
WebDriver API
•Dazu werden die dyamischen Sprachfunktionen von Groovy
genutzt.
•JQuery like API für Selenium WebDriver
•Geb bietet einen Mechanismus zur Seitenabstraktion
lesbare Oberflächentests
•Einfacher waitFor{ } mir Groovy Closure für dynamische
Web-Anwendungen
•einfache JavaScript Integration für Testanbindung
Geb „JQuery like API“
$(«css	
  selector»,	
  «index	
  or	
  range»,	
  «attribute	
  /	
  text	
  matchers»)
Geb „JQuery like API“
$(«css	
  selector»,	
  «index	
  or	
  range»,	
  «attribute	
  /	
  text	
  matchers»)
$('div.span8	
  p')
$('#newUserButton')
$('.error')
selector
Geb „JQuery like API“
$(«css	
  selector»,	
  «index	
  or	
  range»,	
  «attribute	
  /	
  text	
  matchers»)
$('div.span8	
  p')
$('#newUserButton')
$('.error')
$('div',	
  2,	
  class:	
  'span2')
$('div',	
  0..2,	
  class:	
  'span2')
selector
index	
  or	
  range
Geb „JQuery like API“
$(«css	
  selector»,	
  «index	
  or	
  range»,	
  «attribute	
  /	
  text	
  matchers»)
$('div.span8	
  p')
$('#newUserButton')
$('.error')
$('div',	
  2,	
  class:	
  'span2')
$('div',	
  0..2,	
  class:	
  'span2')
$('button',	
  class:	
  'btn')
$('td',	
  text:	
  '559')
$('td',	
  text:	
  contains('55'))
$('input',	
  value:	
  ~/.*/)
selector
index	
  or	
  range
attribute	
  /	
  
text	
  matchers
Geb „JQuery like API“
$(«css	
  selector»,	
  «index	
  or	
  range»,	
  «attribute	
  /	
  text	
  matchers»)
$('div.span8	
  p')
$('#newUserButton')
$('.error')
$('div',	
  2,	
  class:	
  'span2')
$('div',	
  0..2,	
  class:	
  'span2')
$('button',	
  class:	
  'btn')
$('td',	
  text:	
  '559')
$('td',	
  text:	
  contains('55'))
$('input',	
  value:	
  ~/.*/)
$('div').find('.span8')
selector
index	
  or	
  range
attribute	
  /	
  
text	
  matchers
Finding
Geb „JQuery like API“
$('div').parent()
$('div').next()
$('div').siblings()
$('div').children()
$('td',	
  text:	
  '559').parent().find('td')
$('td',	
  text:	
  '559').parent().children()
Traversing
Geb „JQuery like API“
$('#newUser').@id	
  	
  	
  	
  	
  	
  	
  	
  ==	
  'newUser'
$('#newUser').attr('id')	
  ==	
  'newUser'
$('#newUser').text()	
  	
  	
  	
  	
  ==	
  'Neuen	
  Nutzer	
  anlegen'
$('#newUser').tag()	
  	
  	
  	
  	
  	
  ==	
  'button'
$('#newUser').classes()	
  	
  ==	
  ['btn',	
  'updateUserButton']
$('button')*.text()	
  	
  	
  	
  	
  	
  ==	
  ['Löschen',	
  'Neuen	
  Nutzer']
$('#newUser').click()
$('input',	
  name:	
  'basarNumber').value('100')
$('div.desc')	
  <<	
  'X'
$('input',	
  name:	
  'basarNumber')	
  <<	
  '100'
Accessing
Attributes
clicking
input	
  values
Sending	
  
keystrokes
Geb waitFor API
//	
  use	
  default	
  wait	
  configuration
waitFor	
  {	
  
	
  	
  	
  sellerCountBefore	
  <	
  sellerCount()	
  
}
//	
  wait	
  for	
  up	
  to	
  10	
  seconds,	
  using	
  the	
  default	
  retry	
  interval
waitFor(10)	
  {	
  
	
  	
  	
  sellerCountBefore	
  <	
  sellerCount()	
  
}
waitFor(timeout=20)	
  {	
  $("#newUser")	
  }
//	
  wait	
  for	
  up	
  to	
  10	
  seconds,	
  waiting	
  half	
  a	
  second	
  between	
  retries
waitFor(10,	
  0.5)	
  {	
  
	
  	
  	
  sellerCountBefore	
  <	
  sellerCount()	
  
}
//	
  custom	
  message
waitFor(message:	
  'Button	
  not	
  found',	
  timeout=2)	
  {
$("#NewUserButton")
}
Page Object Pattern
import	
  geb.Page
	
  	
  	
  	
  	
  
class	
  BasarPage	
  extends	
  Page	
  {
	
  	
  	
  	
  static	
  url	
  =	
  "static/basar.html"
	
  	
  	
  	
  static	
  at	
  =	
  {	
  title	
  ==	
  "Basar"	
  }
	
  	
  	
  	
  static	
  content	
  =	
  {
	
  	
  	
  	
  	
  	
  	
  	
  basarForm	
  {	
  $("form")	
  }
	
  	
  	
  	
  	
  	
  	
  	
  addButton	
  (to:	
  BasarPage)	
  {	
  basarForm.addCartItem()	
  }
	
  	
  	
  	
  }
}
Page Object Pattern
import	
  geb.Page
	
  	
  	
  	
  	
  
class	
  BasarPage	
  extends	
  Page	
  {
	
  	
  	
  	
  static	
  url	
  =	
  "static/basar.html"
	
  	
  	
  	
  static	
  at	
  =	
  {	
  title	
  ==	
  "Basar"	
  }
	
  	
  	
  	
  static	
  content	
  =	
  {
	
  	
  	
  	
  	
  	
  	
  	
  basarForm	
  {	
  $("form")	
  }
	
  	
  	
  	
  	
  	
  	
  	
  addButton	
  (to:	
  BasarPage)	
  {	
  basarForm.addCartItem()	
  }
	
  	
  	
  	
  }
}
Browser.drive	
  {
	
  	
  	
  	
  to	
  BasarPage
	
  	
  	
  	
  assert	
  at(BasarPage)
	
  	
  	
  	
  basarForm.with	
  {
	
  	
  	
  	
  	
  	
  	
  	
  basarNumber	
  =	
  "100"
	
  	
  	
  	
  	
  	
  	
  	
  price	
  =	
  "10,50"
	
  	
  	
  	
  }
	
  	
  	
  	
  addButton.click()
}
// Test (Test Logik)
Action Test
def	
  "add	
  a	
  item	
  to	
  the	
  cart"()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  given:
	
  	
  	
  	
  	
  	
  	
  	
  BasarBind	
  basar	
  =	
  start	
  BasarBind
	
  	
  	
  	
  	
  	
  	
  	
  when:
	
  	
  	
  	
  	
  	
  	
  	
  basar	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  enter	
  '100'	
  into	
  basarNumberField
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  enter	
  '0,50'	
  into	
  priceField
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  click	
  addButton
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  then:
	
  	
  	
  	
  	
  	
  	
  	
  basar.sum	
  ==	
  '0,50'
}
https://github.com/tux2323/gebbind
class	
  BasarBind	
  extends	
  Bind	
  {
	
  	
  	
  	
  def	
  start()	
  {
	
  	
  	
  	
  	
  	
  	
  	
  go	
  "/static/basar.html"
	
  	
  	
  	
  	
  	
  	
  	
  waitFor	
  {	
  title	
  ==	
  "Basar"	
  }
	
  	
  	
  	
  }
	
  	
  	
  	
  InputText	
  basarNumberField	
  =	
  inputText	
  {	
  $("#basarNumber")	
  }
	
  	
  InputText	
  priceField	
  =	
  inputText	
  {	
  $("#price")	
  }
	
  	
  	
  	
  Button	
  addButton	
  =	
  button	
  onClick:	
  {
	
  	
  	
  	
  	
  	
  	
  	
  def	
  beforeClickCartSize	
  =	
  $('tr').size()
	
  	
  	
  	
  	
  	
  	
  	
  $('#addCartItem').click()
	
  	
  	
  	
  	
  	
  	
  	
  waitFor	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  $('tr').size()	
  >	
  beforeClickCartSize	
  ||
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  $('.text-­‐error').size()	
  >	
  0
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  }
Text	
  sum	
  =	
  text	
  {	
  $('#sum')	
  }
}
Action Test
https://github.com/tux2323/gebbind
Test Design
Test
Test Design
Test
Logik
Test Design
Test
Logik
Spock Framework
Test Design
Test
Logik
Binding SUT
Spock Framework
Test Design
Test
Logik
Binding SUT
Spock Framework
Page Object Pattern
Test Design
Test
Logik
Binding SUT
Spock Framework
Page Object Pattern
Action Test Pattern
Test Design
Test
Daten
Logik
Binding SUT
Spock Framework
Page Object Pattern
Action Test Pattern
Test Design
Test
Daten
Logik
Binding SUT
Spock Framework
Page Object PatternbasarNumber	
  	
  |	
  name	
  	
  	
  	
  	
  	
  	
  	
  	
  ||	
  	
  	
  lastname
"100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  ||	
  	
  	
  "Baranowski"
"ABC"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  ||	
  	
  	
  "Baranowski"
"100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  ""	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ||	
  	
  	
  "Baranowski"
"100"	
  	
  	
  	
  	
  	
  	
  	
  |	
  "Christian"	
  	
  ||	
  	
  	
  ""
Parameterized Test Action Test Pattern

More Related Content

What's hot

Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRick Copeland
 
groovy databases
groovy databasesgroovy databases
groovy databasesPaul King
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3Simon Su
 
MongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GParsPaul King
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42Yevhen Bobrov
 
Drivers APIs and Looking Forward
Drivers APIs and Looking ForwardDrivers APIs and Looking Forward
Drivers APIs and Looking ForwardMongoDB
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management SystemNeerajMudgal1
 
node.js Module Development
node.js Module Developmentnode.js Module Development
node.js Module DevelopmentJay Harris
 
The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88Mahmoud Samir Fayed
 
Understanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsUnderstanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsShinpei Hayashi
 
Hidden Treasures of the Python Standard Library
Hidden Treasures of the Python Standard LibraryHidden Treasures of the Python Standard Library
Hidden Treasures of the Python Standard Librarydoughellmann
 
The Ring programming language version 1.7 book - Part 72 of 196
The Ring programming language version 1.7 book - Part 72 of 196The Ring programming language version 1.7 book - Part 72 of 196
The Ring programming language version 1.7 book - Part 72 of 196Mahmoud Samir Fayed
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?Andrei Pangin
 
The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184Mahmoud Samir Fayed
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneAndres Almiray
 
Webinar: Replication and Replica Sets
Webinar: Replication and Replica SetsWebinar: Replication and Replica Sets
Webinar: Replication and Replica SetsMongoDB
 

What's hot (20)

Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 
MongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() OutputMongoDB World 2016: Deciphering .explain() Output
MongoDB World 2016: Deciphering .explain() Output
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42
 
Drivers APIs and Looking Forward
Drivers APIs and Looking ForwardDrivers APIs and Looking Forward
Drivers APIs and Looking Forward
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management System
 
node.js Module Development
node.js Module Developmentnode.js Module Development
node.js Module Development
 
Jersey Guice AOP
Jersey Guice AOPJersey Guice AOP
Jersey Guice AOP
 
The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88
 
Understanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsUnderstanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring Effects
 
Hidden Treasures of the Python Standard Library
Hidden Treasures of the Python Standard LibraryHidden Treasures of the Python Standard Library
Hidden Treasures of the Python Standard Library
 
The Ring programming language version 1.7 book - Part 72 of 196
The Ring programming language version 1.7 book - Part 72 of 196The Ring programming language version 1.7 book - Part 72 of 196
The Ring programming language version 1.7 book - Part 72 of 196
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Do we need Unsafe in Java?
Do we need Unsafe in Java?Do we need Unsafe in Java?
Do we need Unsafe in Java?
 
Database security
Database securityDatabase security
Database security
 
The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184
 
Oscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast LaneOscon Java Testing on the Fast Lane
Oscon Java Testing on the Fast Lane
 
Webinar: Replication and Replica Sets
Webinar: Replication and Replica SetsWebinar: Replication and Replica Sets
Webinar: Replication and Replica Sets
 

Similar to Spock and Geb in Action

Spock Framework - Slidecast
Spock Framework - SlidecastSpock Framework - Slidecast
Spock Framework - SlidecastDaniel Kolman
 
Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeTed Vinke
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdfHans Jones
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con djangoTomás Henríquez
 
Qualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniQualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniGrupo de Testes Carioca
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - StockholmJan Kronquist
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macrosunivalence
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql JOYITAKUNDU1
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScriptniklal
 

Similar to Spock and Geb in Action (20)

Spock Framework - Slidecast
Spock Framework - SlidecastSpock Framework - Slidecast
Spock Framework - Slidecast
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Spock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted VinkeSpock the enterprise ready specifiation framework - Ted Vinke
Spock the enterprise ready specifiation framework - Ted Vinke
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdf
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
Next Level Testing
Next Level TestingNext Level Testing
Next Level Testing
 
Qualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio SimoniQualidade levada a sério em Python - Emilio Simoni
Qualidade levada a sério em Python - Emilio Simoni
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - Stockholm
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macros
 
Unit test
Unit testUnit test
Unit test
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Typescript barcelona
Typescript barcelonaTypescript barcelona
Typescript barcelona
 
Clojure functions midje
Clojure functions midjeClojure functions midje
Clojure functions midje
 
code for quiz in my sql
code for quiz  in my sql code for quiz  in my sql
code for quiz in my sql
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 

More from Christian Baranowski

Microservices – die Architektur für Agile-Entwicklung?
Microservices – die Architektur für Agile-Entwicklung?Microservices – die Architektur für Agile-Entwicklung?
Microservices – die Architektur für Agile-Entwicklung?Christian Baranowski
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application DevelopmentChristian Baranowski
 
Komponententests und Testabdeckung
Komponententests und TestabdeckungKomponententests und Testabdeckung
Komponententests und TestabdeckungChristian Baranowski
 
Einführung in die Software-Qualitätssicherung
Einführung in die Software-QualitätssicherungEinführung in die Software-Qualitätssicherung
Einführung in die Software-QualitätssicherungChristian Baranowski
 
Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungChristian Baranowski
 
Software Testing und Qualitätssicherung
Software Testing und QualitätssicherungSoftware Testing und Qualitätssicherung
Software Testing und QualitätssicherungChristian Baranowski
 
Einführung Software Testing und Qualitätssicherung
Einführung Software Testing und QualitätssicherungEinführung Software Testing und Qualitätssicherung
Einführung Software Testing und QualitätssicherungChristian Baranowski
 
Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiChristian Baranowski
 
HTTP und Java Servlets Programmierung
HTTP und Java Servlets ProgrammierungHTTP und Java Servlets Programmierung
HTTP und Java Servlets ProgrammierungChristian Baranowski
 

More from Christian Baranowski (20)

Microservices – die Architektur für Agile-Entwicklung?
Microservices – die Architektur für Agile-Entwicklung?Microservices – die Architektur für Agile-Entwicklung?
Microservices – die Architektur für Agile-Entwicklung?
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application Development
 
Komponententests und Testabdeckung
Komponententests und TestabdeckungKomponententests und Testabdeckung
Komponententests und Testabdeckung
 
Einführung in die Software-Qualitätssicherung
Einführung in die Software-QualitätssicherungEinführung in die Software-Qualitätssicherung
Einführung in die Software-Qualitätssicherung
 
OSGi Web Development in Action
OSGi Web Development in ActionOSGi Web Development in Action
OSGi Web Development in Action
 
Continuous Delivery in Action
Continuous Delivery in ActionContinuous Delivery in Action
Continuous Delivery in Action
 
Gradle and Continuous Delivery
Gradle and Continuous DeliveryGradle and Continuous Delivery
Gradle and Continuous Delivery
 
Semantic Versioning
Semantic VersioningSemantic Versioning
Semantic Versioning
 
OSGi Community Updates 2012
OSGi Community Updates 2012OSGi Community Updates 2012
OSGi Community Updates 2012
 
OSGi Mars World in Action
OSGi Mars World in ActionOSGi Mars World in Action
OSGi Mars World in Action
 
Warum OSGi?
Warum OSGi?Warum OSGi?
Warum OSGi?
 
Top10- Software Engineering Books
Top10- Software Engineering BooksTop10- Software Engineering Books
Top10- Software Engineering Books
 
Domain Driven Design - 10min
Domain Driven Design - 10minDomain Driven Design - 10min
Domain Driven Design - 10min
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software Entwicklung
 
Software Testing und Qualitätssicherung
Software Testing und QualitätssicherungSoftware Testing und Qualitätssicherung
Software Testing und Qualitätssicherung
 
Einführung Software Testing und Qualitätssicherung
Einführung Software Testing und QualitätssicherungEinführung Software Testing und Qualitätssicherung
Einführung Software Testing und Qualitätssicherung
 
Datenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence ApiDatenbankzugriff mit der Java Persistence Api
Datenbankzugriff mit der Java Persistence Api
 
Java Servlets und AJAX
Java Servlets und AJAX Java Servlets und AJAX
Java Servlets und AJAX
 
HTTP und Java Servlets Programmierung
HTTP und Java Servlets ProgrammierungHTTP und Java Servlets Programmierung
HTTP und Java Servlets Programmierung
 

Recently uploaded

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetEnjoy Anytime
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 

Recently uploaded (20)

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 

Spock and Geb in Action

  • 1. Spock and Geb in Action Christian Baranowski
  • 6.
  • 8. Warum Spock? 1. Spock ist ein einfaches BDD Werkzeug für die JVM
  • 10. 2. Spock biete ausdrucksstarke DSL zur Spezifikation von Tests, insbesondere für Parametrisierte Tests und Mocking weitere Argumente ...
  • 11. 2. Spock biete ausdrucksstarke DSL zur Spezifikation von Tests, insbesondere für Parametrisierte Tests und Mocking 3. Spock kann sowohl für Unit- wie Systemtests genutzt werden weitere Argumente ...
  • 12. 2. Spock biete ausdrucksstarke DSL zur Spezifikation von Tests, insbesondere für Parametrisierte Tests und Mocking 3. Spock kann sowohl für Unit- wie Systemtests genutzt werden 4. JUnit Kompatibel - Zur Ausführung wird JUnit genutzt, Integration in IDEs, Build-Tools (Ant, Maven, Gradle...) und CI (Jenkins) weitere Argumente ...
  • 13. 2. Spock biete ausdrucksstarke DSL zur Spezifikation von Tests, insbesondere für Parametrisierte Tests und Mocking 3. Spock kann sowohl für Unit- wie Systemtests genutzt werden 4. JUnit Kompatibel - Zur Ausführung wird JUnit genutzt, Integration in IDEs, Build-Tools (Ant, Maven, Gradle...) und CI (Jenkins) 5. Spock vereint die besten Features aus bewährten Tools wie JUnit und RSpec weitere Argumente ...
  • 15. Spock Given When Then def  "spock  test  with  given  when  then  block"()  {      given:  "Array  with  one  element"              def  data  =  ["Some  Data"]      when:  "Pop  a  element  from  the  array"              data.pop()      then:  "Size  of  the  array  is  zero"              data.size()  ==  0 }
  • 16. Spock Blocks given: when: then: and: setup: expect: cleanup: Vorbedingung, Data Fixtures, Setup Zustand SUT wird verändert Assertions, Prüfung des neuen Zustands Kurzvariante für when & then Unterteilung in weitere Blöcke Alias für den given Block Cleanup innerhalb eines Tests
  • 17. Spock Blocks in Action def  "spock  test  with  some  blocks"()  {                given:                          def  basar  =  Mock(Basar)                        basar.getTotal()  >>  100L                when:                        def  total  =  basar.getTotal()                then:                        total  ==  100L                and:                        def  user  =  basar.findUserWithId(100)                then:                        user  ==  null                cleanup:                        basar  =  null }
  • 18. Vier Phasen Test (Four-Phase Test) SUT xUnit Test Patterns - Gerard Meszaros
  • 19. Vier Phasen Test (Four-Phase Test) Setup Fixure 1 def  setupSpec()  {} def  setup()  {} SUT xUnit Test Patterns - Gerard Meszaros
  • 20. Vier Phasen Test (Four-Phase Test) Setup Exercise SUT Fixure 1 2 def  setupSpec()  {} def  setup()  {} when: def  "spock  test"()  {   SUT xUnit Test Patterns - Gerard Meszaros
  • 21. Vier Phasen Test (Four-Phase Test) Setup Verify Exercise SUT Fixure 1 2 3 def  setupSpec()  {} def  setup()  {} when: def  "spock  test"()  {   then: } SUT xUnit Test Patterns - Gerard Meszaros
  • 22. Vier Phasen Test (Four-Phase Test) Setup Verify Teardown Exercise SUT Fixure 1 2 3 4 def  setupSpec()  {} def  setup()  {} when: def  cleanup()  {} def  cleanupSpec()  {} def  "spock  test"()  {   then: } SUT xUnit Test Patterns - Gerard Meszaros
  • 23. Spock Lifecycle class  LifecycleSpec  extends  Specification  {        def  setupSpec()  {    println  "01  -­‐  setup  Spec"  }        def  setup()  {  println  "02  -­‐  setup"  }        def  "simple  spock  test"()  {                given: println  "02  -­‐  setup  test"   expect:                        def  data  =  []        data  ==  [] cleanup: println  "04  -­‐  cleanup  test"        }        def  cleanup()  {  println  "04  -­‐  cleanup"  }        def  cleanupSpec()  {  println  "04  -­‐  cleanup  Spec"  } }
  • 24. def  christian  =  new  User(id:  1,  name:  "Christian") def  martin  =  new  User(id:    1,  name:  "Martin") assert  christian.name  ==  martin.name christian.name  ==  martin.name |                  |        |    |            | |                  |        |    |            Martin |                  |        |    User{id=1,  basarNumber='null',  name='Martin',  email='null',  lastname='null'} |                  |        false |                  |        5  differences  (44%  similarity) |                  |        (Ch)r(is)ti(a)n |                  |        (Ma)r(-­‐-­‐)ti(-­‐)n |                  Christian User{id=1,  basarNumber='null',  name='Christian',  email='null',  lastname='null'} Groovy Power Assertion
  • 25. def  christian  =  new  User(id:  1,  name:  "Christian") def  martin  =  new  User(id:    1,  name:  "Martin") assert  christian.name  ==  martin.name christian.name  ==  martin.name |                  |        |    |            | |                  |        |    |            Martin |                  |        |    User{id=1,  basarNumber='null',  name='Martin',  email='null',  lastname='null'} |                  |        false |                  |        5  differences  (44%  similarity) |                  |        (Ch)r(is)ti(a)n |                  |        (Ma)r(-­‐-­‐)ti(-­‐)n |                  Christian User{id=1,  basarNumber='null',  name='Christian',  email='null',  lastname='null'} Im then: block Kurzschreibweise möglich ohne assert Groovy Power Assertion
  • 27. Mocking 1  *            mockService.findByName(  'max'  ) def  mockService  =  Mock(SellerService)        
  • 28. Mocking 1  *            mockService.findByName(  'max'  ) cardinality cardinality def  mockService  =  Mock(SellerService)         1  *            mockService.findByName(  'max'  ) (0..1)  *  mockService.findByName(  'max'  ) (1.._)  *  mockService.findByName(  'max'  ) _  *  mockService.findByName(  'max'  )
  • 29. Mocking 1  *            mockService.findByName(  'max'  ) cardinality method constraint cardinality method constraint def  mockService  =  Mock(SellerService)         1  *            mockService.findByName(  'max'  ) (0..1)  *  mockService.findByName(  'max'  ) (1.._)  *  mockService.findByName(  'max'  ) _  *  mockService.findByName(  'max'  ) 1  *            mockService._(  *_  ) 0  *            mockService._
  • 30. Mocking 1  *            mockService.findByName(  'max'  ) cardinality method constraint argument constraint cardinality method constraint argument constraint def  mockService  =  Mock(SellerService)         1  *            mockService.findByName(  'max'  ) (0..1)  *  mockService.findByName(  'max'  ) (1.._)  *  mockService.findByName(  'max'  ) _  *  mockService.findByName(  'max'  ) 1  *            mockService.findByName(  _  ) 1  *            mockService.findByName(  !null  ) 1  *            mockService.findByName(  !'max'  ) 1  *            mockService.findByName(  {  it.size()  >  0  }  ) 1  *            mockService._(  *_  ) 0  *            mockService._
  • 31. def  "only  the  first  call  should  be  forwarded"()  {    given:        def  mockService  =  Mock(SellerService)                        def  cache  =  new  SimpleCache(target:  mockService)                    when:  "invoke  two  times  the  cached  method"        cache.findByName('max')        cache.findByName('max')    then:  "target  method  was  invoked  one  time"        1  *  mockService.findByName('max') } Mocking Example
  • 33. Stubbing mockService.findByName(  'max'  )  >>  'OK' def  mockService  =  Mock(SellerService)        
  • 34. Stubbing mockService.findByName(  'max'  )  >>  'OK' method constraint def  mockService  =  Mock(SellerService)        
  • 35. Stubbing mockService.findByName(  'max'  )  >>  'OK' method constraint argument constraint def  mockService  =  Mock(SellerService)        
  • 36. Stubbing mockService.findByName(  'max'  )  >>  'OK' mockService.findByName(  'max'  )  >>  'OK'  >>  'ERR' mockService.findByName(  'max'  )  >>>  ['OK',  'ERROR',  'ups']     mockService.findByName(  'max'  )  >>  {  throw  new  InternalError()  } mockService.findByName(  _  )  >>  'OK' mockService.findByName(  _  )  >>  {name  -­‐>  name.size()  >  1  ?  'OK'  :  'ERR'} mockService.findByName(  'max'  )  >>  'OK' method constraint argument constraint response generator responsegenerator def  mockService  =  Mock(SellerService)        
  • 37.  def  "cache  should  return  result  of  the  target"()  {      given:  "a  mock  service  object  that  returns  OK"      def  mockService  =  Mock(SellerService)              mockService.findByName('max')  >>  'OK'  >>  {  throw  exception()  }      and:  "cache  with  the  mock  object  as  target"      def  cache  =  new  SimpleCache(target:  mockService)            when:  "invoke  cache  the  first  time"      def  result  =  cache.findByName('max')      then:  "result  is  OK"      result  ==  'OK'      when:  "invoke  cache  the  second  time"      result  =  cache.findByName('max')      then:  "result  is  OK"      result  ==  'OK' } Stubbing Example
  • 39. Parameterized Test (I) @Unroll def  "edit  seller  '#basarNumber',  '#name'  and  '#lastname'"()  {      when:          def  updatedUser  =  updateUser(basarNumber,  name,  lastname)      then:          updatedUser.basarNumber  ==  basarNumber          updatedUser.name  ==  name          updatedUser.lastname  ==  lastname      where:                    basarNumber    |  name                  |      lastname                    "100"                |  "Christian"    |      "Baranowski"                    "ABC"                |  "Christian"    |      "Baranowski"                    "100"                |  ""                      |      "Baranowski"                    "100"                |  "Christian"    |      "" }
  • 40. @Unroll def  "edit  seller  '#basarNumber',  '#name'  and  '#lastname'"()  {    ...      where:                basarNumber    |  name                  |      lastname                "100"                |  "Christian"    |      "Baranowski"                "ABC"                |  "Christian"    |      "Baranowski"                "100"                |  ""                      |      "Baranowski"                "100"                |  "Christian"    |      "" } Parameterized Test (I)
  • 41. @Unroll def  "create  a  #user"()  {      when:          basar.saveUser(user)      then:          basar.findUserWithId(user.id)  ==  user      where:          user  <<  [new  User(id:  1),  new  User(id:  2),  new  User(id:  3)] } Parameterized Test (II)
  • 42. Warum Geb? •Geb bietet eine Abstraktion undVereinfachung der WebDriver API •Dazu werden die dyamischen Sprachfunktionen von Groovy genutzt. •JQuery like API für Selenium WebDriver •Geb bietet einen Mechanismus zur Seitenabstraktion lesbare Oberflächentests •Einfacher waitFor{ } mir Groovy Closure für dynamische Web-Anwendungen •einfache JavaScript Integration für Testanbindung
  • 43. Geb „JQuery like API“ $(«css  selector»,  «index  or  range»,  «attribute  /  text  matchers»)
  • 44. Geb „JQuery like API“ $(«css  selector»,  «index  or  range»,  «attribute  /  text  matchers») $('div.span8  p') $('#newUserButton') $('.error') selector
  • 45. Geb „JQuery like API“ $(«css  selector»,  «index  or  range»,  «attribute  /  text  matchers») $('div.span8  p') $('#newUserButton') $('.error') $('div',  2,  class:  'span2') $('div',  0..2,  class:  'span2') selector index  or  range
  • 46. Geb „JQuery like API“ $(«css  selector»,  «index  or  range»,  «attribute  /  text  matchers») $('div.span8  p') $('#newUserButton') $('.error') $('div',  2,  class:  'span2') $('div',  0..2,  class:  'span2') $('button',  class:  'btn') $('td',  text:  '559') $('td',  text:  contains('55')) $('input',  value:  ~/.*/) selector index  or  range attribute  /   text  matchers
  • 47. Geb „JQuery like API“ $(«css  selector»,  «index  or  range»,  «attribute  /  text  matchers») $('div.span8  p') $('#newUserButton') $('.error') $('div',  2,  class:  'span2') $('div',  0..2,  class:  'span2') $('button',  class:  'btn') $('td',  text:  '559') $('td',  text:  contains('55')) $('input',  value:  ~/.*/) $('div').find('.span8') selector index  or  range attribute  /   text  matchers Finding
  • 48. Geb „JQuery like API“ $('div').parent() $('div').next() $('div').siblings() $('div').children() $('td',  text:  '559').parent().find('td') $('td',  text:  '559').parent().children() Traversing
  • 49. Geb „JQuery like API“ $('#newUser').@id                ==  'newUser' $('#newUser').attr('id')  ==  'newUser' $('#newUser').text()          ==  'Neuen  Nutzer  anlegen' $('#newUser').tag()            ==  'button' $('#newUser').classes()    ==  ['btn',  'updateUserButton'] $('button')*.text()            ==  ['Löschen',  'Neuen  Nutzer'] $('#newUser').click() $('input',  name:  'basarNumber').value('100') $('div.desc')  <<  'X' $('input',  name:  'basarNumber')  <<  '100' Accessing Attributes clicking input  values Sending   keystrokes
  • 50. Geb waitFor API //  use  default  wait  configuration waitFor  {        sellerCountBefore  <  sellerCount()   } //  wait  for  up  to  10  seconds,  using  the  default  retry  interval waitFor(10)  {        sellerCountBefore  <  sellerCount()   } waitFor(timeout=20)  {  $("#newUser")  } //  wait  for  up  to  10  seconds,  waiting  half  a  second  between  retries waitFor(10,  0.5)  {        sellerCountBefore  <  sellerCount()   } //  custom  message waitFor(message:  'Button  not  found',  timeout=2)  { $("#NewUserButton") }
  • 51. Page Object Pattern import  geb.Page           class  BasarPage  extends  Page  {        static  url  =  "static/basar.html"        static  at  =  {  title  ==  "Basar"  }        static  content  =  {                basarForm  {  $("form")  }                addButton  (to:  BasarPage)  {  basarForm.addCartItem()  }        } }
  • 52. Page Object Pattern import  geb.Page           class  BasarPage  extends  Page  {        static  url  =  "static/basar.html"        static  at  =  {  title  ==  "Basar"  }        static  content  =  {                basarForm  {  $("form")  }                addButton  (to:  BasarPage)  {  basarForm.addCartItem()  }        } } Browser.drive  {        to  BasarPage        assert  at(BasarPage)        basarForm.with  {                basarNumber  =  "100"                price  =  "10,50"        }        addButton.click() } // Test (Test Logik)
  • 53. Action Test def  "add  a  item  to  the  cart"()  {                given:                BasarBind  basar  =  start  BasarBind                when:                basar  {                      enter  '100'  into  basarNumberField                      enter  '0,50'  into  priceField                      click  addButton                }                then:                basar.sum  ==  '0,50' } https://github.com/tux2323/gebbind
  • 54. class  BasarBind  extends  Bind  {        def  start()  {                go  "/static/basar.html"                waitFor  {  title  ==  "Basar"  }        }        InputText  basarNumberField  =  inputText  {  $("#basarNumber")  }    InputText  priceField  =  inputText  {  $("#price")  }        Button  addButton  =  button  onClick:  {                def  beforeClickCartSize  =  $('tr').size()                $('#addCartItem').click()                waitFor  {                        $('tr').size()  >  beforeClickCartSize  ||                        $('.text-­‐error').size()  >  0                }        } Text  sum  =  text  {  $('#sum')  } } Action Test https://github.com/tux2323/gebbind
  • 59. Test Design Test Logik Binding SUT Spock Framework Page Object Pattern
  • 60. Test Design Test Logik Binding SUT Spock Framework Page Object Pattern Action Test Pattern
  • 61. Test Design Test Daten Logik Binding SUT Spock Framework Page Object Pattern Action Test Pattern
  • 62. Test Design Test Daten Logik Binding SUT Spock Framework Page Object PatternbasarNumber    |  name                  ||      lastname "100"                |  "Christian"    ||      "Baranowski" "ABC"                |  "Christian"    ||      "Baranowski" "100"                |  ""                      ||      "Baranowski" "100"                |  "Christian"    ||      "" Parameterized Test Action Test Pattern