Slide 1

Slide 1 text

WRITING CLEANER, STURDIER CODE WITH UNIT TESTING David Herrera alleyinteractive.com @dlh01

Slide 2

Slide 2 text

OUTLINE 1. Unit testing overview 2. Examining a unit test 3. Testing our own code 4. Unit testing in WordPress

Slide 3

Slide 3 text

WHAT IS UNIT TESTING? Units = small parts Meeting expectations

Slide 4

Slide 4 text

UNIT TESTS IN WORDPRESS CORE Reject an u p d a t e _ o p t i o n ( ) with an illegal key Set the correct status to future posts Clear the usermeta cache after a user is deleted

Slide 5

Slide 5 text

WHAT IS PHPUNIT? See also: QUnit

Slide 6

Slide 6 text

GETTING TO P H P U N I T Next: "Setting up Vagrant for Unit Testing" with Paul Bearne

Slide 7

Slide 7 text

CREATE A PLUGIN WITH UNIT TESTS $ w p s c a f f o l d p l u g i n m y - p l u g i n $ l s m y - p l u g i n > b i n m y - p l u g i n . p h p p h p u n i t . x m l r e a d m e . t x t t e s t s

Slide 8

Slide 8 text

ADD UNIT TEST FILES TO AN EXISTING PLUGIN $ w p s c a f f o l d u n i t - t e s t s m y - e x i s t i n g - p l u g i n

Slide 9

Slide 9 text

RUN THE DEFAULT TEST $ c d m y - p l u g i n / $ p h p u n i t

Slide 10

Slide 10 text

DEFAULT TEST OUTPUT

Slide 11

Slide 11 text

WHAT WAS THE TEST? < ? p h p / / t e s t s / t e s t - s a m p l e . p h p c l a s s S a m p l e T e s t e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t S a m p l e ( ) { / / r e p l a c e t h i s w i t h s o m e a c t u a l t e s t i n g c o d e $ t h i s - > a s s e r t T r u e ( t r u e ) ; } }

Slide 12

Slide 12 text

THE DEFAULT TEST < ? p h p / / t e s t s / t e s t - s a m p l e . p h p f u n c t i o n t e s t S a m p l e ( ) { / / r e p l a c e t h i s w i t h s o m e a c t u a l t e s t i n g c o d e $ t h i s - > a s s e r t T r u e ( t r u e ) ; }

Slide 13

Slide 13 text

THE DEFAULT TEST (AMENDED) < ? p h p / / t e s t s / t e s t - s a m p l e . p h p f u n c t i o n t e s t S a m p l e ( ) { $ f o o = t r u e ; $ t h i s - > a s s e r t T r u e ( $ f o o ) ; }

Slide 14

Slide 14 text

ASSERTIONS a s s e r t F a l s e ( ) a s s e r t E q u a l s ( ) a s s e r t I n t e r n a l T y p e ( ) And many more: a s s e r t A r r a y H a s K e y ( ) a s s e r t C o u n t ( ) a s s e r t E m p t y ( ) a s s e r t F i l e E x i s t s ( ) a s s e r t G r e a t e r T h a n ( ) a s s e r t L e s s T h a n ( ) a s s e r t O b j e c t H a s A t t r i b u t e ( ) phpunit.de/manual

Slide 15

Slide 15 text

MULTIPLE TESTS < ? p h p c l a s s S a m p l e T e s t e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t _ i s _ t r u e ( ) { $ f o o = t r u e ; $ t h i s - > a s s e r t T r u e ( $ f o o ) ; } f u n c t i o n t e s t _ i s _ n u l l ( ) { $ f o o = n u l l ; $ t h i s - > a s s e r t N u l l ( $ f o o ) ; } }

Slide 16

Slide 16 text

MULTIPLE TESTS OUTPUT

Slide 17

Slide 17 text

FAILED TESTS < ? p h p c l a s s S a m p l e T e s t e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t _ i s _ t r u e ( ) { / * . . . * / } f u n c t i o n t e s t _ i s _ n u l l ( ) { / * . . . * / } f u n c t i o n t e s t _ n a m e s ( ) { $ n a m e = ' W o r d p r e s s ' ; $ t h i s - > a s s e r t E q u a l s ( ' W o r d P r e s s ' , $ n a m e ) ; } }

Slide 18

Slide 18 text

FAILED TEST OUTPUT

Slide 19

Slide 19 text

TESTING OUR CODE < ? p h p / / m y - p l u g i n . p h p f u n c t i o n s a y _ h e l l o ( $ n a m e ) { r e t u r n s p r i n t f ( _ _ ( ' H e l l o % s ! ' , ' m y - p l u g i n ' ) , $ n a m e ) ; } < ? p h p / / t e s t s / t e s t - s a m p l e . p h p f u n c t i o n t e s t _ s a y _ h e l l o ( ) { $ e x p e c t e d = ' H e l l o , D a v i d ! ' ; $ a c t u a l = s a y _ h e l l o ( ' D a v i d ' ) ; $ t h i s - > a s s e r t E q u a l s ( $ e x p e c t e d , $ a c t u a l ) ; }

