SlideShare una empresa de Scribd logo
1 de 69
specs and Scala Tips and tricks for a friendly DSL syntax
Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
About…
About…
About…
     tour
       tour Test Specification specify example example example example example example example example example
       tour importIncredibleStringReverser._ classReverserSpecextends Specification { "a reversed empty string must be empty" in {     reverse("") must_== ""   } "a reversed empty string must really *be empty*" in {     reverse("") must be empty   } "a reversed string must be reversed abc -> cba" in {     reverse("abc") must be_==("cba")   } "a longer string must also be reversed. Whoops!" in {     reverse("abcdef") must be_==("xxxxx")   } }
       tour "a reversed empty string must be empty" in {   reverse("") must be empty }
       tour Specification "ReverserSpec" + a reversed empty string must be empty   + a reversed empty string must really *be empty*   + a reversed string must be reversed abc -> cba x a longer string must also be reversed. Whoops!     'fedcba' is not equal to 'xxxxx' (ReverserSpec.scala:17) Total for specification "ReverserSpec": Finished in 0 second, 140 ms 4 examples, 4 expectations, 1 failure, 0 error
       tour repetition repetition repetition repetition repetition repetition organize System Under Specification
       tour class Reverser2Spec extends Specification { "a reversed empty string" should {     val reversed = reverse("")   "be empty" in {       reversed must_== ""     } "really *be empty*" in {       reversed must be empty     }   } "a reversed non-empty string" should {     val reversed = reverse("abc")   "be reversed abc -> cba" in {       reversed must be_==("cba")     } "have the same size as the original string" in {       reversed must have size(3)     }   } }
       tour "a reversed empty string" should {   val reversed = reverse("")     … } "a reversed non-empty string" should {   val reversed = reverse("abc")     … }
       tour
       tour Be specific Matchers
       tour traitHelloWorldSnippet { def hello(s: String)=            <div class="txt">Hello {s}</div> } "the snippet must output a div element" >> {   hello("Eric") must (<div/>) } "it must have an attribute class=txt" >> {   hello("You") must (<div/>, "class" -> "txt") }
       tour   hello("Eric") must (<div/>)
       tour Be exhaustive Properties
       tour class Reverser3Spec extends Specification withScalaCheck {   "reverse must preserve the length of a string" verifies {      s: String => reverse(s).size == s.size   } "reverse applied twice must return the same string" verifies {        s: String => reverse(reverse(s)) == s    }   "reverse 2 concatenated strings must return the reversed second     string concatenated with the reversed first one" verifies {     (s1: String, s2: String) => reverse(s1 + s2) ==                                  reverse(s2) + reverse(s1)    } defcenter(s: String) = s(s.size / 2)   "keep the same 'center' character - Whoops!" verifies {      s: String => s.isEmpty || center(reverse(s)) == center(s)    } }
       tour   "reverse applied twice must return " +   "the same string" verifies {        s: String => reverse(reverse(s)) == s    }
       tour x keep the same 'center' character - Whoops!   A counter-example is 'bc'    (after 1 try – shrinked ('bcab' -> 'bc'))
       tour Isolate Mocks
       tour /**  * A simple Observable-Observer implementation  */ trait Observable { privatevar observers: List[Observer] = Nil def add(o: Observer) =              observers = o :: observers def changed(event: String) =       observers foreach (_.notify(event)) } trait Observer { def notify(event: String) }
       tour classObservableSpecextends Specification withMockito { val observer = mock[Observer] val observable = new Observable { add(observer) } "An observable notifies its observers if changed" >> { observable.changed("event")     there was one(observer).notify("event")   } "Each change event is notified" >> { observable.changed("event1") observable.changed("event2")     there was two(observer).notify(startWith("event"))   } }
       tour "An observable notifies its observers if " + "changed" >> { observable.changed("event")   there was one(observer).notify("event") }
     DSL How does it work?
     DSL The  best tool in the box "This is ok" in {   1 + 1 } // is the same as "This is ok".in(1 + 1) "In"method  on String ?!
     DSL The  best tool in the box class Example(description: String) {   def in(e: Any) = e } implicitdefforExample(d: String) = {   new Example(d) }
     DSL Naming forExample("this works") in {   1 + 1 }
     DSL Some examples "This is true" in {    true must beTrue } 3.seconds 3 seconds 3 times { i => println(i) }
Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
     DSL Restrict
     DSL Restrict class Example(description: String) {   def in(e: Any) = expectations   def tag(t: String) = this }
     DSL Restrict  "this is a" tag ("really?")
     DSL Restrict classExampleDesc(description: String) {   def in(e: Any): Example = new     Example(description, e)  } } class Example(d: String, e: Any) {   def tag(t: String): Example = this }
     DSL Combine
     DSL Combine trait Matcher[-T] { def apply(y: =>T): (Boolean, String, String) def not: Matcher[T] def when(condition: =>Boolean): Matcher[T] def unless(condition: =>Boolean): Matcher[T] deforSkip: Matcher[T] def or[S <: T](m: Matcher[S]): Matcher[S] defxor[S <: T](m: Matcher[S]): Matcher[S] def and[S <: T](m: Matcher[S]): Matcher[S] def ^^[S<: T, U](f: S => U): Matcher[U] deftoIterable: Matcher[Iterable[T]] }
     DSL Some examples def beFalse = beTrue.not condition must beTrue or beFalse condition must beTrue.unless(condition2) def trimmedSize(i: Int) = size(i) ^^ (_.trim) string must have trimmedSize(3)
     DSL Add, add, add
     DSL Repeated parameters include(spec1) include(spec1, spec2) 1 must beOneOf(1, 2, 3)
     DSL Use and pass  result + 1    // result = ?  result.pp + 1 // print and pass
     DSL Use and pass Customers.findBy(_.age >= 18)    aka "adult customers"   must haveSize(3) > adult customers 'Bob, Lee'      doesn't have size 3
     DSL this.type classBigSpecextends Spec { // I want to "tag" the    // slow spec as slow   include(slowSpec, fastSpec)   }
     DSL this.type classBigSpecextends Spec {   include(slow tag "slow", fast)   }
     DSL this.type class Spec extends Tagged {   def include(other: Spec*) = … } trait Tagged {   def tag(t: String): ? }
     DSL this.type // store the tag and return this def tag(t: String): this.type = this
     DSL Configuration val prop = forAll { (s: String) =>    reverse(reverse(s)) == s  }  "With the default configuration" in {   prop must pass }
     DSL Configuration "With a 3 tests ok" in {   prop must pass(set(minTestsOk -> 3)) } "With 3 tests ok – in the console" in {   prop must pass(display(minTestsOk -> 3)) }
     DSL Implicit  parameters def pass(implicit p: Params) = {   new Matcher[Prop] { def apply(prop: =>Prop) = check(prop)(p)  } } implicitvaldefaultParams = newParams
     DSL Belazy
     DSL Be lazy "This should not explode" in {   error("boom") }
     DSL Be lazy classExampleDesc(d: String) {   def in(e: =>Any) =      new Example(description, e) } class Example(d: String, e: =>Any)
     DSL Be lazy   def in(e: =>Any) = …
     DSL By name  parameters   Evaluate once! classEqualMatcher[T](x: =>T) extends Matcher[T] {  def apply(y: =>T) = { val (a, b) = (x, y)     (a == b, a + " is equal to " + b,               a + " is not equal to " + b)   } }
     DSL By name  parameters   With varargs? // not legal!!  def method[T](params: =>T*)  method(1., 2., math.pow(100, 100))
     DSL By name  parameters   With varargs! implicitdef lazyfy[T](value: =>T) =       new LazyParameter(() => value) class LazyParameter[T](value: () => T) { lazyval v = value() def get() = v }
     DSL By name  parameters   With varargs! def method[T](params: LazyParameter[T]*)
Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
     DSL Operators classExampleDesc(d: String) {   def >>(e: =>Any) = new Example(d, e) } "When I setup the system" >> {   "And a customer is entered" >> { "if he has a discount" >> {} "if he doesn't have a discount" >> {}   } }
     DSL Operators // contexts  "A full stack" ->-(fullStack) should { … } // matchers   xml must (<node/>) // repl matcher  > "This is the expected result"
     DSL DataTables /**  * Fit-like table in Scala?  *   *  | a | b | c |  *  | 1 | 2 | 3 |  *  | 2 | 2 | 4 |  *  */    Use ‘!‘  to separate cells and ‘|‘  to separate rows
     DSL DataTables classDataTablesSpecextends Specification with DataTables { "lots of examples" >> { "a" | "b" | "a + b" |      1  !  2  !    3    |      2  !  2  !    4    |      2  !  3  !    4    |> { (a, b, c) =>        a + b must_== c     }   } }
     DSL DataTables // the ‘play’ operator |>  2  !  3  !  4   |> { (a, b, c) =>
     DSL Class manifests  // How to avoid   // throwA(classOf[FailureException])  (1 must_== 2) must          throwA[FailureException]
     DSL Class manifests importscala.reflect._ defthrowA[T](implicit m: ClassManifest[T]) =    new Matcher[Any] {   // use m.erasure }
     DSL Make a guess "When I setup the system" >> {   "And a customer is entered" >> { "if he has a discount" >> {} "if he doesn't have a discount" >> {}   } } ,[object Object],[object Object]
Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
     DSL http://code.google.com/p/specs http://etorreborre.blogspot.com/oscon-2010 Scala 2.8.0  inside !
Oscon 2010 Specs talk

Más contenido relacionado

La actualidad más candente

Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objectsHusain Dalal
 
Parsing with Perl6 Grammars
Parsing with Perl6 GrammarsParsing with Perl6 Grammars
Parsing with Perl6 Grammarsabrummett
 
Akka Typed — between Session Types and the Actor Model
Akka Typed — between Session Types and the Actor ModelAkka Typed — between Session Types and the Actor Model
Akka Typed — between Session Types and the Actor ModelRoland Kuhn
 
Project Gålbma – Actors vs Types
Project Gålbma – Actors vs TypesProject Gålbma – Actors vs Types
Project Gålbma – Actors vs TypesRoland Kuhn
 
Chapter 8- Advanced Views and URLconfs
Chapter 8- Advanced Views and URLconfsChapter 8- Advanced Views and URLconfs
Chapter 8- Advanced Views and URLconfsVincent Chien
 
The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185Mahmoud Samir Fayed
 
bullismo e scuola primaria
bullismo e scuola primariabullismo e scuola primaria
bullismo e scuola primariaimartini
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskAlexander Granin
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptLoïc Knuchel
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Philip Schwarz
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)ujihisa
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTsKevlin Henney
 

La actualidad más candente (20)

Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
Idiomatic kotlin
Idiomatic kotlinIdiomatic kotlin
Idiomatic kotlin
 
Parsing with Perl6 Grammars
Parsing with Perl6 GrammarsParsing with Perl6 Grammars
Parsing with Perl6 Grammars
 
Groovy
GroovyGroovy
Groovy
 
Akka Typed — between Session Types and the Actor Model
Akka Typed — between Session Types and the Actor ModelAkka Typed — between Session Types and the Actor Model
Akka Typed — between Session Types and the Actor Model
 
Project Gålbma – Actors vs Types
Project Gålbma – Actors vs TypesProject Gålbma – Actors vs Types
Project Gålbma – Actors vs Types
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
Chapter 8- Advanced Views and URLconfs
Chapter 8- Advanced Views and URLconfsChapter 8- Advanced Views and URLconfs
Chapter 8- Advanced Views and URLconfs
 
The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185The Ring programming language version 1.5.4 book - Part 34 of 185
The Ring programming language version 1.5.4 book - Part 34 of 185
 
Go testdeep
Go testdeepGo testdeep
Go testdeep
 
C++ 11 usage experience
C++ 11 usage experienceC++ 11 usage experience
C++ 11 usage experience
 
bullismo e scuola primaria
bullismo e scuola primariabullismo e scuola primaria
bullismo e scuola primaria
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Voce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu CodigoVoce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu Codigo
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)
 
