Search code examples
scalaintellij-ideaspecs2

Outputting list elements as Examples in Scala Specs2 when using forAll


In this code snippet, SqlTypes.BinaryTypes is a list of (String, Int) tuples.

"process binary types" >> {
  SqlTypes.BinaryTypes.foreach(sqlType => {
    val label = sqlType._1
    val value = sqlType._2

    s"$label" in new ABinaryColumnHandler {
      handler.canProcess(value) should beTrue
    }
  })

  "for all of them" in new ABinaryColumnHandler {
    handler should processTypes(SqlTypes.BinaryTypes)
  }
}

The first part, where the foreach is, creates a new Example for each element of the list, and runs the simple test. The second part calls a custom matcher:

def processTypes(typeList: List[(String, Int)]): Matcher[ColumnHandler] = (handler: ColumnHandler) => {
    forall(typeList) { sqlType =>
      val value = sqlType._2
      handler.canProcess(value) should beTrue
    }
}

The first part won't run without another example defined after it, because the return of that foreach is Unit and not Example or Fragment. I tried the second way because it seems much more straightforward, but I can't get its output to be structured the way I want, which is like this (in IntelliJ, but would look similar in SBT):

output in intellij

What I really want is for Specs2 to output the same in both cases, or be more like

process binary types
   for all of them
      BINARY
      VARBINARY
      LONGBINARY

How can I adjust how the latter example runs to output the way I want?


Solution

  • A block using >> and returning Unit is ambiguous. Do you want to create examples or to create expectations?

    // is it this?
    "several examples" >> {
      Seq(1, 2).foreach { i => s"example $i" >> { 1 must_== 1 } }
    }
    
    // or that?
    "several expectations" >> {
      Seq(1, 2).foreach { i => i must_== i }
    }
    

    In order to resolve the ambiguity you need to use one of those 2 methods:

    • examplesBlock to create examples
    • Result.unit to create expectations

    Like this:

    class TestSpec extends org.specs2.mutable.Specification {
    
      "process binary types" >> examplesBlock {
         List("BINARY", "VARBINARY").foreach { label =>
          s"$label" in new ABinaryColumnHandler {
            Result.unit(Seq(1, 2).foreach(i => i must_== i))
          }
        }
      }
    
      trait ABinaryColumnHandler extends Scope
    }
    

    There is a note about those 2 methods in the User Guide.