Юнит Теории и Скала - PullRequest
       5

Юнит Теории и Скала

3 голосов
/ 20 декабря 2011

Я ищу способ протестировать мой код Scala с несколькими входами. Исходя из Java / JUnit, я сразу подумал о @RunWith(Theories.class). Я застрял в использовании @DataPoints и отсутствии статических членов / методов в Scala. Так есть ли способ написать следующий код в Scala?

@RunWith(classOf[Theories])
class ScalaTheory {

  @DataPoints
  val numbers = Array(1, 2, 3)

  @Theory
  def shouldMultiplyByTwo(number : Int) = {
    // Given
    val testObject = ObjectUnderTest

    // When
    val result = testObject.run(number)

    // Then
    assertTrue(result == number * 2)
  }

}

Я не зациклен ни на JUnit, ни на Теориях, поэтому, если есть что-то специфичное для Scala для этого варианта использования, я с удовольствием его использую.

Ответы [ 3 ]

4 голосов
/ 20 декабря 2011

Чтобы сделать это, вам нужно сделать две вещи: использовать метод [см. Правку ниже], а не значение, и, во-вторых, определить ваш @DataPoints в сопутствующем объекте. Должно работать следующее:

object ScalaTheory {
  @DataPoints
  def numbers() = Array(1, 2, 3) // note def not val
}

@RunWith(classOf[Theories])
class ScalaTheory {
  @Theory
  def shouldMultiplyByTwo(number : Int) = {
    // Given
    val testObject = ObjectUnderTest

    // When
    val result = testObject.run(number)

    // Then
    assertTrue(result == number * 2)
  }
}

Когда вы определяете методы или поля в сопутствующем объекте в Scala, вы получаете статический перенаправитель в классе. Декомпиляция с использованием JAD:

@Theories
public static final int[] numbers()
{
    return ScalaTheory$.MODULE$.numbers();
}

Так что это решает статическую проблему. Тем не менее, когда мы используем val numbers = ..., аннотация не переносится в поле, а для методов. Так что использование def работает.

Как уже говорили другие, если вы разрабатываете с нуля, возможно, стоит начать с такой среды Scala, как scalatest. Интеграция инструмента с scalatest улучшается (то есть maven, Eclipse, Intellij), но это не уровень JUnit, поэтому оцените его для своего проекта перед началом.

РЕДАКТИРОВАТЬ: На самом деле, после этого обсуждения на scala-user , вы можете использовать val, но вам нужно указать компилятору scala применить аннотацию DataPoints к статическому перенаправителю:

object ScalaTheory {
  @(DataPoints @scala.annotation.target.getter)
  val numbers = Array(1, 2, 3)
}

В аннотации получателя сказано, что аннотация @DataPoints должна применяться к методу доступа для поля чисел, то есть метода numbers (), который создается компилятором. См. целевой пакет .

2 голосов
/ 20 декабря 2011

Так же, как ziggystar, я не могу помочь вам с вашим прямым вопросом.Но я настоятельно рекомендую перейти на платформу тестирования Scala.Мой личный фаворит - самый масштабный.

В последнем примере здесь: http://blog.schauderhaft.de/2011/01/16/more-on-testing-with-scalatest/ Я демонстрирую, как просто и просто написать тест, который выполняется с несколькими входами.Это просто петля!

2 голосов
/ 20 декабря 2011

Я ожидаю, что то, что вы хотите, возможно с любой средой тестирования Scala. Я только знаком с Specs2 , так что вот мой выстрел:

class DataPoints extends Specification {
  val objectUnderTest: Int => Int = _ + 2

  val testCases = 1 :: 2 :: 3 :: 4 :: Nil

  def is: Fragments = 
    (objectUnderTest must multiplyByTwo((_: Int))).foreach(testCases)    

  def multiplyByTwo(i: Int): Matcher[(Int) => Int] = 
    (=== (i * 2)) ^^ 
      ((f: Int => Int) => f(i) aka "result of applying %s to %d".format(f, i))
}

И вывод:

result of applying <function1> to 1 '3' is not equal to '2'; result of applying <function1> to 3 '5' is not equal to '6'; result of applying <function1> to 4 '6' is not equal to '8'

Ответственность

Я не утверждаю, что это очень читабельно. Также я не опытный пользователь Specs2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...