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

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

主站蜘蛛池模板: 大姚县| 德安县| 陕西省| 新昌县| 新巴尔虎左旗| 深泽县| 雅江县| 宝清县| 洛浦县| 德江县| 疏附县| 吉木乃县| 陆川县| 手机| 通城县| 琼结县| 亚东县| 察隅县| 安西县| 定襄县| 崇州市| 山丹县| 裕民县| 阿拉善盟| 兴仁县| 微山县| 霍邱县| 沾化县| 确山县| 舞钢市| 新宾| 荔浦县| 贵德县| 青河县| 夏河县| 当雄县| 昆山市| 青州市| 苍南县| 思茅市| 华阴市|