Search code examples
scalatestingconcurrencyspecs2

Specs2 - Unit specification style should not be used in concurrent environments


Specs2 promotes functional style when dealing with Acceptance specification (even Unit specification if we want).

Risks of using old style (mutable style) are mentioned in the spec Specs2 philosophy and concernes potential unwanted side-effects:

The important things to know are:

side-effects are only used to build the specification fragments, by mutating a variable they are also used to short-circuit the execution of an example as soon as there is a failure (by throwing an exception). If you build fragments in the body of examples or execute the same specification concurrently, the sky should fall down. "context" management is to be done with case classes or traits (see org.specs2.examples.MutableSpec)

I don't figure out how a same specification could be run concurrently since each specification is distinct from the other (separated class's instances), even if we run the same twice or more simultaneously.

Indeed, specFragments (mutable variable):

protected[mutable] var specFragments: Fragments = new Fragments()

is declared in a trait called FragmentBuilder, not in an object(in scala sense => singleton) or other shared thing..., so specFragments is a local variable to each Specification's instance.

So what might a scenario be risking concurrency mechanism?

I don't really figure out a true scenario (non-stupid) proving the benefit of Specs2 functional style.


Solution

  • The issues with mutable specification can only be seen when the specification is being built, not when it is executed. When building a mutable specification it's easy to have unexpected side-effect

    import org.specs2._
    
    val spec = new mutable.Specification {
      "example" >> ok
    }
    import spec._
    
    def addTitle {
      // WHOOPS, forgot to remove this line!
      // test, add also an example
      "this is only for testing" >> ok
    
      "new title".title
    }
    addTitle
    

    And the output is:

    new title
    
    + example
    + this is only for testing
    
    Total for specification new title
    Finished in 0 ms
    2 examples, 0 failure, 0 error
    

    So, you're right, the highlighted sentence in the guide ("execute the same specification concurrently") is ambiguous. The construction of the specification itself might be unsafe if several threads were building the same specification object but not if they were running it (the whole process being called "execute" in that sentence).

    Your other question is: what are the benefits of the "functional style"? The main benefit, from a user point of view, is that it is another style of writing specifications where all the text comes first and all the code is put elsewhere.

    In conclusion, do not fear the mutable style of Specification if you like it!