官术网_书友最值得收藏!

Testing snippets using Specs2

We cannot dilute the importance of testing software. The only way we can guarantee that our software works and will keep working after we have changed, refactored, and applied new features to it, is by testing it.

Getting ready

We'll use the code from the Creating an HTML list using CSS selectors recipe.

How to do it...

  1. Create a file called AnimalsSpec in src/test/scala/code/snippet with the following content:
    import org.specs2.mutable._
    
    class AnimalsSpec extends Specification {
      "Animals list" should {
        "contains 5 animals" in {
          val result = <ul><li><span class="name">Dog</span> - <span class="sname">(Canis lupus familiaris)</span></li><li><span class="name">Cat</span> - <span class="sname">(Felis catus)</span></li><li><span class="name">Giraffe</span> - <span class="sname">(Giraffa camelopardalis)</span></li><li><span class="name">Lion</span> - <span class="sname">(Panthera leo)</span></li><li><span class="name">Horse</span> - <span class="sname">(Equus ferus caballus)</span></li></ul>
    
          val nodeSeq = Animals.list(<ul><li><span class="name"></span> - <span class="sname"></span></li></ul>)
    
          nodeSeq.toString must ==/(result)
        }
      }
    }
  2. Run the test in the SBT session by running the following command:
    ~test
    

    You should see SBT executing the test and printing the result, as displayed in the following screenshot:

How it works...

Specs2 is a framework to create executable specifications. Each specification in Specs2 has the following format:

"Specification description" should
  "example one" in
  "another example" in

The first line defines Fragment, which is a trait defined by the Specs2 framework. What's happening here, is that Specs2 uses the string before the should method as description, and the string just after the opening of the should method as Fragment. The Fragment instance is, in this case, a set of examples that are constructed by the in method. Each block defined by the in method will be a test that will run during the execution of the tests.

An example will have one description, the string before the in method, and a body, which is the block between the curly braces. So, when the test runs, Specs2 executes the code defined in the body of every example and prints the description of the example with a green plus sign in case of success. If the execution fails, Specs2 prints a yellow X followed by the text fail test; it also prints the reason why the test failed. The printing will be different for cases when the example is skipped, pending, or erroneous.

Getting back to our test, we have created a specification for the Animals snippet, which contains one example that invokes the list method of the Animals snippet. The list method takes a NodeSeq object as a parameter and returns another NodeSeq object. Since we know what the output should be, we can compare the output produced by the method invocation with a fragment of HTML code. And that's all that the test is doing.

The result variable is the output we are expecting, and it will be compared with the output produced by the list method, stored in NodeSeq val.

Now that we have both fragments—the expected HTML and the HTML returned by the snippet—we can compare both of them using the DSL defined by the Specs2 framework. To compare both fragments, we invoked the must method, which takes a matcher as its parameter. The matcher is the code before and after the must method. The ==/ matcher compares two XML literals, and in this case, it will compare the values of the NodeSeq and result variables; if the values match, it returns Success.

There's more...

As you can see, testing snippets is just like unit testing any Scala code. And that makes testing snippets quite easy. But sometimes, the snippets might depend on HTTP variables and sessions. For such cases, you can mock an HTTP request using MockWeb or WebSpec.

For example, if you try to test a snippet that uses the S.? method and don't mock an HTTP request, you'll get the following error:

Cause: java.lang.IllegalStateException: Attempted to use resource bundles outside of an initialized S scope. S only usable when initialized

In such cases, you'll need to do something like this:

val expectedResult = MockWeb.testS("/someUrl") {
  // do something that requires having the context of an HTTP request or
  // such as using session variable and returns a value that can be
  // tested.
  1
}

What happens in this case is that the testS method sets up the required context for accessing /somePath as if you accessed the URL via a browser. So, you'll have access to session and request variables, for example.

Since testing snippets is just like unit testing Scala code, you can use any framework you want, such as JUnit, TestNG, and ScalaTest.

See also

主站蜘蛛池模板: 中宁县| 化德县| 宜川县| 綦江县| 饶河县| 萨嘎县| 青州市| 昌平区| 萨迦县| 马鞍山市| 右玉县| 陆河县| 庆元县| 平塘县| 云霄县| 随州市| 乐安县| 闽侯县| 上饶市| 尚志市| 通许县| 衡阳市| 砚山县| 河津市| 如东县| 定安县| 兰州市| 积石山| 乐东| 康保县| 漳平市| 进贤县| 德州市| 文成县| 崇义县| 介休市| 腾冲县| 仙桃市| 乌兰浩特市| 全州县| 武穴市|