Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

About me Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 3

Slide 3 text

2 interesting companies Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 4

Slide 4 text

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/

Slide 5

Slide 5 text

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/

Slide 6

Slide 6 text

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/

Slide 7

Slide 7 text

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/

Slide 8

Slide 8 text

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/

Slide 9

Slide 9 text

Conditional test exection Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

@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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

@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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

@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

Slide 20

Slide 20 text

Cleaning up Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

@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

Slide 25

Slide 25 text

@AutoCleanup Cleans up resource at the end of its life time Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

@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

Slide 30

Slide 30 text

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/

Slide 31

Slide 31 text

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/

Slide 32

Slide 32 text

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/

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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/

Slide 36

Slide 36 text

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/

Slide 37

Slide 37 text

Parametrized tests Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 38

Slide 38 text

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/

Slide 39

Slide 39 text

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/

Slide 40

Slide 40 text

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/

Slide 41

Slide 41 text

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/

Slide 42

Slide 42 text

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/

Slide 43

Slide 43 text

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/

Slide 44

Slide 44 text

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/

Slide 45

Slide 45 text

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/

Slide 46

Slide 46 text

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/

Slide 47

Slide 47 text

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/

Slide 48

Slide 48 text

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/

Slide 49

Slide 49 text

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/

Slide 50

Slide 50 text

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/

Slide 51

Slide 51 text

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/

Slide 52

Slide 52 text

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/

Slide 53

Slide 53 text

Mocking Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 54

Slide 54 text

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/

Slide 55

Slide 55 text

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/

Slide 56

Slide 56 text

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/

Slide 57

Slide 57 text

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/

Slide 58

Slide 58 text

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/

Slide 59

Slide 59 text

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/

Slide 60

Slide 60 text

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/

Slide 61

Slide 61 text

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/

Slide 62

Slide 62 text

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/

Slide 63

Slide 63 text

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/

Slide 64

Slide 64 text

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/

Slide 65

Slide 65 text

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/

Slide 66

Slide 66 text

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/

Slide 67

Slide 67 text

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/

Slide 68

Slide 68 text

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/

Slide 69

Slide 69 text

Miscellaneous Marcin Zajączkowski @SolidSoftBlog http://blog.solidsoft.info/

Slide 70

Slide 70 text

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/

Slide 71

Slide 71 text

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/

Slide 72

Slide 72 text

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/

Slide 73

Slide 73 text

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/

Slide 74

Slide 74 text

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/

Slide 75

Slide 75 text

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/

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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/

Slide 78

Slide 78 text

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/

Slide 79

Slide 79 text

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/

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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/

Slide 84

Slide 84 text

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/

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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/

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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/