注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

阿弥陀佛

街树飘影未见尘 潭月潜水了无声 般若观照心空静...

 
 
 

日志

 
 
关于我

一直从事气象预报、服务建模实践应用。 注重气象物理场、实况场、地理信息、本体知识库、分布式气象内容管理系统建立。 对Barnes客观分析, 小波,计算神经网络、信任传播、贝叶斯推理、专家系统、网络本体语言有一定体会。 一直使用Java、Delphi、Prolog、SQL编程。

网易考拉推荐
GACHA精选

ScalaTest User Guide8  

2014-07-04 23:34:26|  分类: Scala |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
ScalaTest User Guide

Getting started

Selecting testing styles

Defining base classes

Writing your first test

Using assertions

Tagging your tests

Running your tests

Sharing fixtures

Sharing tests

Using matchers

Testing with mock objects

Property-based testing

Using Selenium

Other goodies

Philosophy and design

Migrating to 2.0

Sharing tests

Sometimes you may want to run the same test code on different fixture objects. In other words, you may want to write tests that are "shared" by different fixture objects. To accomplish this in a FlatSpec, you first place shared tests in behavior functions. These behavior functions will be invoked during the construction phase of any FlatSpec that uses them, so that the tests they contain will be registered as tests in that FlatSpec. For example, given this stack class:

import scala.collection.mutable.ListBuffer

class Stack[T] {
val MAX = 10 private val buf = new ListBuffer[T]
def push(o: T) { if (!full) buf.prepend(o) else throw new IllegalStateException("can't push onto a full stack") }
def pop(): T = { if (!empty) buf.remove(0) else throw new IllegalStateException("can't pop an empty stack") }
def peek: T = { if (!empty) buf(0) else throw new IllegalStateException("can't pop an empty stack") }
def full: Boolean = buf.size == MAX def empty: Boolean = buf.size == 0 def size = buf.size
override def toString = buf.mkString("Stack(", ", ", ")") }

You may want to test the Stack class in different states: empty, full, with one item, with one item less than capacity, etc. You may find you have several tests that make sense any time the stack is non-empty. Thus you'd ideally want to run those same tests for three stack fixture objects: a full stack, a stack with a one item, and a stack with one item less than capacity. With shared tests, you can factor these tests out into a behavior function, into which you pass the stack fixture to use when running the tests. So in your FlatSpec for stack, you'd invoke the behavior function three times, passing in each of the three stack fixtures so that the shared tests are run for all three fixtures. You can define a behavior function that encapsulates these shared tests inside the FlatSpec that uses them. If they are shared between different FlatSpecs, however, you could also define them in a separate trait that is mixed into each FlatSpec that uses them.

For example, here the nonEmptyStack behavior function (in this case, a behavior method) is defined in a trait along with another method containing shared tests for non-full stacks:

trait StackBehaviors { this: FlatSpec =>

def nonEmptyStack(newStack: => Stack[Int], lastItemAdded: Int) {
it should "be non-empty" in { assert(!newStack.empty) }
it should "return the top item on peek" in { assert(newStack.peek === lastItemAdded) }
it should "not remove the top item on peek" in { val stack = newStack val size = stack.size assert(stack.peek === lastItemAdded) assert(stack.size === size) }
it should "remove the top item on pop" in { val stack = newStack val size = stack.size assert(stack.pop === lastItemAdded) assert(stack.size === size - 1) } }
def nonFullStack(newStack: => Stack[Int]) {
it should "not be full" in { assert(!newStack.full) }
it should "add to the top on push" in { val stack = newStack val size = stack.size stack.push(7) assert(stack.size === size + 1) assert(stack.peek === 7) } } }

Given these behavior functions, you could invoke them directly, but FlatSpec offers a DSL for the purpose, which looks like this:

it should behave like nonEmptyStack(stackWithOneItem, lastValuePushed)
it should behave like nonFullStack(stackWithOneItem)

If you prefer to use an imperative style to change fixtures, for example by mixing in BeforeAndAfterEach and reassigning a stack var in beforeEach, you could write your behavior functions in the context of that var, which means you wouldn't need to pass in the stack fixture because it would be in scope already inside the behavior function. In that case, your code would look like this:

