bdd - behavior driven development webapps mit groovy spock und geb

29
SEITENBAU GmbH Christian Baranowski Behavior Driven Development von Web-Applikationen mit Grovvy Spock und Geb

Upload: christian-baranowski

Post on 11-Jan-2017

1.505 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

SEITENBAU GmbHChristian Baranowski

Behavior Driven Development von Web-Applikationen mit Grovvy Spock und Geb

Page 2: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

BDD

define behavior

verify behavior

implement unit

„BDD behavior-driven development is a specialized version of test-driven development“ - wiki

“Behaviour” is a more useful word than “test” - Dan North

Page 3: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

define behavior

given:

when:

then:

some initial context (the givens)

an event occurs

ensure some outcomes

User Story

Scenario

Page 4: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Gradle

Werkzeuge

Groovy Spock Geb WebDriver

Page 5: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Klasse

package  com.github.tux2323;  

!class  Customer  {  

!}

Groovy

Page 6: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Variablen und Methoden

class  Customer  {  

!   def  foo  

  String  bar  

!   def  doFoo(def  foo){  

    def  bar  

  }  

  boolean  doBar(){  

    bar  

  }  

}

Groovy

Page 7: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Collectionsvoid  callWithList(){  

     withList([1,  1,  2,  3,  5])  

}  

!void  withList(def  list)  {  

     list.each  {  

           entry  -­‐>  

                 println  "${entry}"  

     }  

     list.eachWithIndex  {  

           entry,  index  -­‐>  

                 println  "${index}:  ${entry}"  

     }  

}

Groovy

Page 8: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Maps

void  callWithMap()  {  

     withMap(test:  '123',  name:  '324')  

}  

!void  withMap(def  map)  {  

     map.each  {  

           key,  value  -­‐>  

                 println  "${key}:  ${value}"  

     }  

}

Groovy

Page 9: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Closures

void  callWithClosure()  {  

     assert  withClosure  {  

           boolean  result  =  1  ==  1  

           println  "within  closure  ${result}"  

           result  

     }  

}  

!def  withClosure(Closure<Boolean>  closure)  {  

  closure.call()  

}

Groovy

Page 10: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Groovy Assertions

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

Page 11: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

• Sehr einfaches BDD Werkzeug für die JVM, kann schnell erlernt werden

• Biete eine ausdrucksstarke DSL zur Spezifikation von Tests, insbesondere für Parametrisierte Tests (Data Driven Tests)

• Spock kann sowohl für Unit- wie Systemtests genutzt werden

• JUnit Kompatibel - Zur Ausführung wird JUnit genutzt,

• Spock vereint die besten Features aus bewährten Tools wie JUnit, JMock und RSpec

Warum Spock?

Page 12: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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

Page 13: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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

Page 14: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Blocks

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  

}

Spock

Page 15: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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"  }  

}

Spock

Page 16: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Stubbing

Setup

Verify

Teardown

Exercise

Stub !

!

Create

Install

Return Values

Indirect Inputs

SUT

xUnit Test Patterns - Gerard Meszaros

Spock

Page 17: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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

res

pons

e ge

nera

tor

def  mockService  =  Mock(SellerService)        

Spock

Page 18: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Stubbing

 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'  

}

Spock

Page 19: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Mocking

Setup

Verify

Teardown

Exercise

Mock Object

!

!

!

Create

Install

ExpectionsIndirect InputsSUT

RecordVerify

xUnit Test Patterns - Gerard Meszaros

Spock

Page 20: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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._

Spock

Page 21: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Mocking Example

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')  

}

Spock

Page 22: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Parameterized Test

@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"    |      ""  

}

Spock

Page 23: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Parameterized Test

@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)]  

}

Spock

Page 24: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Warum Geb?

• Geb bietet eine Abstraktion und Vereinfachung der WebDriver API für Groovy

• 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

• Groovy GString bietet einfache JavaScript Integration in Tests

Geb WebDriver

Page 25: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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 WebDriver

Page 26: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

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 WebDriver

Page 27: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Geb waitFor

//  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")  

}

Geb WebDriver

Page 28: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Gradle

Zusammenfassung

Groovy Spock Geb WebDriver

Page 29: BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb

Links

• Spock - http://spockframework.org

• Spock GitHub - https://github.com/spockframework

• Spock Framework Reference Documentation http://docs.spockframework.org/en/latest/

• Geb - http://www.gebish.org/