3 u-mpb2u2na
 3 u-mpb2u2na 3 u-mpb2u2na
3 u-mpb2u2na
 
What are arrays in java script
What are arrays in java scriptWhat are arrays in java script
What are arrays in java script
 
Programming with GUTs
Programming with GUTsProgramming with GUTs
Programming with GUTs
 

Destacado (7)

Specs2 3.4
Specs2 3.4Specs2 3.4
Specs2 3.4
 
Cape workshop runaway bay
Cape workshop runaway bayCape workshop runaway bay
Cape workshop runaway bay
 
Cpl final v5
Cpl final v5Cpl final v5
Cpl final v5
 
Momentos Inolvidables
Momentos InolvidablesMomentos Inolvidables
Momentos Inolvidables
 
RELOJES
RELOJESRELOJES
RELOJES
 
Scala days2013 proxyfactorybeandelegate
Scala days2013 proxyfactorybeandelegate Scala days2013 proxyfactorybeandelegate
Scala days2013 proxyfactorybeandelegate
 
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job? Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
 

Similar a Oscon 2010 Specs talk

Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In ScalaSkills Matter
 
Scala 3camp 2011
Scala   3camp 2011Scala   3camp 2011
Scala 3camp 2011Scalac
 
My First Rails Plugin - Usertext
My First Rails Plugin - UsertextMy First Rails Plugin - Usertext
My First Rails Plugin - Usertextfrankieroberto
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Pragmatic Real-World Scala
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scalaparag978978
 