it should behave like nonEmptyStack // assuming lastValuePushed is also in scope inside nonEmptyStack
it should behave like nonFullStack

The recommended style, however, is the functional, pass-all-the-needed-values-in style. Here's an example:

class SharedTestExampleSpec extends FlatSpec with StackBehaviors {

// Stack fixture creation methods def emptyStack = new Stack[Int]
def fullStack = { val stack = new Stack[Int] for (i <- 0 until stack.MAX) stack.push(i) stack }
def stackWithOneItem = { val stack = new Stack[Int] stack.push(9) stack }
def stackWithOneItemLessThanCapacity = { val stack = new Stack[Int] for (i <- 1 to 9) stack.push(i) stack }
val lastValuePushed = 9
"A Stack (when empty)" should "be empty" in { assert(emptyStack.empty) }
it should "complain on peek" in { intercept[IllegalStateException] { emptyStack.peek } }
it should "complain on pop" in { intercept[IllegalStateException] { emptyStack.pop } }
"A Stack (with one item)" should behave like nonEmptyStack(stackWithOneItem, lastValuePushed)
it should behave like nonFullStack(stackWithOneItem)
"A Stack (with one item less than capacity)" should
behave like nonEmptyStack(stackWithOneItemLessThanCapacity, lastValuePushed)
it should behave like nonFullStack(stackWithOneItemLessThanCapacity)
"A Stack (full)" should "be full" in { assert(fullStack.full) }
it should behave like nonEmptyStack(fullStack, lastValuePushed)
it should "complain on a push" in { intercept[IllegalStateException] { fullStack.push(10) } } }

If you load these classes into the Scala interpreter (with scalatest's JAR file on the class path), and execute it, you'll see:

scala> (new SharedTestExampleSpec).execute()
A Stack (when empty)
- should be empty
- should complain on peek
- should complain on pop
A Stack (with one item)
- should be non-empty
- should return the top item on peek
- should not remove the top item on peek
- should remove the top item on pop
- should not be full
- should add to the top on push
A Stack (with one item less than capacity)
- should be non-empty
- should return the top item on peek
- should not remove the top item on peek
- should remove the top item on pop
- should not be full
- should add to the top on push
A Stack (full)
- should be full
- should be non-empty
- should return the top item on peek
- should not remove the top item on peek
- should remove the top item on pop
- should complain on a push

One thing to keep in mind when using shared tests is that in ScalaTest, each test in a suite must have a unique name. If you register the same tests repeatedly in the same suite, one problem you may encounter is an exception at runtime complaining that multiple tests are being registered with the same test name. A good way to solve this problem in a FlatSpec is to make sure each invocation of a behavior function is in the context of a different subject, which will prepend a string to each test name. For example, the following code in a FlatSpec would register a test with the name "A Stack (when empty) should be empty":

behavior of "A Stack (when empty)"

it should "be empty" in { assert(emptyStack.empty) } // ...

Or, using the shorthand notation:

"A Stack (when empty)" should "be empty" in {
  assert(emptyStack.empty)
}
// ...

If the "should be empty" test was factored out into a behavior function, it could be called repeatedly so long as each invocation of the behavior function is in the context of a different subject.

Shared tests in other style traits

Shared tests are supported in all style traits in which tests are represented as functions, because they require registering the same test function multiple times, each time parameterized with different fixture objects. In trait Suite tests are methods, thus shared tests aren't supported. The Scaladoc of each style trait that supports them includes an example of shared tests.

A related technique is property-based testing. Whereas in shared tests you evaluate the same test function on different data, in property-based testing you evaluate the same property function on different data.

Next, learn about using matchers.

ScalaTest is brought to you by Bill Venners, with contributions from several other folks. It is sponsored by Artima, Inc.
ScalaTest is free, open-source software released under the Apache 2.0 license.

Copyright ? 2009-2013 Artima, Inc. All Rights Reserved.

artima

  评论这张
 
阅读(438)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017