Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Smarter testing Java code with Spock Framework

Smarter testing Java code with Spock Framework

Spock Framework is increasingly used to create automatic tests for production code written in Java. Thanks to a DSL based on Groovy language Spock allows to create more compact constructions with much better readability.

During my presentation I will show number of advanced and less known features, the use of which can simplify testing our code even more. I will present also a few new features which officially became available in recently released version 1.0.

This will NOT be a presentation about Spock basics. Nevertheless thanks to its natural clarity even people new to Spock should not have problems to follow and benefit.

Marcin Zajączkowski

April 20, 2015
Tweet

More Decks by Marcin Zajączkowski

Other Decks in Programming

Transcript

  1. Smarter testing Java code with Spock Framework Including changes in

    Spock 1.0 Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ Warszawa, 20th April 2015
  2. Agenda Why I like Spock? Less know, but cool Spock

    features New and noteworthy in Spock 1.0 Spock tricks Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  3. Why idea for this presentation? JUnit/TestNG + Mockito + AssertJ

    work... ... but Spock brings testing to another level Integrates seamlessly with production Java code Since version 1.0 provides even more useful features Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  4. Why idea for this presentation? JUnit/TestNG + Mockito + AssertJ

    work... ... but Spock brings testing to another level Integrates seamlessly with production Java code Since version 1.0 provides even more useful features Encourage more people to using Spock In even more effective way Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  5. Why I like Spock? Consist and readable test code Tests

    as specification by default All Groovy magic available to help Embedded mocking framework Although Mockito can be used if preferred Highly extensible Compatible with tools supporting JUnit Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  6. Simple specification in Spock given/when/then (or expect) are required to

    compile code c l a s s S i m p l e C a l c u l a t o r S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d a d d t w o n u m b e r s " ( ) { g i v e n : d e f s u t = n e w C a l c u l a t o r ( ) w h e n : d e f r e s u l t = s u t . a d d ( 1 , 2 ) t h e n : r e s u l t = = 3 } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  7. @Requires Runs annotated test (or the whole specification) only if

    given criteria are met Useful to depend on JVM version, operating system, activated profile, custom system property, etc. Opposite to @ I g n o r e I f Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  8. @Requires Runs annotated test (or the whole specification) only if

    given criteria are met Useful to depend on JVM version, operating system, activated profile, custom system property, etc. Opposite to @ I g n o r e I f Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  9. @Requires - continued Provides access to system properties and environment

    variables @ R e q u i r e s ( { S y s t e m . g e t P r o p e r t y ( " o s . a r c h " ) = = " a m d 6 4 " } ) d e f " s h o u l d u s e o p t i m i z a t i o n o n 6 4 - b i t s y s t e m s " ( ) { . . . } @ R e q u i r e s ( { e n v . c o n t a i n s K e y ( " E N A B L E _ C R M _ I N T E G R A T I O N _ T E S T S " ) } ) d e f " s h o u l d d o c o m p l i c a t e d t h i n g s w i t h C R M " ( ) { . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  10. @Requires - continued Can use static methods i m p

    o r t s t a t i c F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T . i s U r l A v a i l a b l e @ R e q u i r e s ( { i s U r l A v a i l a b l e ( " h t t p : / / s o m e - h o s t . i n t r a n e t / " ) } ) c l a s s F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T e x t e n d s S p e c i f i c a t i o n { / / c o u l d b e a l s o f r o m t r a i t o r o t h e r c l a s s s t a t i c b o o l e a n i s U r l A v a i l a b l e ( S t r i n g u r l ) { / / . . . } d e f " s h o u l d d o o n e t h i n g i n i n t r a n e t " ( ) { . . . } d e f " s h o u l d d o a n o t h e r t h i n g i n i n t r a n e t " ( ) { . . . } . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  11. @Requires - continued Can use static methods i m p

    o r t s t a t i c F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T . i s U r l A v a i l a b l e @ R e q u i r e s ( { i s U r l A v a i l a b l e ( " h t t p : / / s o m e - h o s t . i n t r a n e t / " ) } ) c l a s s F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T e x t e n d s S p e c i f i c a t i o n { / / c o u l d b e a l s o f r o m t r a i t o r o t h e r c l a s s s t a t i c b o o l e a n i s U r l A v a i l a b l e ( S t r i n g u r l ) { / / . . . } d e f " s h o u l d d o o n e t h i n g i n i n t r a n e t " ( ) { . . . } d e f " s h o u l d d o a n o t h e r t h i n g i n i n t r a n e t " ( ) { . . . } . . . } Import is required to prevent M i s s i n g M e t h o d E x c e p t i o n Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  12. @Requires - continued Can use static methods i m p

    o r t s t a t i c F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T . i s U r l A v a i l a b l e @ R e q u i r e s ( { i s U r l A v a i l a b l e ( " h t t p : / / s o m e - h o s t . i n t r a n e t / " ) } ) c l a s s F a n c y F e a t u r e R e q u i r e d I n t r a n e t C o n n e c t i o n S p e c I T e x t e n d s S p e c i f i c a t i o n { @ M e m o i z e d / / c o u l d b e a l s o f r o m t r a i t o r o t h e r c l a s s s t a t i c b o o l e a n i s U r l A v a i l a b l e ( S t r i n g u r l ) { / / . . . } d e f " s h o u l d d o o n e t h i n g i n i n t r a n e t " ( ) { . . . } d e f " s h o u l d d o a n o t h e r t h i n g i n i n t r a n e t " ( ) { . . . } . . . } @ M e m o i z e d for caching Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  13. @IgnoreIf and @Requires - new features s p o c

    k . u t i l . e n v i r o n m e n t . J v m Simple and convenient access to Java version (j a v a . v e r s i o n and j a v a . s p e c i f i c a t i o n . v e r s i o n ) b o o l e a n i s J a v a 7 ( ) / / t r u e o n l y i f J a v a 7 b o o l e a n i s J a v a 8 C o m p a t i b l e ( ) / / t r u e i f J a v a 8 + S t r i n g g e t J a v a V e r s i o n ( ) / / e . g . " 1 . 8 . 0 _ 0 5 " S t r i n g g e t J a v a S p e c i f i c a t i o n V e r s i o n ( ) / / e . g . " 1 . 8 " @ I g n o r e I f ( { ! j v m . j a v a 8 C o m p a t i b l e } ) d e f " s h o u l d f i n d a t r u n t i m e a n d u s e C o m p l e t a b l e F u t u r e f o r J a v a 8 + " ( ) { . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  14. @IgnoreIf and @Requires - new features s p o c

    k . u t i l . e n v i r o n m e n t . J v m Simple and convenient access to Java version (j a v a . v e r s i o n and j a v a . s p e c i f i c a t i o n . v e r s i o n ) b o o l e a n i s J a v a 7 ( ) / / t r u e o n l y i f J a v a 7 b o o l e a n i s J a v a 8 C o m p a t i b l e ( ) / / t r u e i f J a v a 8 + S t r i n g g e t J a v a V e r s i o n ( ) / / e . g . " 1 . 8 . 0 _ 0 5 " S t r i n g g e t J a v a S p e c i f i c a t i o n V e r s i o n ( ) / / e . g . " 1 . 8 " @ I g n o r e I f ( { ! j v m . j a v a 8 C o m p a t i b l e } ) d e f " s h o u l d f i n d a t r u n t i m e a n d u s e C o m p l e t a b l e F u t u r e f o r J a v a 8 + " ( ) { . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  15. @IgnoreIf and @Requires - new features s p o c

    k . u t i l . e n v i r o n m e n t . O p e r a t i n g S y s t e m Simple and convenient access to OS information (o s . n a m e and o s . v e r s i o n system properties) S t r i n g g e t N a m e ( ) / / L i n u x S t r i n g g e t V e r s i o n ( ) / / 8 . 1 F a m i l y g e t F a m i l y ( ) / / S O L A R I S ( e n u m ) b o o l e a n i s L i n u x ( ) b o o l e a n i s W i n d o w s ( ) b o o l e a n i s M a c O s ( ) / / a l s o S o l a r i s a n d O t h e r b o o l e a n i S o l a r i s ( ) b o o l e a n i s O t h e r ( ) @ R e q u i r e s ( { o s . l i n u x | | o s . m a c O s } ) d e f " s h o u l d u s e f a n c y c o n s o l e f e a t u r e s " ( ) { . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  16. @IgnoreIf and @Requires - new features s p o c

    k . u t i l . e n v i r o n m e n t . O p e r a t i n g S y s t e m Simple and convenient access to OS information (o s . n a m e and o s . v e r s i o n system properties) S t r i n g g e t N a m e ( ) / / L i n u x S t r i n g g e t V e r s i o n ( ) / / 8 . 1 F a m i l y g e t F a m i l y ( ) / / S O L A R I S ( e n u m ) b o o l e a n i s L i n u x ( ) b o o l e a n i s W i n d o w s ( ) b o o l e a n i s M a c O s ( ) / / a l s o S o l a r i s a n d O t h e r b o o l e a n i S o l a r i s ( ) b o o l e a n i s O t h e r ( ) @ R e q u i r e s ( { o s . l i n u x | | o s . m a c O s } ) d e f " s h o u l d u s e f a n c y c o n s o l e f e a t u r e s " ( ) { . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  17. @RestoreSystemProperties Restores original system properties From S y s t

    e m . g e t P r o p e r t i e s ( ) To a state before test Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  18. @RestoreSystemProperties - example @ S t e p w i

    s e c l a s s R e s t o r e S y s t e m P r o p e r t i e s S p e c e x t e n d s S p e c i f i c a t i o n { @ R e s t o r e S y s t e m P r o p e r t i e s d e f " s h o u l d d e n y p e r f o r m a c t i o n w h e n r u n n i n g a s r o o t " ( ) { g i v e n : S y s t e m . s e t P r o p e r t y ( " u s e r . n a m e " , " r o o t " ) a n d : d e f s u t = n e w D a n g e r o u s A c t i o n P e r f o r m e r ( ) w h e n : s u t . s q u a s h T h e m A l l ( ) t h e n : t h r o w n ( I l l e g a l S t a t e E x c e p t i o n ) } d e f " s h o u l d p e r f o r m a c t i o n w h e n r u n n i n g a s ' n o r m a l ' u s e r " ( ) { g i v e n : d e f s u t = n e w D a n g e r o u s A c t i o n P e r f o r m e r ( ) w h e n : s u t . s q u a s h T h e m A l l ( ) t h e n : n o E x c e p t i o n T h r o w n ( ) } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  19. @RestoreSystemProperties Restores original system properties From S y s t

    e m . g e t P r o p e r t i e s ( ) To a state before test Useful in integration tests when playing with them E.g. testing Spring profiles activation based on system property Two modes For one feature (test) For the whole specification Just like using for every test Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  20. @RestoreSystemProperties Restores original system properties From S y s t

    e m . g e t P r o p e r t i e s ( ) To a state before test Useful in integration tests when playing with them E.g. testing Spring profiles activation based on system property Two modes For one feature (test) For the whole specification Just like using for every test Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  21. @AutoCleanup Cleans up resource at the end of its life

    time Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  22. @AutoCleanup - with separate cleanup c l a s s

    F a n c y D B S p e c e x t e n d s S p e c i f i c a t i o n { @ S h a r e d p r i v a t e D B C o n n e c t i o n d b C o n n e c t i o n = n e w H 2 D B C o n n e c t i o n ( . . . ) d e f c l e a n u p S p e c ( ) { d b C o n n e c t i o n . r e l e a s e ( ) } d e f " s h o u l d d o f a n c y t h i n g s o n D B " ( ) { . . . } d e f " s h o u l d d o f a n c y 2 t h i n g s o n D B " ( ) { . . . } } i n t e r f a c e D B C o n n e c t i o n { . . . v o i d r e l e a s e ( ) ; } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  23. @AutoCleanup - example c l a s s F a

    n c y D B S p e c e x t e n d s S p e c i f i c a t i o n { @ A u t o C l e a n u p ( " r e l e a s e " ) @ S h a r e d p r i v a t e D B C o n n e c t i o n d b C o n n e c t i o n = n e w H 2 D B C o n n e c t i o n ( . . . ) d e f " s h o u l d d o f a n c y t h i n g s o n D B " ( ) { . . . } d e f " s h o u l d d o f a n c y 2 t h i n g s o n D B " ( ) { . . . } } i n t e r f a c e D B C o n n e c t i o n { . . . v o i d r e l e a s e ( ) ; } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  24. @AutoCleanup Cleans up resource at the end of its life

    time Applied on field No need to use separate c l e a u p /c l e a n u p S p e c method Supports both instance (per feature) and shared (per specification) variables By default method c l o s e ( ) is called Can be overridden with @ A u t o C l e a n u p ( " r e l e a s e " ) @ A u t o C l e a n u p ( q u i e t = t r u e ) to suppress exception logging Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  25. @AutoCleanup Cleans up resource at the end of its life

    time Applied on field No need to use separate c l e a u p /c l e a n u p S p e c method Supports both instance (per feature) and shared (per specification) variables By default method c l o s e ( ) is called Can be overridden with @ A u t o C l e a n u p ( " r e l e a s e " ) @ A u t o C l e a n u p ( q u i e t = t r u e ) to suppress exception logging Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 0.7
  26. Initialization and clean up in test s e t u

    p / c l e a n u p can be declared per feature useful if feature specific operations Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  27. Initialization and clean up in test s e t u

    p / c l e a n u p can be declared per feature useful if feature specific operations d e f " c o m p l e x l o g i c s h o u l d w o r k w i t h f i x e d t h r e a d p o o l " ( ) { s e t u p : / / a l i a s f o r ' g i v e n : ' E x e c u t o r S e r v i c e t h r e a d P o o l = E x e c u t o r s . n e w F i x e d T h r e a d P o o l ( 1 ) w h e n : S t r i n g r e t u r n e d V a l u e = t h r e a d P o o l . s u b m i t ( { " v a l " } a s C a l l a b l e ) . g e t ( 1 , T i m e U n i t . S E C O N D S ) t h e n : r e t u r n e d V a l u e = = " v a l " c l e a n u p : t h r e a d P o o l ? . s h u t d o w n ( ) } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  28. Initialization and clean up in test s e t u

    p / c l e a n u p can be declared per feature useful if feature specific operations s e t u p alias for g i v e n c l e a n u p like f i n a l l y executed even on exception works for every iteration (w h e r e ) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  29. Native support for JUnit before/after annotations By default s e

    t u p S p e c ( ) , s e t u p ( ) , c l e a n u p ( ) , c l e a n u p S p e c ( ) In addition @ B e f o r e C l a s s , @ B e f o r e , @ A f t e r , @ A f t e r C l a s s Can be mixed together (also through class hierarchy) No longer called twice in super class More than one method of given type can be provided Useful when dealing with Additional testing frameworks like in Grails Traits with setup/clean up code Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  30. Simplifying specifications with traits Share common logic across different specifications

    No specification inheritance involved Can provide setup/cleanup methods Can have instance variables Groovy 2.3+ is required Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ G roovy 2.3
  31. Simplifying specifications with traits t r a i t D

    a t a b a s e T r a i t { @ S h a r e d D B C o n n e c t i o n d b C o n n e c t i o n d e f s e t u p S p e c ( ) { / / o r @ B e f o r e C l a s s / / p r e p a r e D B } d e f c l e a n u p S p e c ( ) { / / o r @ A f t e r C l a s s / / c l e a n u p D B } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  32. Simplifying specifications with traits t r a i t D

    a t a b a s e T r a i t { @ S h a r e d D B C o n n e c t i o n d b C o n n e c t i o n d e f s e t u p S p e c ( ) { / / o r @ B e f o r e C l a s s / / p r e p a r e D B } d e f c l e a n u p S p e c ( ) { / / o r @ A f t e r C l a s s / / c l e a n u p D B } } c l a s s F a n c y 1 D a t a b a s e S p e c e x t e n d s S p e c i f i c a t i o n i m p l e m e n t s D a t a b a s e T r a i t { d e f " s h o u l d d o f a n c y 1 t h i n g o n d a t a b a s e " ( ) { / / f a n c y 1 t h i n g s o n d a t a b a s e } } c l a s s F a n c y 2 D a t a b a s e S p e c e x t e n d s S p e c i f i c a t i o n i m p l e m e n t s D a t a b a s e T r a i t { d e f " s h o u l d d o f a n c y 2 t h i n g o n d a t a b a s e " ( ) { / / f a n c y 2 t h i n g s o n d a t a b a s e } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  33. Parametrized tests - basic case d e f " s

    h o u l d a d d t w o i n t e g e r s " ( ) { g i v e n : C a l c u l a t o r s u t = n e w S i m p l e C a l c u l a t o r ( ) w h e n : i n t r e s u l t = s u t . a d d ( x , y ) t h e n : r e s u l t = = e x p e c t e d R e s u l t w h e r e : x | y | | e x p e c t e d R e s u l t 1 | 2 | | 3 - 2 | 3 | | 1 - 1 | - 2 | | - 3 } build-in support with w h e r e keyword does not stop on failure for given test case syntatic sugar for table-like data formatting Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  34. Parametrized tests - could look better p r i v

    a t e P E S E L V a l i d a t o r s u t = n e w F a k e P E S E L V a l i d a t o r ( ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  35. Parametrized tests - could look better p r i v

    a t e P E S E L V a l i d a t o r s u t = n e w F a k e P E S E L V a l i d a t o r ( ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  36. Parametrized tests - could look better p r i v

    a t e P E S E L V a l i d a t o r s u t = n e w F a k e P E S E L V a l i d a t o r ( ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } one combined test for all test cases not very readable in case of failure(s) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  37. Parametrized tests - @Unroll @ U n r o l

    l d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s ( m u l t i p l e t e s t s ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  38. Parametrized tests - @Unroll @ U n r o l

    l d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s ( m u l t i p l e t e s t s ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  39. Parametrized tests - @Unroll @ U n r o l

    l d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s ( m u l t i p l e t e s t s ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } @ U n r o l l to generate separate test per test case still confusing in case of failure Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  40. Parametrized tests - @Unroll + #pesel @ U n r

    o l l d e f " s h o u l d v a l i d a t e P E S E L ( # p e s e l ) c o r r e c t n e s s ( # i s V a l i d ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  41. Parametrized tests - @Unroll + #pesel @ U n r

    o l l d e f " s h o u l d v a l i d a t e P E S E L ( # p e s e l ) c o r r e c t n e s s ( # i s V a l i d ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  42. Parametrized tests - @Unroll + #pesel @ U n r

    o l l d e f " s h o u l d v a l i d a t e P E S E L ( # p e s e l ) c o r r e c t n e s s ( # i s V a l i d ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e } # p e s e l and # i s V a l i d to put input parameter into test report more readable, but still can be confusing for business people reading BDD reports Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  43. Parametrized tests - @Unroll with message @ U n r

    o l l ( " P E S E L ' # p e s e l ' s h o u l d b e # d e s c r i p t i o n " ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e d e s c r i p t i o n = i s V a l i d ? " v a l i d " : " i n v a l i d " } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  44. Parametrized tests - @Unroll with message @ U n r

    o l l ( " P E S E L ' # p e s e l ' s h o u l d b e # d e s c r i p t i o n " ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e d e s c r i p t i o n = i s V a l i d ? " v a l i d " : " i n v a l i d " } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  45. Parametrized tests - @Unroll with message @ U n r

    o l l ( " P E S E L ' # p e s e l ' s h o u l d b e # d e s c r i p t i o n " ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l | | i s V a l i d " 1 2 3 " | | f a l s e " a b c d " | | f a l s e " 9 7 1 1 0 2 0 8 6 3 1 " | | t r u e d e s c r i p t i o n = i s V a l i d ? " v a l i d " : " i n v a l i d " } distinguish test name and test description used in test report additional (artificial) parameter for test report only with autocompletion in IntelliJ IDEA Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  46. Parametrized tests - data pipes @ U n r o

    l l ( " P E S E L ' # p e s e l ' s h o u l d b e # d e s c r i p t i o n " ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) = = i s V a l i d w h e r e : p e s e l < < [ " 1 2 3 " , " a b c d " , " 9 7 1 1 0 2 0 8 6 3 1 " ] i s V a l i d < < [ f a l s e , f a l s e , t r u e ] d e s c r i p t i o n = i s V a l i d ? " v a l i d " : " i n v a l i d " } table is syntatic sugar for data pipes "< < " operator to connect data variable with data provider Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  47. Parametrized tests - more data providers @ U n r

    o l l ( " # p e s e l i s v a l i d ( # d b I d ) " ) d e f " s h o u l d v a l i d a t e P E S E L c o r r e c t n e s s ( C S V ) " ( ) { e x p e c t : s u t . v a l i d a t e ( p e s e l ) w h e r e : [ d b I d , _ , _ , p e s e l ] < < r e a d V a l i d P e o p l e F r o m C S V F i l e ( ) . r e a d L i n e s ( ) . c o l l e c t { i t . s p l i t ( ' , ' ) } / / u g l y w a y t o r e a d C S V - d o n ' t d o t h i s } not only static elements everything iterable in Groovy also SQL rows or CSV files Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  48. Simple Stubbing c l a s s D a o

    S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b m e t h o d c a l l " ( ) { g i v e n : D a o d a o = S t u b ( D a o ) d a o . g e t C o u n t ( ) > > 1 e x p e c t : d a o . g e t C o u n t ( ) = = 1 } } i n t e r f a c e D a o { i n t g e t C o u n t ( ) I t e m s a v e ( I t e m i t e m ) } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  49. Simple Stubbing - inline c l a s s D

    a o S p e c e x t e n d s S p e c i f i c a t i o n { p r i v a t e D a o < I t e m > d a o = S t u b ( D a o ) { d a o . g e t C o u n t ( ) > > 1 } d e f " s h o u l d s t u b m e t h o d c a l l " ( ) { e x p e c t : d a o . g e t C o u n t ( ) = = 1 } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  50. Simple Stubbing - consecutive calls c l a s s

    D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b c o n s e c u t i v e c a l l s " ( ) { g i v e n : D a o < I t e m > d a o = S t u b ( D a o ) d a o . g e t C o u n t ( ) > > 1 > > 2 e x p e c t : d a o . g e t C o u n t ( ) = = 1 a n d : d a o . g e t C o u n t ( ) = = 2 a n d : d a o . g e t C o u n t ( ) = = 2 } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  51. Simple Stubbing - consecutive calls (list) c l a s

    s D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b c o n s e c u t i v e c a l l s ( l i s t ) " ( ) { g i v e n : D a o < I t e m > d a o = S t u b ( D a o ) d a o . g e t C o u n t ( ) > > > [ 1 , 2 ] e x p e c t : d a o . g e t C o u n t ( ) = = 1 a n d : d a o . g e t C o u n t ( ) = = 2 a n d : d a o . g e t C o u n t ( ) = = 2 } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  52. Simple Stubbing - input parameters (array) c l a s

    s D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b m e t h o d c a l l t o r e t u r n i n p u t v a l u e " ( ) { g i v e n : I t e m b a s e I t e m = n e w I t e m ( ) a n d : D a o < I t e m > d a o = S t u b ( D a o ) d a o . s a v e ( _ ) > > { i t [ 0 ] } w h e n : I t e m r e t u r n e d I t e m = d a o . s a v e ( b a s e I t e m ) t h e n : b a s e I t e m . i s ( r e t u r n e d I t e m ) } } by default array of input parameters Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  53. Simple Stubbing - named input parameters c l a s

    s D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b m e t h o d c a l l t o r e t u r n i n p u t v a l u e " ( ) { g i v e n : I t e m b a s e I t e m = n e w I t e m ( ) a n d : D a o < I t e m > d a o = S t u b ( D a o ) d a o . s a v e ( _ ) > > { I t e m i t e m - > i t e m } w h e n : I t e m r e t u r n e d I t e m = d a o . s a v e ( b a s e I t e m ) t h e n : b a s e I t e m . i s ( r e t u r n e d I t e m ) } } can be declared explicit as named (and typed) parameters all have to be declared Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  54. Simple Stubbing - throwing exception c l a s s

    D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d t h r o w e x c e p t i o n f o r s p e c i f i c i n p u t p a r a m e t e r s " ( ) { g i v e n : D a o < I t e m > d a o = S t u b ( D a o ) d a o . s a v e ( _ ) > > { I t e m i t e m - > t h r o w n e w I l l e g a l A r g u m e n t E x c e p t i o n ( i t e m . t o S t r i n g ( ) ) } w h e n : d a o . s a v e ( n e w I t e m ( ) ) t h e n : t h r o w n ( I l l e g a l A r g u m e n t E x c e p t i o n ) } } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  55. Simple Stubbing - throwing exception c l a s s

    D a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d t h r o w e x c e p t i o n f o r s p e c i f i c i n p u t p a r a m e t e r s " ( ) { g i v e n : D a o < I t e m > d a o = S t u b ( D a o ) d a o . s a v e ( _ ) > > { I t e m i t e m - > t h r o w n e w I l l e g a l A r g u m e n t E x c e p t i o n ( i t e m . t o S t r i n g ( ) ) } w h e n : d a o . s a v e ( n e w I t e m ( ) ) t h e n : t h r o w n ( I l l e g a l A r g u m e n t E x c e p t i o n ) w h e n : d a o . s a v e ( n u l l ) t h e n : t h r o w n ( I l l e g a l A r g u m e n t E x c e p t i o n ) } } smart t o S t r i n g ( ) from Groovy (for null objects) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  56. Stubbing and verifying together c l a s s D

    a o S p e c e x t e n d s S p e c i f i c a t i o n { d e f " s h o u l d s t u b a n d v e r i f y " ( ) { g i v e n : I t e m b a s e I t e m = n e w I t e m ( ) a n d : D a o < I t e m > d a o = S t u b ( D a o ) w h e n : I t e m r e t u r n e d I t e m = d a o . s a v e ( b a s e I t e m ) t h e n : 1 * d a o . s a v e ( _ ) > > { I t e m i t e m - > i t e m } a n d : b a s e I t e m . i s ( r e t u r n e d I t e m ) } } has to be in the same statement in t h e n section Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  57. Overriding stubbed value c l a s s B u

    s i n e s s S e r v i c e S p e c e x t e n d s S p e c i f i c a t i o n { p r i v a t e B o r i n g C o l l a b o r a t o r b o r i n g S t u b = S t u b ( B o r i n g C o l l a b o r a t o r ) { s e n d P i n g ( ) > > " O K " } p r i v a t e B u s i n e s s S e r v i c e s u t = n e w B u s i n e s s S e r v i c e ( b o r i n g S t u b ) d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 1 " ( ) { w h e n : i n t r e s u l t = s u t . c a l c u l a t e I m p o r t a n t T h i n g s ( ) t h e n : r e s u l t = = E X P E C T E D _ R E S U L T _ 1 } d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 2 " ( ) { . . . } many positive cases with s e n d P i n g ( ) > > " O K " how to test negative scenario? Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  58. Overriding stubbed value - broken c l a s s

    B u s i n e s s S e r v i c e S p e c e x t e n d s S p e c i f i c a t i o n { p r i v a t e B o r i n g C o l l a b o r a t o r b o r i n g S t u b = S t u b ( B o r i n g C o l l a b o r a t o r ) { s e n d P i n g ( ) > > " O K " } p r i v a t e B u s i n e s s S e r v i c e s u t = n e w B u s i n e s s S e r v i c e ( b o r i n g S t u b ) d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 1 " ( ) { . . . } d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 2 " ( ) { . . . } @ I g n o r e ( " b r o k e n " ) d e f " s h o u l d c o v e r c o l l a b o r a t o r e r r o r " ( ) { g i v e n : b o r i n g S t u b . s e n d P i n g ( ) > > " E R R O R " / / d o e s n o t w o r k ! w h e n : s u t . c a l c u l a t e I m p o r t a n t T h i n g s ( ) t h e n : t h r o w n ( I l l e g a l S t a t e E x c e p t i o n ) } override in Mockito style does not work Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  59. Overriding stubbed value - in t h e n section

    c l a s s B u s i n e s s S e r v i c e S p e c e x t e n d s S p e c i f i c a t i o n { p r i v a t e B o r i n g C o l l a b o r a t o r b o r i n g S t u b = S t u b ( B o r i n g C o l l a b o r a t o r ) { s e n d P i n g ( ) > > " O K " } p r i v a t e B u s i n e s s S e r v i c e s u t = n e w B u s i n e s s S e r v i c e ( b o r i n g S t u b ) d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 1 " ( ) { . . . } d e f " s h o u l d c a l c u l a t e i m p o r t a n t b u s i n e s s c a s e 2 " ( ) { . . . } d e f " s h o u l d c o v e r c o l l a b o r a t o r e r r o r " ( ) { w h e n : s u t . c a l c u l a t e I m p o r t a n t T h i n g s ( ) t h e n : b o r i n g S t u b . s e n d P i n g ( ) > > " E R R O R " / / s t u b b i n g i n " t h e n " , l o o k s b a d a n d : t h r o w n ( I l l e g a l S t a t e E x c e p t i o n ) } has to placed in t h e n section Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  60. Verification in order - issue @ I g n o

    r e ( " b r o k e n " ) d e f " n o t i f i c a t i o n s h o u l d b e s e n d a f t e r b u s i n e s s o p e r a t i o n ( i g n o r e o r d e r ) " ( ) { g i v e n : D a o d a o = M o c k ( ) N o t i f i e r n o t i f i e r = M o c k ( ) a n d : d e f s u t = n e w B u s i n e s s S e r v i c e ( d a o , n o t i f i e r ) w h e n : s u t . p r o c e s s O r d e r ( ) t h e n : 1 * d a o . s a v e O r d e r ( _ ) / / o r d e r d o e s n o t m a t t e r 1 * n o t i f i e r . s e n d N o t i f i c a t i o n ( _ ) } order is not verified notification could be send before saving order Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  61. Verification in order - solution d e f " n

    o t i f i c a t i o n s h o u l d b e s e n d a f t e r b u s i n e s s o p e r a t i o n " ( ) { g i v e n : D a o d a o = M o c k ( ) N o t i f i e r n o t i f i e r = M o c k ( ) a n d : d e f s u t = n e w B u s i n e s s S e r v i c e ( d a o , n o t i f i e r ) w h e n : s u t . p r o c e s s O r d e r ( ) t h e n : 1 * d a o . s a v e O r d e r ( _ ) t h e n : 1 * n o t i f i e r . s e n d N o t i f i c a t i o n ( _ ) } mutiple then block are evaluated separately Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  62. Verification in order - gotcha @ I g n o

    r e ( " b r o k e n " ) d e f " n o t i f i c a t i o n s h o u l d b e s e n d a f t e r b u s i n e s s o p e r a t i o n ( w i t h ' a n d ' ) " ( ) { g i v e n : D a o d a o = M o c k ( ) N o t i f i e r n o t i f i e r = M o c k ( ) a n d : d e f s u t = n e w B u s i n e s s S e r v i c e ( d a o , n o t i f i e r ) w h e n : s u t . p r o c e s s O r d e r ( ) t h e n : 1 * d a o . s a v e O r d e r ( _ ) a n d : / / ' a n d ' d o e s n o t v e r i f y e x e c u t i o n o r d e r 1 * n o t i f i e r . s e n d N o t i f i c a t i o n ( _ ) } a n d does not verify execution order it is for documentation purposes only Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  63. Active condition waiting PoolingConditions Active waiting for condition to pass

    - like in Awaitility No more s l e e p ( 3 0 0 0 ) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  64. Active condition waiting - example d e f " s

    h o u l d r e c e i v e p a c k e t a f t e r w h i l e " ( ) { g i v e n : d e f c o n d i t i o n s = n e w P o l l i n g C o n d i t i o n s ( ) d e f a s y n c h r o n o u s M e s s a g e Q u e u e = n e w D e l a y e d D e l i v e r y M e s s a g e Q u e u e F a c a d e ( ) w h e n : a s y n c h r o n o u s M e s s a g e Q u e u e . s e n d P i n g ( ) t h e n : c o n d i t i o n s . e v e n t u a l l y { a s s e r t a s y n c h r o n o u s M e s s a g e Q u e u e . n u m b e r O f R e c e i v e d P a c k e t s = = 1 } } With default values Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  65. Active condition waiting - example d e f " s

    h o u l d r e c e i v e p a c k e t a f t e r w h i l e " ( ) { g i v e n : d e f c o n d i t i o n s = n e w P o l l i n g C o n d i t i o n s ( t i m e o u t : 2 , i n i t i a l D e l a y : 0 . 3 ) d e f a s y n c h r o n o u s M e s s a g e Q u e u e = n e w D e l a y e d D e l i v e r y M e s s a g e Q u e u e F a c a d e ( ) w h e n : a s y n c h r o n o u s M e s s a g e Q u e u e . s e n d P i n g ( ) t h e n : c o n d i t i o n s . e v e n t u a l l y { a s s e r t a s y n c h r o n o u s M e s s a g e Q u e u e . n u m b e r O f R e c e i v e d P a c k e t s = = 1 } } With custom configuration Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  66. Active condition waiting - example d e f " s

    h o u l d r e c e i v e p a c k e t a f t e r w h i l e " ( ) { g i v e n : d e f c o n d i t i o n s = n e w P o l l i n g C o n d i t i o n s ( t i m e o u t : 2 , i n i t i a l D e l a y : 0 . 3 ) d e f a s y n c h r o n o u s M e s s a g e Q u e u e = n e w D e l a y e d D e l i v e r y M e s s a g e Q u e u e F a c a d e ( ) w h e n : a s y n c h r o n o u s M e s s a g e Q u e u e . s e n d P i n g ( ) t h e n : c o n d i t i o n s . w i t h i n ( 5 ) { a s s e r t a s y n c h r o n o u s M e s s a g e Q u e u e . n u m b e r O f R e c e i v e d P a c k e t s = = 1 } } w i t h i n g ( t i m e o u t I n S e c o n d s ) can override original timeout in specific call Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  67. Active condition waiting - example d e f " s

    h o u l d r e c e i v e p a c k e t a f t e r w h i l e " ( ) { g i v e n : P o l l i n g C o n d i t i o n s c o n d i t i o n s = n e w P o l l i n g C o n d i t i o n s ( ) d e f a s y n c h r o n o u s M e s s a g e Q u e u e = n e w D e l a y e d D e l i v e r y M e s s a g e Q u e u e F a c a d e ( ) w h e n : a s y n c h r o n o u s M e s s a g e Q u e u e . s e n d P i n g ( ) t h e n : c o n d i t i o n s . e v e n t u a l l y { a s y n c h r o n o u s M e s s a g e Q u e u e . n u m b e r O f R e c e i v e d P a c k e t s = = 1 } } a s s e r t keyword can omitted when P o l l i n g C o n d i t i o n s is declared explicit (not with d e f ) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  68. Active condition waiting PoolingConditions Active waiting for condition to pass

    - like in Awaitility No more s l e e p ( 3 0 0 0 ) Ability to specify: timeout, initialDelay, delay and factor a s s e r t keyword is (usually) required Useful in multithreading code and asynchronous external calls (like message queues) Cannot be used for interaction verification Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  69. Active condition waiting PoolingConditions Active waiting for condition to pass

    - like in Awaitility No more s l e e p ( 3 0 0 0 ) Ability to specify: timeout, initialDelay, delay and factor a s s e r t keyword is (usually) required Useful in multithreading code and asynchronous external calls (like message queues) Cannot be used for interaction verification Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 0.7
  70. Asserting previous value (manual way) Check if/how given value was

    changed d e f " s h o u l d c r e a t e n e w r e c o r d w h e n i t e m i s s a v e d ( m a n u a l w a y ) " ( ) { g i v e n : D a o d a o = n e w D u m m y D a o ( ) a n d : i n t o r i g i n a l N u m b e r O f R e c o r d s = d a o . g e t C o u n t ( ) w h e n : d a o . s a v e ( n e w I t e m ( ) ) t h e n : d a o . g e t C o u n t ( ) = = o r i g i n a l N u m b e r O f R e c o r d s + 1 } i n t e r f a c e D a o { i n t g e t C o u n t ( ) v o i d s a v e ( I t e m i t e m ) } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  71. Asserting previous value (Spock way) d e f " s

    h o u l d c r e a t e n e w r e c o r d w h e n i t e m i s s a v e d " ( ) { g i v e n : D a o d a o = n e w D u m m y D a o ( ) w h e n : d a o . s a v e ( n e w I t e m ( ) ) t h e n : d a o . g e t C o u n t ( ) = = o l d ( d a o . g e t C o u n t ( ) ) + 1 } i n t e r f a c e D a o { i n t g e t C o u n t ( ) v o i d s a v e ( I t e m i t e m ) } Spock generates code to keep the old value Works with fields and methods Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  72. BDD-like documentation Highlight business context Block description (w h e

    n : " p u t e l e m e n t o n s t a c k " ) @ S e e ( " h t t p s : / / e n . w i k i p e d i a . o r g / w i k i / S p o c k " ) @ I s s u e ( " h t t p : / / t i n y u r l . c o m / s p o c k - i s s u e 2 6 0 " ) @ S u b j e c t ( " T O D O : p r z y k l a d y " ) @ T i t l e @ N a r r a t i v e Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  73. Optional runtime configuration Configures Spock behavior Injectable into run context

    and extensions By default for Runner Report Ability to create custom configuration when needed Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 0.7, 1.0
  74. Optional runtime configuration ~ / . s p o c

    k / S p o c k C o n f i g . g r o o v y r u n n e r { i n c l u d e p a c k a g e . D e f a u l t S p e c i f i c a t i o n B a s e C l a s s e x c l u d e p a c k a g e . I n t e g r a t i o n A n n o t a t i o n o p t i m i z e R u n O r d e r = t r u e f i l t e r S t a c k T r a c e = f a l s e } r e p o r t { e n a b l e d = t r u e i s s u e N a m e P r e f i x = " J L T N - " i s s u e U r l P r e f i x = " h t t p s : / / g i t h u b . c o m / C o n f i t u r a / j e l a t y n a / i s s u e s " l o g F i l e S u f f i x = " . l o g " . . . } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 0.7, 1.0
  75. Optional runtime configuration - location Reads from S p o

    c k C o n f i g . g r o o v y taken from: - D s p o c k . c o n f i g u r a t i o n Classpath Spock home directory - D s p o c k . u s e r . h o m e $ S P O C K _ U S E R _ H O M E ~ / . s p o c k / Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 0.7, 1.0
  76. Exception util Makes assertions on nested exception causes easier Taken

    after Grails s p o c k . u t i l . E x c e p t i o n s T h r o w a b l e g e t R o o t C a u s e ( T h r o w a b l e e x c e p t i o n ) L i s t < T h r o w a b l e > g e t C a u s e C h a i n ( T h r o w a b l e e x c e p t i o n ) Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  77. Exception util Makes assertions on nested exception causes easier Taken

    after Grails s p o c k . u t i l . E x c e p t i o n s T h r o w a b l e g e t R o o t C a u s e ( T h r o w a b l e e x c e p t i o n ) L i s t < T h r o w a b l e > g e t C a u s e C h a i n ( T h r o w a b l e e x c e p t i o n ) d e f " s h o u l d t h r o w b u s i n e s s e x c e p t i o n o n c o m m u n i c a t i o n e r r o r k e e p i n g o r i g i n a l " ( ) w h e n : s u t . s e n d P i n g ( T E S T _ R E Q U E S T _ I D ) t h e n : d e f e = t h r o w n ( C o m m u n i c a t i o n E x c e p t i o n ) e . m e s s a g e = = " C o m m u n i c a t i o n p r o b l e m w h e n s e n d i n g r e q u e s t w i t h i d : 5 " E x c e p t i o n s . g e t R o o t C a u s e ( e ) . c l a s s = = C o n n e c t E x c e p t i o n } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  78. Exception util Makes assertions on nested exception causes easier Taken

    after Grails s p o c k . u t i l . E x c e p t i o n s T h r o w a b l e g e t R o o t C a u s e ( T h r o w a b l e e x c e p t i o n ) L i s t < T h r o w a b l e > g e t C a u s e C h a i n ( T h r o w a b l e e x c e p t i o n ) d e f " s h o u l d t h r o w b u s i n e s s e x c e p t i o n o n c o m m u n i c a t i o n e r r o r k e e p i n g o r i g i n a l " ( ) w h e n : s u t . s e n d P i n g ( T E S T _ R E Q U E S T _ I D ) t h e n : d e f e = t h r o w n ( C o m m u n i c a t i o n E x c e p t i o n ) e . m e s s a g e = = " C o m m u n i c a t i o n p r o b l e m w h e n s e n d i n g r e q u e s t w i t h i d : 5 " E x c e p t i o n s . g e t R o o t C a u s e ( e ) . c l a s s = = C o n n e c t E x c e p t i o n } Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/ 1.0
  79. Extensibility Powerful extension mechanism Many of features implemented as built-in

    extensions Most of already presented Official extensions available as separate modules Spring, Guice, Tapestry, Unitils (Sometimes) easier to write one's own extension than have accepted pull request JUnit rules (@ R u l e / @ C l a s s R u l e ) can be also used Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/
  80. Summary (aka Why I like Spock?) Consist and readable test

    code Tests as specification by default All Groovy magic available to help Embedded mocking framework Although Mockito can be used if preferred Highly extensible Compatible with tools supporting JUnit Marcin Zajączkowski @SolidSoftBlog Version: 1.11p-4d
  81. Thank you (and remember about the feedback!) Marcin Zajączkowski http://blog.solidsoft.info/

    @SolidSoftBlog [email protected] Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/