Search code examples
scalatestingtddbddspecs2

Grouping test cases or "shared_examples_for" equivalent in specs2


I am trying to write a bunch of test codes against a Java class library and I am using specs2 on Scala.

I have a group of test cases that should be ran for all the subclasses of class T, but could not figure out the best way to implement this.

Coming from Ruby, I naturally sought something like *shared_examples_for* macro as in Rspec, but there seems to be no such thing in specs2.

Then I thought, subclassing my own Specification subclass with test cases may be one way to go.

Is there any tidier solution to this?


Solution

  • You can find an example of shared examples in the User Guide. Basically this uses the fact that you can define a method taking a specific instance to test and declare examples for it (see the nonEmptyStack method).

    If this helps let me kickstart you with a quick example using a mutable Specification:

     import org.specs2._
    
     class SubclassesSpec extends mutable.Specification {
       "These examples must pass for all subclasses" >> {
         subclasses foreach { subclass => examples(subclass) }
       }
    
       /** @return instances of subclasses of type T where T is 
        * the supertype of the classes you want to test */
       def subclasses: Seq[T] = ...
    
       /** @return examples parameterized by a specific instance */
       def examples(t: T) = {
         "this is the first example" >> {
           // use t here
         }
         "this is the second example" >> {
           // use t here
         }
       }
     }
    

    The only thing you need to check before you do that is the possible side-effects between examples. In the specification above, all the examples are executed concurrently and they share the same object. If that creates any issue, you can either:

    • add sequential at the top of the specification to avoid concurrency

    • change subclasses and examples to def subclasses: Seq[() => T] and def examples(t: () => T) so that you will create a brand new instance for each example