2012-01-10 4 views
3

У меня есть следующий класс, и я хочу написать некоторые тестовые примеры Spec, но я действительно новичок в этом, и я не знаю, с чего начать. Мой класс делает это следующим образом:Scala spec unit tests

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/ –

+0

Предполагая, что вы просмотрели спецификации specs2. Учитывая ваш класс Board, вы хотите подтвердить, написав тесты, что ваш код ведет себя так, как вы ожидаете, путем вызова методов и проверки состояния или возвращаемых значений, как вы ожидаете. Посмотрите здесь несколько примеров https://github.com/mongodb/casbah/tree/master/casbah-gridfs/src/test/scala. Посмотрите также на это видео http://www.youtube.com/watch?v = lMyNRUuEvNU – foolshat

+0

Спасибо, я посмотрел, но все равно не понимаю! Можете ли вы дать мне пример для класса платы? класс BoardSpec распространяется СпецификацияWithJUnit { } – user1137701

ответ

-1

Предлагаю вам выбросить весь этот код - ну, сохраните его где-нибудь, но начните с нуля с помощью TDD.

На сайте Specs2 есть много примеров того, как писать тесты, но используйте TDD-test driven design - для этого. Добавление тестов после того, как факт субоптимален, если не сказать больше.

Итак, подумайте о самом простом случае, который вы хотите обработать самой простой функцией, напишите тест на это, посмотрите, как он сработает, напишите код, чтобы исправить это. При необходимости повторите попытку, и повторите его для следующего наиболее простого случая.

Если вам нужна помощь в том, как делать TDD, я сердечно одобряю видео о TDD, доступном на Clean Coders. По крайней мере, смотрите вторую часть, где Боб Мартин пишет целый класс TDD-стиля, от дизайна до конца.

Если вы знаете, как проводить тестирование в целом, но смущены о Scala или Specs, пожалуйста, будьте более конкретными в отношении ваших вопросов.

+0

Дело в том, что я не могу выбросить этот код ... Порграмма работает, но мне нужны некоторые тестовые примеры для него – user1137701

+0

@ user1137701 Если вы собираетесь быть программистом, d лучше привыкнуть выбросить код и переделать его. Класс выше достаточно мал, чтобы переписывать все это было достаточно просто. Но сделай то, что хочешь. Я не собираюсь менять свой совет, потому что ты этого не хочешь. –

4

Я могу предложить только второе предложение Дэниела, потому что вы получите более практичный API, используя TDD.

Я также считаю, что ваше приложение может быть хорошо протестировано с использованием сочетаний 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. Вы также захотите изменить сгенерированные данные, чтобы платы были сгенерированы с чередованием x и o. Это должен быть отличный способ узнать, как использовать ScalaCheck!

+0

Эй, Эрик, большое спасибо! Как запустить этот код? Я попытался запустить JUNIT-Test, но потом получим результат, который не найден в тестах JUNIT. – user1137701

+0

Я использую Intellij, который напрямую поддерживает specs2. Если вы используете eclipse, вам нужно расширить org.specs2.SpecificationWithJUnit (если это не сработает, вам нужно добавить аннотацию @RunWith (classOf [JUnitRunner]) (JUnitRunner находится в org.specs2.runner package)) – Eric

+0

Эй, Эрик, я попытался использовать это, но затем получим эту ошибку: java.lang.ClassCastException: TestSpec нельзя отнести к org.scalatest.Suite – user1137701