Introducere In Java Jx
Introducere In Java JxIntroducere In Java Jx
Introducere In Java Jxdanielnastase
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0Yaser Zhian
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009David Pollak
 
Falcon初印象
Falcon初印象Falcon初印象
Falcon初印象勇浩 赖
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Peter Maas
 
JSUG - Scala Lightning Talk by Michael Greifeneder
JSUG - Scala Lightning Talk by Michael GreifenederJSUG - Scala Lightning Talk by Michael Greifeneder
JSUG - Scala Lightning Talk by Michael GreifenederChristoph Pickl
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick touraztack
 

Similar a Oscon 2010 Specs talk (20)

Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Scala en
Scala enScala en
Scala en
 
Rewriting Java In Scala
Rewriting Java In ScalaRewriting Java In Scala
Rewriting Java In Scala
 
Prototype js
Prototype jsPrototype js
Prototype js
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Scala 3camp 2011
Scala   3camp 2011Scala   3camp 2011
Scala 3camp 2011
 
My First Rails Plugin - Usertext
My First Rails Plugin - UsertextMy First Rails Plugin - Usertext
My First Rails Plugin - Usertext
 
Antlr V3
Antlr V3Antlr V3
Antlr V3
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Pragmatic Real-World Scala
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scala
 
Introducere In Java Jx
Introducere In Java JxIntroducere In Java Jx
Introducere In Java Jx
 
