1

I am new in Specs2. I read the specs2 documentation but it's kinda confusing. I don't know if it's possible or not.

So I have Specs2 test code roughly like this:

"DataServiceTest" should {
  "InsertNewData" in {
    val name = "some name here"
    val description = "some description here"

    // Assumed DataService.insertNewData method execute the insertion
    // and returns "Data" model.
    Data data = DataService.insertNewData(name, description)

    // Checking of equality here
    data.name === name
    data.description === description

    // Assumed the "Data" model has List[SubData] property "subData"
    // and the code below is checking the List[SubData]
    data.subData.foreach {
        ...
    }

    success
  }
}

1. Is there a way to give message for these parts?

data.name === name
data.description === description

Something like "Checking data's name" in { data.name === name }. So the message will be shown on the output screen when the test is executed whether it's success or failed.

2. Is there a way to group the sub-code inside the "InsertNewData" by giving a text message like this:

"DataServiceTest" should {
  "InsertNewData" in {
    val name = "some name here"
    val description = "some description here"

    // Assumed DataService.insertNewData method execute the insertion
    // and returns "Data" model.
    Data data = DataService.insertNewData(name, description)

    "Checking basic properties of Data" in {
        // Checking of equality here
        data.name === name
        data.description === description
    }

    "Checking subData" in {
        // Assumed the "Data" model has List[SubData] property "subData"
        // and the code below is checking the subData

        data.subData must have size(3)

        data.subData.foreach {
            ...
        }

    }
    success
  }
}

UPDATE:

Based on one of answer here, I tried this:

"Checking of equality" ! e1

def e1 = {
        data.name === name
        data.description === description
        failure
}

It didn't work as it should fail. But the test result is all passed.

UPDATE #2:

I did some experiment of nested in block:

"DataServiceTest" should {
    "my test" in {

      "hello test" in {    // this block is not executed
        "hello" !== "hello"
        success
      }

      "world" === "world"
      success
    }
}

The result is success, but it should fail because of "hello" !== "hello". Looking from console screen, the is no "hello test" message, so it seems nested in block doesn't get executed.

UPDATE #3:

Based on edited answer by eric, I edited the code in Update #2:

"DataServiceTest" >> {
    "my test" >> {

        "hello test" >> {    // this block is not executed
            "hello" !== "hello"
            success
        }

        "world" === "world"
        success
    }
}

Same result, the "hello test" nested block didn't get executed.

null
  • 8,669
  • 16
  • 68
  • 98

3 Answers3

0

You might find the Specs2 guides helpful: https://etorreborre.github.io/specs2/guide/org.specs2.guide.Structure.html#Expectations

Look for "Expectations" in the guide.

Pradyumna
  • 1,583
  • 4
  • 19
  • 34
0
  1. Spec2 will just show that your tests will pass if the conditions are met. No message will be generated and usually this is sufficient. If your testsuite becomes large enough, then the positive messages will become numerous. You are more interested in failures anyways.

Spec2 does generate clear message by default and will use the variable name, the actual value and what it is supposed to be in general. But if that is not good enough, you can set a custom message. How this can be done can be seen in this stackoverflow answer

If you still want to generate the messages, you can use print statement and loggers. But I would advise you against it.

  1. I would refactor to two different tests:
"DataServiceTest"
should {
  "InsertNewData should have correct basic properties" in {
    // Arrange 
    val name = "some name here"
    val description = "some description here"

    // Act
    // Assumed DataService.insertNewData method execute the insertion
    // and returns "Data" model.
    Data data = DataService.insertNewData(name, description)

    // Assert
    // Checking of equality here
    data.name === name
    data.description === description
  }

  "InsertNewData should have correct subData" in {
    // Arrange 
    val name = "some name here"
    val description = "some description here"

    // Act
    // Assumed DataService.insertNewData method execute the insertion
    // and returns "Data" model.
    Data data = DataService.insertNewData(name, description)

    // Assert
    // Assumed the "Data" model has List[SubData] property "subData"
    // and the code below is checking the 
    data.subData must have size(3)

    data.subData.foreach {
      ...
    }
  }
}
Community
  • 1
  • 1
snorberhuis
  • 3,108
  • 2
  • 22
  • 29
  • In this case, where should I put the `Data data = DataService.insertNewData(name, description)` code? – null Jan 12 '15 at 12:06
  • I updated the example with explicit setting up the test following Arrange, Act, Assert pattern: http://c2.com/cgi/wiki?ArrangeActAssert – snorberhuis Jan 12 '15 at 12:23
  • Some of codes like `Data data = DataService.insertNewData(name, description)` are redundant or duplicated in your example. – null Jan 21 '15 at 14:00
0

An easy way to create small examples based on one "ACT" call is to use a lazy val like this:

"DataServiceTest should" >> {
  "InsertNewData" >> {
    val name = "some name here"
    val description = "some description here"

    // Assumed DataService.insertNewData method execute the insertion
    // and returns "Data" model.
    lazy val data = DataService.insertNewData(name, description)

    "name must be ok" >> {
      data.name === name
    }
    "description must be ok" >> {
      data.description === description
    }

    "subdata must be ok" >> {
       data.subData.foreach {
       ...
       }
       success
    }
 }
Eric
  • 15,494
  • 38
  • 61
  • Hi, is the "name must be ok", "description must be ok", and "subdata must be ok" blocks are inside "InsertNewData" block? Because nested `in` block doesn't work, see **UPDATE #2** in my question. – null Jan 13 '15 at 13:47
  • I edited my answer. Instead of using nested "in" blocks you can use the `>>` operator. – Eric Jan 15 '15 at 17:12
  • Update #3 is not exactly what I have written above. In Update #3, you have a block of code which is an example because it ends with an expectation. In the middle of the example you create another one which doesn't get executed because there is a separation between design time and execution time in specs2. – Eric Jan 18 '15 at 04:11
  • I don't really get it. Could you modify the code in example #3 so it works? – null Jan 18 '15 at 08:26
  • What is missing in my solution above? – Eric Jan 18 '15 at 20:04
  • Ok, I think I get it now, since I put the `success` in the `"my test"` block so the block is considered as test block, and then the nested `"hello test"` block is not considered anymore as test block. Btw, what is the difference between `in` and `>>` ? – null Jan 21 '15 at 13:58
  • 1
    There is no real difference. `>>` can be used when reading `in` makes no sense. Same thing for `should`. You could go by always using `>>` and adding `should` (or `can`, or `must`, or ...) or `in` in your descriptions only when they make sense. – Eric Jan 22 '15 at 00:18