Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

GR8 Conf US: Spock Soup to Nuts

An overview of everything that is cool in the Spock Testing Framework

  • Inicia sesión para ver los comentarios

GR8 Conf US: Spock Soup to Nuts

  1. 1. Spock
  2. 2. Zan Thrash
  3. 3. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         Book book = new Book(isdn:book & a library" given: "I have a checked out 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         controller.catalogService = new CatalogService()         params.id = library.id for controller" and: "all dependancies         params.isdn = book.isdn and: "we submit the isdn and library id"         controller.returnBook()     JSONElement json = response.getJson()         assertEquals( json.isdn, book.isdn ) when: "submit the form"         assertEquals( json.status, FILED )     }} then: "verify the returned book is FILED" json.isdn == book.isdn json.status == FILED
  4. 4. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         Book book = new Book(isdn:book & a library" given: "I have a checked out 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         controller.catalogService = new CatalogService()         params.id = library.id for controller" and: "all dependancies         params.isdn = book.isdn and: "we submit the isdn and library id"         controller.returnBook()     JSONElement json = response.getJson()         assertEquals( json.isdn, book.isdn ) when: "submit the form"         assertEquals( json.status, FILED )     }} then: "verify the returned book is FILED" json.isdn == book.isdn json.status == FILED
  5. 5. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         Book book = new Book(isdn:book & a library" given: "I have a checked out 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         controller.catalogService = new CatalogService()         params.id = library.id for controller" and: "all dependancies         params.isdn = book.isdn and: "we submit the isdn and library id"         controller.returnBook()     JSONElement json = response.getJson()         assertEquals( json.isdn, book.isdn ) when: "submit the form"         assertEquals( json.status, FILED )     }} then: "verify the returned book is FILED" json.isdn == book.isdn json.status == FILED
  6. 6. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() params.id = library.id and: "we submit the isdn and library id"         params.isdn = book.isdn     controller.returnBook()         JSONElement json = response.getJson() when: "submit the form"             assertEquals( json.isdn, book.isdn ) assertEquals( json.status, FILED ) then: "verify the returned book is FILED" } json.isdn == book.isdn json.status == FILED}
  7. 7. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() params.id = library.id and: "we submit the isdn and library id"         params.isdn = book.isdn     controller.returnBook()         JSONElement json = response.getJson() when: "submit the form"             assertEquals( json.isdn, book.isdn ) assertEquals( json.status, FILED ) then: "verify the returned book is FILED" } json.isdn == book.isdn json.status == FILED}
  8. 8. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() and: "we submit the isdn and library id"         params.id = library.id     params.isdn = book.isdn         when: "submit the form"         controller.returnBook()     JSONElement json = response.getJson() then: "verify the returned book is FILED" json.isdn == book.isdn assertEquals( json.isdn, book.isdn ) assertEquals( json.status, FILED ) json.status == FILED }}
  9. 9. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() and: "we submit the isdn and library id"         params.id = library.id     params.isdn = book.isdn         when: "submit the form"         controller.returnBook()     JSONElement json = response.getJson() then: "verify the returned book is FILED" json.isdn == book.isdn assertEquals( json.isdn, book.isdn ) assertEquals( json.status, FILED ) json.status == FILED }}
  10. 10. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() and: "we submit the isdn and library id"         params.id = library.id     params.isdn = book.isdn         when: "submit the form"         controller.returnBook()     JSONElement json = response.getJson() then: "verify the returned book is FILED" json.isdn == book.isdn book.isdn ) assertEquals( json.isdn, json.status == FILED assertEquals( json.status, FILED ) }}
  11. 11. @TestFor(LibraryController)@Mock([Book, Library])class LibraryControllerTests extends Specification{ LibraryControllerSpec {     void testReturnBookToLibrary() { libraray"() { "sucessfully return book to         given: "I have a checked out book & a library"         Book book = new Book(isdn: 1234567ABC).save()         Library library = new Library(name: Carnegie).save()         and: "all dependancies for controller"         controller.catalogService = new CatalogService() and: "we submit the isdn and library id"         params.id = library.id     params.isdn = book.isdn         when: "submit the form"         controller.returnBook()     JSONElement json = response.getJson() then: "verify the returned book is FILED" json.isdn == book.isdn book.isdn ) assertEquals( json.isdn, json.status == FILED assertEquals( json.status, FILED ) }}
  12. 12. Fixture Methods
  13. 13. def setup() {}
  14. 14. def cleanup() {}
  15. 15. def setupSpec() {}
  16. 16. def cleanupSpec() {}
  17. 17. void "add 2 things together"() {    expect:        1 + 2 == 3 Bat + man == Bat man        99 + 1 == 100}
  18. 18. Condition not satisfied:Bat + man == Bat man      |       |      Batman  false              1 difference (85% similarity)              Bat(-)man              Bat( )man
  19. 19. Condition not satisfied:json.status == FILE|    |      ||    FILED  false|           1 difference (80% similarity)|           FILE(D)|           FILE(-)[id:1, author:null, title:UNKNOWN, status:FILED, class:opi.com.Book, isdn:1234567ABC
  20. 20. void "add 2 things together"() {    expect:        1 + 2 == 3 Bat + man == Bat man        99 + 1 == 100}
  21. 21. void "add 2 things together"() {    expect:"a + b = c"        a + b == c    where:        a << [1, Bat, 99]        b << [1, man, 1]        c << [2, Batman, 100]}
  22. 22. @Unrollvoid "add 2 things together"() {    expect:"a + b = c"        a + b == c    where:        a << [1, Bat, 99]        b << [1, man, 1]        c << [2, Batman, 100]}
  23. 23. @Unroll(#a + #b = #c)void "add 2 things together"() {    expect:"a + b = c"        a + b == c    where:        a << [1, Bat, 99]        b << [1, man, 1]        c << [2, Batman, 100]}
  24. 24. @Unrollvoid "#a + #b = #c"() {    expect:"a + b = c"        a + b == c    where:        a << [1, Bat, 99]        b << [1, man, 1]        c << [2, Batman, 100]}
  25. 25. @Unroll(#a + #b = #c)void "add 2 things together"() {    expect:"a + b = c"        a + b == c    where:        a      | b     || c        1      | 1     || 2        99     | 1     || 100        "Bat" | "man" || "Batman"}
  26. 26. void "custom data provider" () {    expect:"a + b = c"        a + b == c    where:        [a, b, c] << new ABCDataProvider()}
  27. 27. class ABCDataProvider implements Iterator{    List list = [[1,2,3], [1,99, 100], [Bat, man, Batman]]    int position = 0    boolean hasNext() {        position < list.size()    }    Object next() {        def result = list[position]        position += 1        result    }    def size() {        list.size()    }    def close(){ }    void remove() { }}
  28. 28. Interactions
  29. 29. def catalogService = Mock(CatalogService)CatalogService catalogService = Mock()
  30. 30. def catalogService = Mock(CatalogService)CatalogService catalogService = Mock()
  31. 31. void "test interaction scoping"() {    given:"create mock CatalogService"        CatalogService service = Mock()        controller.catalogService = service    and: "make sure it can file books"        service.isAvailable(_ as Book) >> true    when:"we verify isdn"        params.isdn = book.isdn        def result = controller.verifyISDN()    then:"verify the book was filed"        1 * service.inquired(_)        result == true}
  32. 32. void "test interaction scoping"() {    given:"create mock CatalogService"        CatalogService service = Mock()        controller.catalogService = service    and: "make sure it can file books"        service.isAvailable(_ as Book) >> true    when:"we verify isdn" Global        params.isdn = book.isdn        def result = controller.verifyISDN()    then:"verify the book was filed"        1 * service.inquired(_)        result == true}
  33. 33. void "test interaction scoping"() {    given:"create mock CatalogService"        CatalogService service = Mock()        controller.catalogService = service    and: "make sure it can file books"        service.isAvailable(_ as Book) >> true    when:"we verify isdn" Local        params.isdn = book.isdn        def result = controller.verifyISDN()    then:"verify the book was filed"        1 * service.inquired(_)        result == true}
  34. 34. void "test interaction scoping"() {    given:"create mock CatalogService"        CatalogService service = Mock()        controller.catalogService = service    and: "make sure it can file books"        service.isAvailable(_ as Book) >> true    when:"we verify isdn" Required        params.isdn = book.isdn        def result = controller.verifyISDN()    then:"verify the book was filed"        1 * service.inquired(_)        result == true}
  35. 35. void "test interaction scoping"() {    given:"create mock CatalogService"        CatalogService service = Mock()        controller.catalogService = service    and: "make sure it can file books"        service.isAvailable(_ as Book) >> true    when:"we verify isdn" Optional        params.isdn = book.isdn        def result = controller.verifyISDN()    then:"verify the book was filed"        1 * service.inquired(_)        result == true}
  36. 36. 1 * catalogService.file(book, library) >> FILED Carnality
  37. 37. 1 * catalogService.file(book, library) >> FILED Carnality
  38. 38. 1 * catalogService.file(book, library) >> FILED Carnality
  39. 39. (0..3) * catalogService.file(book, library) >> FILED Carnality
  40. 40. (3.._) * catalogService.file(book, library) >> FILED Carnality
  41. 41. (_..3) * catalogService.file(book, library) >> FILED Carnality
  42. 42. TooFewInvocationsErrorTooManyInvocationsError
  43. 43. (_..3) * catalogService.file(book, library) >> FILED Carnality Target Constraint
  44. 44. (_..3) * catalogService.file(book, library) >> FILED Carnality Target Constraint
  45. 45. (_..3) * _.file(book, library) >> FILED Target Constraint
  46. 46. (_..3) * _.file(book, library) >> FILED Target Constraint
  47. 47. (_..3) * catalogService.file(book, library) >> FILED Target Constraint Conststraint Method
  48. 48. (_..3) * catalogService.file(book, library) >> FILED Target Constraint Conststraint Method
  49. 49. (_..3) * catalogService./f.*/(book, library) >> FILED Method Conststraint
  50. 50. (_..3) * catalogService./f.*/(book, library) >> FILED Method Conststraint
  51. 51. (_..3) * catalogService._(book, library) >> FILED Method Conststraint
  52. 52. (_..3) * catalogService._(book, library) >> FILED Method Conststraint
  53. 53. (_..3) * catalogService.file(book, library) >> FILED Method Conststraint List Constraint Argument
  54. 54. (_..3) * catalogService.file(book, library) >> FILED Method Conststraint List Constraint Argument
  55. 55. (_..3) * catalogService.file(_, _) >> FILED Argument List Constraint
  56. 56. (_..3) * catalogService.file(*_) >> FILED Argument List Constraint
  57. 57. (_..3) * catalogService.file(_ as Book, _) >> FILED Argument List Constraint
  58. 58. (_..3) * catalogService.file(_ as Book, !null) >> FILED Argument List Constraint
  59. 59. (_..3) * catalogService.file({it.isdn > 1}, !null) >> FILED Argument List Constraint
  60. 60. 1 * catalogService.file(book, library) >> FILED Return Values Constraint Argument List
  61. 61. 1 * catalogService.file(book, library) >> FILED Return Values Constraint Argument List
  62. 62. 3 * catalogService.file(book, library) >>> [FILED,‘ERROR’] Return Values
  63. 63. 3 * catalogService.file(book, library) >> { book.status = FILED return book } Return Values
  64. 64. 3 * catalogService.file(book, library) >> { throw new TimeoutException() } Return Values
  65. 65. foo.bar() >> { throw new IOException() } >>> [1, 2, 3] >> { throw new RuntimeException() }  Return Values
  66. 66. (_.._) * _._(*_)
  67. 67. Order Is NOT enforced void "test ordered interactions"() {   ...     then:"verify the book was filed"         1 * service.inquired(_)         2 * service.notifyLibrarian(*_)         result == true }
  68. 68. Interactions are NOT orderedvoid "test ordered interactions"() {  ...    then:"verify an inquiry was add to the book"        1 * service.inquired(_) then:"verify that all librarians are notified "        2 * service.notifyLibrarian(*_)        result == true}
  69. 69. Extensions
  70. 70. @Unroll
  71. 71. @Shared
  72. 72. @Timeout() @Timeout(10)@Timeout(value=10, unit=TimeUnit.MILLISECONDS)
  73. 73. @Stepwise
  74. 74. @Ignore
  75. 75. @IgnoreRest
  76. 76. @IgnoreIf({ 1 })
  77. 77. @FailsWith(IOException)
  78. 78. @AutoCleanup()@AutoCleanup(‘dispose’)@AutoCleanup(quite=true)
  79. 79. @Use([Category])
  80. 80. class Dynamic {}
  81. 81. void "test the Use annotation"() {    when:"call awesomeness"        def result = new Dynamic().awesomeness(very)    then:"check result"        result == so very awesome}
  82. 82. class DynamicCategory {        static String awesomeness(Dynamic dynamic, String foo) {        “so $foo awesome”    }    }
  83. 83. @Use(DynamicCategory)void "test the Use annotation"() {    when:"call awesomeness"        def result = new Dynamic().awesomeness(very)    then:"check result"        result == so very awesome}
  84. 84. @Use(DynamicCategory)void "test the Use annotation"() {    when:"call awesomeness"        def result = new Dynamic().awesomeness(very)    then:"check result"        result == so very awesome}
  85. 85. void "test the Use annotation"() {    when:"call awesomeness" use(DynamicCategory){         def result = new Dynamic().awesomeness(very) }    then:"check result"        result == so very awesome}
  86. 86. @ConfineMetaClassChanges([Class])
  87. 87. ~/.spock/SpockConfig.groovyimport spock.util.mop.Useimport spock.lang.*import grails.plugin.spock.IntegrationSpecrunner {    optimizeRunOrder true    filterStackTrace false    include Unroll, Use    exclude {        baseClass IntegrationSpec    }}
  88. 88. >$ grails -Dspock.configuration=test/SpockConfig.groovy test-app
  89. 89. Rolling your ownSpock Extensions
  90. 90. import spock.lang.*@SayOnFailclass MyFirstSpec extends Specification {  @SayOnFail(value="Danger! Danger!", voice=Zarvox)  def "lets try this!"() {    expect:    Math.max(1, 2) == 3  }}
  91. 91. Step 1: Create Annotation@Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE, ElementType.METHOD])@ExtensionAnnotation(SayOnFailExtension)public @interface SayOnFail {    String value() default     String voice() default "Alex"}
  92. 92. Step 1: Create Annotation@Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE, ElementType.METHOD])@ExtensionAnnotation(SayOnFailExtension)public @interface SayOnFail { Retention    String value() default     String voice() default "Alex"}
  93. 93. Step 1: Create Annotation@Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE, ElementType.METHOD])@ExtensionAnnotation(SayOnFailExtension)public @interface SayOnFail { Target    String value() default     String voice() default "Alex"}
  94. 94. Step 1: Create Annotation@Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE, ElementType.METHOD])@ExtensionAnnotation(SayOnFailExtension)public @interface SayOnFail { Extension    String value() default     String voice() default "Alex"}
  95. 95. Step 1: Create Annotation@Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE, ElementType.METHOD])@ExtensionAnnotation(SayOnFailExtension) Default Valuespublic @interface SayOnFail {    String value() default     String voice() default "Alex"}
  96. 96. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    }    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  97. 97. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    } Extend    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  98. 98. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    } Override for spec    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  99. 99. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        } Add interceptor to all    } methods    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  100. 100. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    } Override for feature    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  101. 101. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    } Create Interceptor    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  102. 102. Step 2: Create Extensionclass SayOnFailExtension extends AbstractAnnotationDrivenExtension<SayOnFail>{    @Override    void visitSpecAnnotation(SayOnFail sayOnError, SpecInfo spec) {        spec.features.each {FeatureInfo feature ->            if(!feature.featureMethod.reflection.isAnnotationPresent(SayOnFail)) {                visitFeatureAnnotation(sayOnError, feature)            }        }    } Add to Feature    @Override    void visitFeatureAnnotation(SayOnFail sayOnError, FeatureInfo feature) {        def interceptor = new SayOnFailInterceptor(sayOnError, feature)        feature.getFeatureMethod().addInterceptor(interceptor)    }}
  103. 103. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    }    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  104. 104. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } Implement Interface    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  105. 105. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } Override    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  106. 106. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } run method    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  107. 107. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } if test fails    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  108. 108. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } do your thing    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  109. 109. Step 3: Create Intercepterclass SayOnFailInterceptor implements IMethodInterceptor{    SayOnFail sayOnError    FeatureInfo featureInfo    SayOnFailInterceptor(SayOnFail sayOnError, FeatureInfo featureInfo) {        this.sayOnError = sayOnError        this.featureInfo = featureInfo    } Throw Execption!    void intercept(IMethodInvocation invocation) {        try {           invocation.proceed()        } catch(Throwable t) {            def methodName = featureInfo.getFeatureMethod().name            def voiceName = sayOnError.voice()            def sayText = sayOnError.value() ?: "Danger! Failure for: $methodName"            try {                "say -v $voiceName $sayText".execute()            } catch (IOException ex) {}                        throw t        }    }}
  110. 110. @Documentclass LibraryControllerSpec extends Specification{    @Author(Zan)    @JiraIssue(MBL-42)    void "successfully return book to library"() {        given: "there is a checked out book and a active library"            Book book = new Book(isdn: 1234567ABC).save(validate: false)            Library library = new Library(name: Carnegie).save()        and:"the controller has all dependancy"            CatalogService catalogService = Mock()            controller.catalogService = catalogService        and: "submit library id and isdn"            params.id = library.id            params.isdn = book.isdn        when: "submit the form"            controller.returnBook()        and: "get the JSON from the response"            JSONElement json = response.getJson()        then: "verify the returned book is FILED"            json.isdn == book.isdn            json.status == FILE    }}
  111. 111. @Retention(RetentionPolicy.RUNTIME)@Target([ElementType.TYPE])@ExtensionAnnotation(DocumentExtension)public @interface Document {}
  112. 112. class DocumentExtension extends AbstractAnnotationDrivenExtension<Document> {    @Override    void visitSpecAnnotation(Document document, SpecInfo specInfo) {        specInfo.addListener(new DocumentListener(document))    }}
  113. 113. class DocumentListener extends AbstractRunListener{    private Document document    File baseDir = new File("src/docs/ref/Tests")    File output    DocumentListener(Document document) {        this.document = document        baseDir.mkdirs()    }    void beforeSpec(SpecInfo specInfo) {...}        void beforeFeature(FeatureInfo featureInfo) {...}    void beforeIteration(IterationInfo iterationInfo) {...}    void afterIteration(IterationInfo iterationInfo) {...}    void afterFeature(FeatureInfo featureInfo) {...}    void error(ErrorInfo errorInfo) {...}    void featureSkipped(FeatureInfo featureInfo) {...}    void afterSpec(SpecInfo specInfo) {...}        void specSkipped(SpecInfo specInfo) {...}}
  114. 114. Core Spock Links http://meetspock.appspot.com/ http://code.google.com/p/spock/wiki https://github.com/spockframework/spockInsightful Posts http://kousenit.wordpress.com/2011/08/20/i-think-i-get-spock-mocks-now/ http://hamletdarcy.blogspot.com/2009/05/peek-inside-spock-framework.htmlExtensions https://github.com/zanthrash/spock-extensions https://github.com/robfletcher/spock-extensions

×