C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0C++11 - A Change in Style - v2.0
C++11 - A Change in Style - v2.0
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
 
Falcon初印象
Falcon初印象Falcon初印象
Falcon初印象
 
LEX & YACC TOOL
LEX & YACC TOOLLEX & YACC TOOL
LEX & YACC TOOL
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3
 
JSUG - Scala Lightning Talk by Michael Greifeneder
JSUG - Scala Lightning Talk by Michael GreifenederJSUG - Scala Lightning Talk by Michael Greifeneder
JSUG - Scala Lightning Talk by Michael Greifeneder
 
C++ programming
C++ programmingC++ programming
C++ programming
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
 
C to perl binding
C to perl bindingC to perl binding
C to perl binding
 

Más de Eric Torreborre

wire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfwire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfEric Torreborre
 
The many faces of modularity
The many faces of modularityThe many faces of modularity
The many faces of modularityEric Torreborre
 
What haskell taught us when we were not looking
What haskell taught us when we were not lookingWhat haskell taught us when we were not looking
What haskell taught us when we were not lookingEric Torreborre
 
Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Eric Torreborre
 
Pratical eff-functional-conf
Pratical eff-functional-confPratical eff-functional-conf
Pratical eff-functional-confEric Torreborre
 
Specs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenSpecs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenEric Torreborre
 
Streaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyStreaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyEric Torreborre
 
Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Eric Torreborre
 
Pratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoPratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoEric Torreborre
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allEric Torreborre
 
Data generation, the hard parts
Data generation, the hard partsData generation, the hard parts
Data generation, the hard partsEric Torreborre
 
