Search code examples
scalaspecs2

Specs2 and @Before/@After-like methods


Given the code like:

class RESTAcceptanceTest extends Specification {

  override def is = anonymous ^ signinOAuth

  def anonymous = "Something"       ^ givenSomething ^
                  "must happen"     ^ mustHappen 
  end

  def signinOAuth = "Signin"                ^ givenSignin ^
                    "works as expected"     ^ userExistsInDatabase 
  end

  // rest of object definitions

}

how do I ensure that same before and after code is executed before/ after "anonymous" and "signinOAuth", and the "after" method should execute even if test is failing itself?


Solution

  • If you're using Given/When/Then steps you can use a Context to control what gets executed before and after each example:

    import org.specs2._
    import specification._
    
    class MySpec extends Specification { def is = 
      "anonymous" ^ 
        "something" ^ something ^
        "must happen" ^ mustHappen ^ endp^
      "OAuth"^ 
        "signing" ^ signing ^
        "works ok" ^ worksOk
    
      lazy val something: Given[Int] = (s: String) => { s.pp; 1 } 
      lazy val mustHappen: Then[Int] = (i: Int) => (s: String)  => 
        context { s.pp; i must_== 1       }
    
      lazy val signing:  Given[Int] = (s: String) => { s.pp; 2 }
      lazy val worksOk: Then[Int] = (i: Int) => (s: String) => 
        context { s.pp; i must_== 2 }
    
      lazy val context = new BeforeAfter {
       def  before = "before".pp
       def after = "after".pp
      }
    }
    

    In the code above the apply method of the context object is used to wrap the code to execute with before and after. Also if you add an error to one of the examples you will see that the "after" code is always executed.

    PS: pp is a utility method like println to display something in the terminal during the execution. The advantage over println is that it returns its argument so you can write 1.pp must_== 1