2012-01-10 71 views
3

我已經得到了以下類,我想寫一些Spec測試用例,但我真的很陌生,我不知道如何開始。我的班級喜歡這樣:斯卡拉規格單元測試

class Board{ 

    val array = Array.fill(7)(Array.fill(6)(None:Option[Coin])) 

    def move(x:Int, coin:Coin) { 
    val y = array(x).indexOf(None) 
    require(y >= 0) 
    array(x)(y) = Some(coin) 
    } 

    def apply(x: Int, y: Int):Option[Coin] = 
    if (0 <= x && x < 7 && 0 <= y && y < 6) array(x)(y) 
    else None 

    def winner: Option[Coin] = winner(Cross).orElse(winner(Naught)) 

    private def winner(coin:Coin):Option[Coin] = { 
    val rows = (0 until 6).map(y => (0 until 7).map(x => apply(x,y))) 
    val cols = (0 until 7).map(x => (0 until 6).map(y => apply(x,y))) 
    val dia1 = (0 until 4).map(x => (0 until 6).map(y => apply(x+y,y))) 
    val dia2 = (3 until 7).map(x => (0 until 6).map(y => apply(x-y,y))) 

    val slice = List.fill(4)(Some(coin)) 
    if((rows ++ cols ++ dia1 ++ dia2).exists(_.containsSlice(slice))) 
     Some(coin) 
    else None 
    } 

    override def toString = { 
    val string = new StringBuilder 
    for(y <- 5 to 0 by -1; x <- 0 to 6){ 
     string.append(apply(x, y).getOrElse("_")) 
     if (x == 6) string.append ("\n") 
     else string.append("|") 
    } 
    string.append("0 1 2 3 4 5 6\n").toString 
    } 
} 

謝謝!

+1

您可以查看specs2的文檔:http://etorreborre.github.com/specs2/ – 2012-01-10 15:10:13

+0

假設您查看了specs2文檔。考慮到你的Board類,你想通過編寫測試來確認你的代碼的行爲如你所期望的那樣通過調用方法並檢查狀態或返回值是否如你所期望的那樣。看看這裏的一些例子https://github.com/mongodb/casbah/tree/master/casbah-gridfs/src/test/scala另請看這個視頻http://www.youtube.com/watch?v = lMyNRUuEvNU – foolshat 2012-01-10 15:26:33

+0

謝謝,我看了一下,但還是不明白!你可以給我一個板級的例子嗎? class BoardSpec擴展SpecificationWithJUnit { } – user1137701 2012-01-10 15:39:14

回答

-1

我建議你把所有的代碼都扔出去 - 好吧,保存在某個地方,但是使用TDD從零開始。

Specs2網站有很多關於如何編寫測試的例子,但是使用TDD - 測試驅動設計 - 來做到這一點。至少可以說,在事實之後添加測試並不理想。

因此,想想你想要處理的最簡單的功能最簡單的情況,寫一個測試,看到它失敗,編寫代碼來修復它。必要時重構,並重復下一個最簡單的情況。

如果您需要一般TDD的幫助,我衷心贊同Clean Coders上提供的有關TDD的視頻。至少,請看第二部分,鮑勃·馬丁寫下了從設計到結束的全班TDD風格。

如果您知道如何進行一般測試但對Scala或Specs感到困惑,請更具體地瞭解您的問題。

+0

事情是我不能扔掉那個代碼...這個porgram正在工作,但我需要一些測試用例 – user1137701 2012-01-10 15:48:25

+0

@ user1137701如果你要成爲一名程序員,最好習慣扔掉代碼並重做它。上面的類很小,重寫所有它應該很容易。但是,做你想做的事情。我不會改變我的建議,因爲你不需要它。 – 2012-01-10 19:29:17

4

我只能用丹尼爾的建議,因爲使用TDD最終會得到更實用的API。

我也認爲你的應用程序可以很好地測試specs2和ScalaCheck的混合。這裏一個規範的草案,讓你開始:

import org.specs2._ 
    import org.scalacheck.{Arbitrary, Gen} 

    class TestSpec extends Specification with ScalaCheck { def is = 

    "moving a coin in a column moves the coin to the nearest empty slot" ! e1^ 
    "a coin wins if"             ^
     "a row contains 4 consecutive coins"        ! e2^ 
     "a column contains 4 consecutive coins"       ! e3^ 
     "a diagonal contains 4 consecutive coins"       ! e4^ 
                     end 

    def e1 = check { (b: Board, x: Int, c: Coin) => 
     try { b.move(x, c) } catch { case e =>() } 
     // either there was a coin before somewhere in that column 
     // or there is now after the move 
     (0 until 6).exists(y => b(x, y).isDefined) 
    } 

    def e2 = pending 
    def e3 = pending 
    def e4 = pending 

    /** 
    * Random data for Coins, x position and Board 
    */ 
    implicit def arbitraryCoin: Arbitrary[Coin]  = Arbitrary { Gen.oneOf(Cross,  Naught) } 
    implicit def arbitraryXPosition: Arbitrary[Int] = Arbitrary { Gen.choose(0, 6) } 
    implicit def arbitraryBoardMove: Arbitrary[(Int, Coin)] = Arbitrary { 
     for { 
     coin <- arbitraryCoin.arbitrary 
     x <- arbitraryXPosition.arbitrary 
     } yield (x, coin) 
    } 
    implicit def arbitraryBoard: Arbitrary[Board] = Arbitrary { 
     for { 
     moves <- Gen.listOf1(arbitraryBoardMove.arbitrary) 
     } yield { 
     val board = new Board 
     moves.foreach { case (x, coin) => 
      try { board.move(x, coin) } catch { case e =>() }} 
      board 
     } 
    } 


    } 

    object Cross extends Coin { 
    override def toString = "x" 
    } 
    object Naught extends Coin { 
    override def toString = "o" 
    } 
    sealed trait Coin 

e1財產我實現是不是真實的東西,因爲它並沒有真正檢查我們感動的硬幣到最近空插槽,這就是你的代碼和API的建議。您還需要更改生成的數據,以便生成交替xo的板。這應該是學習如何使用ScalaCheck的好方法!

+0

嗨Eric,非常感謝!我如何開始這段代碼?我試圖運行JUNIT-Test,但是然後得到結果,沒有發現JUNIT測試 – user1137701 2012-01-11 11:07:48

+0

我正在使用直接支持specs2的Intellij。如果你使用的是eclipse,你需要擴展org.specs2.SpecificationWithJUnit(如果這不起作用,你需要添加@RunWith(classOf [JUnitRunner])註解(JUnitRunner在org.specs2中。亞軍包)) – Eric 2012-01-11 20:49:21

+0

嘿埃裏克,我試圖用這個,但然後得到這個錯誤:java.lang.ClassCastException:TestSpec不能轉換爲org.scalatest.Suite – user1137701 2012-01-17 11:58:41