Origami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaOrigami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaEric Torreborre
 
Datatypes for the real world
Datatypes for the real worldDatatypes for the real world
Datatypes for the real worldEric Torreborre
 
Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Eric Torreborre
 
Epic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEpic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEric Torreborre
 

Más de Eric Torreborre (20)

wire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdfwire-all-the-things-lambda-days-2023.pdf
wire-all-the-things-lambda-days-2023.pdf
 
The many faces of modularity
The many faces of modularityThe many faces of modularity
The many faces of modularity
 
What haskell taught us when we were not looking
What haskell taught us when we were not lookingWhat haskell taught us when we were not looking
What haskell taught us when we were not looking
 
Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)Wire once, rewire twice! (Haskell exchange-2018)
Wire once, rewire twice! (Haskell exchange-2018)
 
Pratical eff-functional-conf
Pratical eff-functional-confPratical eff-functional-conf
Pratical eff-functional-conf
 
Specs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchenSpecs2, from starters to dessert and... a look in the kitchen
Specs2, from starters to dessert and... a look in the kitchen
 
Streaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogyStreaming, effects and beautiful folds: a winning trilogy
Streaming, effects and beautiful folds: a winning trilogy
 
Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017Pratical eff-scalaitaly-2017
Pratical eff-scalaitaly-2017
 
Pratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays ChicagoPratical eff monad at Scaladays Chicago
Pratical eff monad at Scaladays Chicago
 
Pratical eff
Pratical effPratical eff
Pratical eff
 
The Eff monad, one monad to rule them all
The Eff monad, one monad to rule them allThe Eff monad, one monad to rule them all
The Eff monad, one monad to rule them all
 
Easy di-slideshare
Easy di-slideshareEasy di-slideshare
Easy di-slideshare
 
Data generation, the hard parts
Data generation, the hard partsData generation, the hard parts
Data generation, the hard parts
 
Origami, a monadic fold library for Scala
Origami, a monadic fold library for ScalaOrigami, a monadic fold library for Scala
Origami, a monadic fold library for Scala
 
Datatypes for the real world
Datatypes for the real worldDatatypes for the real world
Datatypes for the real world
 
DSLs with fold algebras
DSLs with fold algebrasDSLs with fold algebras
DSLs with fold algebras
 
Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014Specs2 whirlwind tour at Scaladays 2014
Specs2 whirlwind tour at Scaladays 2014
 
Epic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FPEpic success \/ failure, refactoring to *real* FP
Epic success \/ failure, refactoring to *real* FP
 
Vampire methods
Vampire methodsVampire methods
Vampire methods
 
Specs2 whirlwind-tour
Specs2 whirlwind-tourSpecs2 whirlwind-tour
Specs2 whirlwind-tour
 

