SlideShare a Scribd company logo
Scala Check で Property-based Tes5ng
テスト対象のデータ構造
• ESDataPoint
• ESTimeSeries
ESDataPoint
Int : AAAA_AAAA AAAA_AAAA AAAA_AAAA AABB_BBBB
• A: タイムスタンプ(下位 6 ビットはゼロ埋め)
• B: SSP ID
class ESDataPoint(val rawValue: Int) extends AnyVal {
def sspId: Int = rawValue & 0x3F
def timestamp: Int = rawValue & 0xFFFFFFC0
}
ESTimeSeries
java.util.List[ESDataPoint]
• タイムスタンプの降順にソートされている
• 同一 SSP ID の要素は最大 1 つしか存在しない
ESTimeSeries への ESDataPoint の追加は高頻度で実行するので…
def +(adding: ESDataPoint): ESTimeSeries
スキャンが 1 回で済むように var を使って探索していたり…
var foundSsp: Option[(Int, ESDataPoint)] = None
var insertPos: Int = 0
0.until(storage.size).foreach { i =>
val dp = ESDataPoint(storage.get(i))
if (dp.sspId == addingSspId) foundSsp = Some(i -> dp)
if (dp.timestamp > addingTimestamp) insertPos = i + 1
}
リストの変更も面倒なことに…
val newList = new java.util.ArrayList[java.lang.Long](storage)
newList.add(insertPos, adding.rawValue)
// リストに追加された要素の位置をもとに、削除位置を補正する
val offset = if (insertPos <= sspPos) 1 else 0
newList.remove(sspPos + offset)
正しく書けているか
まったく自信が持てない!
エッジケースを考えるのが面倒!
満たすべき性質ははっきりしているのだから
ScalaCheck
を使ってみよう!
準備
dependencies {
testCompile 'org.specs2:specs2-core_2.11:3.6.6'
testCompile 'org.specs2:specs2-scalacheck_2.11:3.6.6'
}
import org.specs2.mutable.Spec
class ESTimeSeriesSpec extends Spec with ScalaCheck {
...
}
• ScalaCheck trait を mix-in
テストデータの生成ルール (Gen)
import org.scalacheck.Gen
val dataPointGen: Gen[ESDataPoint] = for {
sspId <- Gen.choose(min = 0, max = 63)
timestamp <- Gen.choose(min = 0, max = Int.MaxValue >> 6).map(_ << 6)
} yield ESDataPoint(sspId, timestamp)
• Gen.choose で値の範囲を定義
• map, flatMap できる
import org.scalacheck.Arbitrary
// テストデータ引数の型 T に対する Arbitrary[T] の implicit が必要
// 基本的には Gen[T] を使って宣言すれば良い
implicit val dataPointArb: Arbitrary[ESDataPoint] = Arbitrary(dataPointGen)
"時系列はタイムスタンプの降順にソートされている" >> {
// 性質の宣言
prop {
// 受け取るテストデータ
// - ESDataPoint は Gen[ESDataPoint] のルールからランダムに選択される
// - Array[_] の要素数もランダムに選択される
(dataPoints: Array[ESDataPoint]) => {
// テストデータを使って ESTimeSeries を構築
val ts = dataPoints.foldLeft(ESTimeSeries.empty)(_ + _).toDataPoints
// 性質のチェック
ts.map(_.timestamp) must beSorted(Ordering[UnixTimestamp].reverse)
}
}
}
"時系列は重複する SSP を含まない" >> {
prop {
(dataPoints: Array[ESDataPoint]) => {
val ts = dataPoints.foldLeft(ESTimeSeries.empty)(_ + _).toDataPoints
// 性質のチェック
ts.size must_== ts.map(_.sspId).distinct.size
}
}
}
• デフォルトでは 100 回テストされる
まとめ
• データ構造やアルゴリズムのテストに ScalaCheck は良い
• テストデータそのものをテストに記述しなくて良いのが楽
• テストデータの生成ルール(Gen)は注意深く定義する必要があり
そう

More Related Content

Viewers also liked

Property-Based Testing for Services
Property-Based Testing for ServicesProperty-Based Testing for Services
Property-Based Testing for Services
jessitron
 
Property based testing - Less is more
Property based testing - Less is moreProperty based testing - Less is more
Property based testing - Less is more
Ho Tien VU
 
Better Tests, Less Code: Property-based Testing
Better Tests, Less Code: Property-based TestingBetter Tests, Less Code: Property-based Testing
Better Tests, Less Code: Property-based Testing
C4Media
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rules
Debasish Ghosh
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
Scott Wlaschin
 
UNIT TESTING PPT
UNIT TESTING PPTUNIT TESTING PPT
UNIT TESTING PPT
suhasreddy1
 

Viewers also liked (6)

Property-Based Testing for Services
Property-Based Testing for ServicesProperty-Based Testing for Services
Property-Based Testing for Services
 
Property based testing - Less is more
Property based testing - Less is moreProperty based testing - Less is more
Property based testing - Less is more
 
Better Tests, Less Code: Property-based Testing
Better Tests, Less Code: Property-based TestingBetter Tests, Less Code: Property-based Testing
Better Tests, Less Code: Property-based Testing
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rules
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
 
UNIT TESTING PPT
UNIT TESTING PPTUNIT TESTING PPT
UNIT TESTING PPT
 

ScalaCheckでProperty-based Testing