Slide 20

Slide 20 text

CUSTOM CODE OUTPUT

Slide 21

Slide 21 text

(FIXING THE MISTAKE) < ? p h p / / m y - p l u g i n . p h p f u n c t i o n s a y _ h e l l o ( $ n a m e ) { - r e t u r n s p r i n t f ( _ _ ( ' H e l l o % s ! ' , ' m y - p l u g i n ' ) , $ n a m e ) ; + r e t u r n s p r i n t f ( _ _ ( ' H e l l o , % s ! ' , ' m y - p l u g i n ' ) , $ n a m e ) ; }

Slide 22

Slide 22 text

ROCK PAPER SCISSORS < ? p h p f u n c t i o n r o c k _ w i n s ( $ o p p o n e n t ) { i f ( ' s c i s s o r s ' = = s t r t o l o w e r ( $ o p p o n e n t ) ) { r e t u r n t r u e ; } e l s e { r e t u r n f a l s e ; } }

Slide 23

Slide 23 text

ROCK PAPER SCISSORS < ? p h p c l a s s T e s t _ R P S e x t e n d s W P _ U n i t T e s t C a s e { }

Slide 24

Slide 24 text

ROCK PAPER SCISSORS < ? p h p c l a s s T e s t _ R P S e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t _ a g a i n s t _ s c i s s o r s ( ) { $ a c t u a l = r o c k _ w i n s ( ' s c i s s o r s ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; } }

Slide 25

Slide 25 text

ROCK PAPER SCISSORS < ? p h p c l a s s T e s t _ R P S e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t _ a g a i n s t _ s c i s s o r s ( ) { $ a c t u a l = r o c k _ w i n s ( ' s c i s s o r s ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; } f u n c t i o n t e s t _ a g a i n s t _ p a p e r ( ) { $ a c t u a l = r o c k _ w i n s ( ' p a p e r ' ) ; $ t h i s - > a s s e r t F a l s e ( $ a c t u a l ) ; } }

Slide 26

Slide 26 text

ROCK PAPER SCISSORS < ? p h p c l a s s T e s t _ R P S e x t e n d s W P _ U n i t T e s t C a s e { f u n c t i o n t e s t _ a g a i n s t _ s c i s s o r s ( ) { $ a c t u a l = r o c k _ w i n s ( ' s c i s s o r s ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; } f u n c t i o n t e s t _ a g a i n s t _ p a p e r ( ) { $ a c t u a l = r o c k _ w i n s ( ' p a p e r ' ) ; $ t h i s - > a s s e r t F a l s e ( $ a c t u a l ) ; } f u n c t i o n t e s t _ a g a i n s t _ b a n a n a ( ) { $ a c t u a l = r o c k _ w i n s ( ' b a n a n a ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; } }

Slide 27

Slide 27 text

RPS OUTPUT

Slide 28

Slide 28 text

ROCK PAPER SCISSORS (FIXED) < ? p h p f u n c t i o n r o c k _ w i n s ( $ o p p o n e n t ) { $ v a l i d = a r r a y ( ' r o c k ' , ' p a p e r ' , ' s c i s s o r s ' ) ; $ o p p o n e n t = s t r t o l o w e r ( $ o p p o n e n t ) ; i f ( ! i n _ a r r a y ( $ o p p o n e n t , $ v a l i d ) ) { r e t u r n t r u e ; } r e t u r n ' s c i s s o r s ' = = $ o p p o n e n t ; }

Slide 29

Slide 29 text

RPS OUTPUT

Slide 30

Slide 30 text

MAINTAINABLE CODE < ? p h p f u n c t i o n r o c k _ w i n s ( $ o p p o n e n t ) { i f ( ! i s _ l e g a l _ t h r o w ( $ o p p o n e n t ) ) { r e t u r n t r u e ; } / / . . . } f u n c t i o n i s _ l e g a l _ t h r o w ( $ o p p o n e n t ) { / / . . . }

Slide 31

Slide 31 text

SEPARATE TESTS < ? p h p f u n c t i o n t e s t _ i s _ l e g a l _ t h r o w ( ) { $ a c t u a l = i s _ l e g a l _ t h r o w ( ' s c i s s o r s ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; $ a c t u a l = i s _ l e g a l _ t h r o w ( ' r o c k ' ) ; $ t h i s - > a s s e r t T r u e ( $ a c t u a l ) ; $ a c t u a l = i s _ l e g a l _ t h r o w ( ' b a n a n a ' ) ; $ t h i s - > a s s e r t F a l s e ( $ a c t u a l ) ; $ a c t u a l = i s _ l e g a l _ t h r o w ( a r r a y ( ' r o c k ' , ' p a p e r ' , ' s c i s s o r s ' ) ) ; $ t h i s - > a s s e r t F a l s e ( $ a c t u a l ) ; / / . . . }

Slide 32

Slide 32 text

CORE TESTS f u n c t i o n t e s t _ b a d _ o p t i o n _ n a m e s ( ) { f o r e a c h ( a r r a y ( ' ' , ' 0 ' , ' ' , 0 , f a l s e , n u l l ) a s $ e m p t y ) { $ t h i s - > a s s e r t F a l s e ( g e t _ o p t i o n ( $ e m p t y ) ) ; $ t h i s - > a s s e r t F a l s e ( a d d _ o p t i o n ( $ e m p t y , ' ' ) ) ; $ t h i s - > a s s e r t F a l s e ( u p d a t e _ o p t i o n ( $ e m p t y , ' ' ) ) ; $ t h i s - > a s s e r t F a l s e ( d e l e t e _ o p t i o n ( $ e m p t y ) ) ; } } f u n c t i o n t e s t _ r e t u r n s _ f a l s e _ i f _ g i v e n _ a n _ i n v a l i d _ e m a i l _ a d d r e s s ( ) { $ d a t a = a r r a y ( " k h a a a a a a a a a a a a a a a n ! " , ' h t t p : / / b o b . e x a m p l e . c o m / ' , " s i f i ' d g i v e u i t , s p a m e r ! 1 " , " c o m . e x a m p l e N O S P A M b o b " , " b o b @ y o u r m o m " ) ; f o r e a c h ( $ d a t a a s $ d a t u m ) { $ t h i s - > a s s e r t F a l s e ( i s _ e m a i l ( $ d a t u m ) , $ d a t u m ) ; } }

Slide 33

Slide 33 text

W P _ U N I T T E S T C A S E

Slide 34

Slide 34 text

G O _ T O ( ) f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ l i n k = g e t _ p o s t _ t y p e _ a r c h i v e _ l i n k ( ' m y - p o s t - t y p e ' ) ; $ t h i s - > g o _ t o ( $ l i n k ) ; }

Slide 35

Slide 35 text

A S S E R T W P E R R O R ( ) f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ r e s p o n s e = w p _ u p d a t e _ p o s t ( a r r a y ( ' I D ' = > ' o o p s ' ) , t r u e ) ; $ t h i s - > a s s e r t W P E r r o r ( $ r e s p o n s e ) ; }

Slide 36

Slide 36 text

F A C T O R Y - > P O S T f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ p o s t _ I D _ A = $ t h i s - > f a c t o r y - > p o s t - > c r e a t e ( ) ; $ p o s t _ I D _ B = $ t h i s - > f a c t o r y - > p o s t - > c r e a t e ( a r r a y ( ' p o s t _ t i t l e ' = > ' H e l l o , T o r o n t o ! ' , ' p o s t _ d a t e ' = > ' 2 0 1 4 - 1 1 - 1 6 0 9 : 3 0 : 0 0 ' , ) ) ; }

Slide 37

Slide 37 text

F A C T O R Y - > T E R M f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ t e r m _ I D _ A = $ t h i s - > f a c t o r y - > t e r m - > c r e a t e ( ) ; $ t e r m _ I D _ B = $ t h i s - > f a c t o r y - > t e r m - > c r e a t e ( a r r a y ( ' n a m e ' = > ' T e r m B ' , ' t a x o n o m y ' = > ' c a t e g o r y ' , ) ) ; }

Slide 38

Slide 38 text

F A C T O R Y - > U S E R f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ u s e r _ I D _ A = $ t h i s - > f a c t o r y - > u s e r - > c r e a t e ( ) ; $ u s e r _ I D _ B = $ t h i s - > f a c t o r y - > u s e r - > c r e a t e ( a r r a y ( ' r o l e ' = > ' s u b s c r i b e r ' , ' d i s p l a y _ n a m e ' = > ' A l d o L e o p o l d ' ) ) ; }

Slide 39

Slide 39 text

G E T _ E C H O ( ) f u n c t i o n t e s t _ d e m o n s t r a t i o n s ( ) { $ h a y s t a c k = g e t _ e c h o ( ' t h e _ c o n t e n t ' ) ; $ t h i s - > a s s e r t C o n t a i n s ( ' n e e d l e ' , $ h a y s t a c k ) ; }

Slide 40

Slide 40 text

MORE RESOURCES Curtis McHale: Getting Started With Unit Tests Pippin Williamson: Unit Tests for WordPress Plugins Eric Mann: {12} Needs Unit Tests WPSessions: WordPress Unit Testing Even more at GitHub

Slide 41

Slide 41 text

THANK YOU