Oscon 2010 Specs talk

  • 1. specs and Scala Tips and tricks for a friendly DSL syntax
  • 2. Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
  • 6. tour
  • 7. tour Test Specification specify example example example example example example example example example
  • 8. tour importIncredibleStringReverser._ classReverserSpecextends Specification { "a reversed empty string must be empty" in { reverse("") must_== "" } "a reversed empty string must really *be empty*" in { reverse("") must be empty } "a reversed string must be reversed abc -> cba" in { reverse("abc") must be_==("cba") } "a longer string must also be reversed. Whoops!" in { reverse("abcdef") must be_==("xxxxx") } }
  • 9. tour "a reversed empty string must be empty" in { reverse("") must be empty }
  • 10. tour Specification "ReverserSpec" + a reversed empty string must be empty + a reversed empty string must really *be empty* + a reversed string must be reversed abc -> cba x a longer string must also be reversed. Whoops! 'fedcba' is not equal to 'xxxxx' (ReverserSpec.scala:17) Total for specification "ReverserSpec": Finished in 0 second, 140 ms 4 examples, 4 expectations, 1 failure, 0 error
  • 11. tour repetition repetition repetition repetition repetition repetition organize System Under Specification
  • 12. tour class Reverser2Spec extends Specification { "a reversed empty string" should { val reversed = reverse("") "be empty" in { reversed must_== "" } "really *be empty*" in { reversed must be empty } } "a reversed non-empty string" should { val reversed = reverse("abc") "be reversed abc -> cba" in { reversed must be_==("cba") } "have the same size as the original string" in { reversed must have size(3) } } }
  • 13. tour "a reversed empty string" should { val reversed = reverse("") … } "a reversed non-empty string" should { val reversed = reverse("abc") … }
  • 14. tour
  • 15. tour Be specific Matchers
  • 16. tour traitHelloWorldSnippet { def hello(s: String)= <div class="txt">Hello {s}</div> } "the snippet must output a div element" >> { hello("Eric") must (<div/>) } "it must have an attribute class=txt" >> { hello("You") must (<div/>, "class" -> "txt") }
  • 17. tour hello("Eric") must (<div/>)
  • 18. tour Be exhaustive Properties
  • 19. tour class Reverser3Spec extends Specification withScalaCheck { "reverse must preserve the length of a string" verifies { s: String => reverse(s).size == s.size } "reverse applied twice must return the same string" verifies { s: String => reverse(reverse(s)) == s } "reverse 2 concatenated strings must return the reversed second string concatenated with the reversed first one" verifies { (s1: String, s2: String) => reverse(s1 + s2) == reverse(s2) + reverse(s1) } defcenter(s: String) = s(s.size / 2) "keep the same 'center' character - Whoops!" verifies { s: String => s.isEmpty || center(reverse(s)) == center(s) } }
  • 20. tour "reverse applied twice must return " + "the same string" verifies { s: String => reverse(reverse(s)) == s }
  • 21. tour x keep the same 'center' character - Whoops! A counter-example is 'bc' (after 1 try – shrinked ('bcab' -> 'bc'))
  • 22. tour Isolate Mocks
  • 23. tour /** * A simple Observable-Observer implementation */ trait Observable { privatevar observers: List[Observer] = Nil def add(o: Observer) = observers = o :: observers def changed(event: String) = observers foreach (_.notify(event)) } trait Observer { def notify(event: String) }
  • 24. tour classObservableSpecextends Specification withMockito { val observer = mock[Observer] val observable = new Observable { add(observer) } "An observable notifies its observers if changed" >> { observable.changed("event") there was one(observer).notify("event") } "Each change event is notified" >> { observable.changed("event1") observable.changed("event2") there was two(observer).notify(startWith("event")) } }
  • 25. tour "An observable notifies its observers if " + "changed" >> { observable.changed("event") there was one(observer).notify("event") }
  • 26. DSL How does it work?
  • 27. DSL The best tool in the box "This is ok" in { 1 + 1 } // is the same as "This is ok".in(1 + 1) "In"method on String ?!
  • 28. DSL The best tool in the box class Example(description: String) { def in(e: Any) = e } implicitdefforExample(d: String) = { new Example(d) }
  • 29. DSL Naming forExample("this works") in { 1 + 1 }
  • 30. DSL Some examples "This is true" in { true must beTrue } 3.seconds 3 seconds 3 times { i => println(i) }
  • 31. Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
  • 32. DSL Restrict
  • 33. DSL Restrict class Example(description: String) { def in(e: Any) = expectations def tag(t: String) = this }
  • 34. DSL Restrict "this is a" tag ("really?")
  • 35. DSL Restrict classExampleDesc(description: String) { def in(e: Any): Example = new Example(description, e) } } class Example(d: String, e: Any) { def tag(t: String): Example = this }
  • 36. DSL Combine
  • 37. DSL Combine trait Matcher[-T] { def apply(y: =>T): (Boolean, String, String) def not: Matcher[T] def when(condition: =>Boolean): Matcher[T] def unless(condition: =>Boolean): Matcher[T] deforSkip: Matcher[T] def or[S <: T](m: Matcher[S]): Matcher[S] defxor[S <: T](m: Matcher[S]): Matcher[S] def and[S <: T](m: Matcher[S]): Matcher[S] def ^^[S<: T, U](f: S => U): Matcher[U] deftoIterable: Matcher[Iterable[T]] }
  • 38. DSL Some examples def beFalse = beTrue.not condition must beTrue or beFalse condition must beTrue.unless(condition2) def trimmedSize(i: Int) = size(i) ^^ (_.trim) string must have trimmedSize(3)
  • 39. DSL Add, add, add
  • 40. DSL Repeated parameters include(spec1) include(spec1, spec2) 1 must beOneOf(1, 2, 3)
  • 41. DSL Use and pass result + 1 // result = ? result.pp + 1 // print and pass
  • 42. DSL Use and pass Customers.findBy(_.age >= 18) aka "adult customers" must haveSize(3) > adult customers 'Bob, Lee' doesn't have size 3
  • 43. DSL this.type classBigSpecextends Spec { // I want to "tag" the // slow spec as slow include(slowSpec, fastSpec) }
  • 44. DSL this.type classBigSpecextends Spec { include(slow tag "slow", fast) }
  • 45. DSL this.type class Spec extends Tagged { def include(other: Spec*) = … } trait Tagged { def tag(t: String): ? }
  • 46. DSL this.type // store the tag and return this def tag(t: String): this.type = this
  • 47. DSL Configuration val prop = forAll { (s: String) => reverse(reverse(s)) == s } "With the default configuration" in { prop must pass }
  • 48. DSL Configuration "With a 3 tests ok" in { prop must pass(set(minTestsOk -> 3)) } "With 3 tests ok – in the console" in { prop must pass(display(minTestsOk -> 3)) }
  • 49. DSL Implicit parameters def pass(implicit p: Params) = { new Matcher[Prop] { def apply(prop: =>Prop) = check(prop)(p) } } implicitvaldefaultParams = newParams
  • 50. DSL Belazy
  • 51. DSL Be lazy "This should not explode" in { error("boom") }
  • 52. DSL Be lazy classExampleDesc(d: String) { def in(e: =>Any) = new Example(description, e) } class Example(d: String, e: =>Any)
  • 53. DSL Be lazy def in(e: =>Any) = …
  • 54. DSL By name parameters  Evaluate once! classEqualMatcher[T](x: =>T) extends Matcher[T] { def apply(y: =>T) = { val (a, b) = (x, y) (a == b, a + " is equal to " + b, a + " is not equal to " + b) } }
  • 55. DSL By name parameters  With varargs? // not legal!! def method[T](params: =>T*) method(1., 2., math.pow(100, 100))
  • 56. DSL By name parameters  With varargs! implicitdef lazyfy[T](value: =>T) = new LazyParameter(() => value) class LazyParameter[T](value: () => T) { lazyval v = value() def get() = v }
  • 57. DSL By name parameters  With varargs! def method[T](params: LazyParameter[T]*)
  • 58. Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
  • 59. DSL Operators classExampleDesc(d: String) { def >>(e: =>Any) = new Example(d, e) } "When I setup the system" >> { "And a customer is entered" >> { "if he has a discount" >> {} "if he doesn't have a discount" >> {} } }
  • 60. DSL Operators // contexts "A full stack" ->-(fullStack) should { … } // matchers xml must (<node/>) // repl matcher > "This is the expected result"
  • 61. DSL DataTables /** * Fit-like table in Scala? * * | a | b | c | * | 1 | 2 | 3 | * | 2 | 2 | 4 | * */ Use ‘!‘ to separate cells and ‘|‘ to separate rows
  • 62. DSL DataTables classDataTablesSpecextends Specification with DataTables { "lots of examples" >> { "a" | "b" | "a + b" | 1 ! 2 ! 3 | 2 ! 2 ! 4 | 2 ! 3 ! 4 |> { (a, b, c) => a + b must_== c } } }
  • 63. DSL DataTables // the ‘play’ operator |> 2 ! 3 ! 4 |> { (a, b, c) =>
  • 64. DSL Class manifests // How to avoid // throwA(classOf[FailureException]) (1 must_== 2) must throwA[FailureException]
  • 65. DSL Class manifests importscala.reflect._ defthrowA[T](implicit m: ClassManifest[T]) = new Matcher[Any] { // use m.erasure }
  • 66.
  • 67. Tuesday, July 27, 2010 About… specs tour Implicit def Restrict Combine Add , add Be lazy !&%$#> Manifests Resources
  • 68. DSL http://code.google.com/p/specs http://etorreborre.blogspot.com/oscon-2010 Scala 2.8.0 inside !