Как работает синтаксис ScalaTest? - PullRequest
5 голосов
/ 13 октября 2009

Я занимался программированием в Scala, и я знаю это, например,

xs map f

- это то же самое, что и

xs.map(f)

но я понятия не имею, как обобщить этот синтаксис в нечто вроде синтаксиса ScalaTest, например,

it should "throw NoSuchElementException if an empty stack is popped" in {
  val emptyStack = new Stack[String]
  evaluating { emptyStack.pop() } should produce [NoSuchElementException]
}

Меня больше всего интересуют вещи, которые выглядят как конструкции из нескольких слов, а именно should produce. Это аккуратно.

Ответы [ 2 ]

12 голосов
/ 14 октября 2009

Синтаксис такого типа - это вызовы методов в нотации операторов, но они переносятся более чем на три токена. Как вы уже упоминали:

xs map f

означает:

xs.map(f)

Но вы могли бы пойти дальше и сказать:

xs map f map g

, что означает:

xs.map(f).map(g)

Например, в сопоставителях ScalaTest вы можете сказать:

result should not be null

Это компилируется с помощью компилятора:

result.should(not).be(null)

Это:

it should "throw an exception" in { ... }

переводится в:

it.should("throw an exception").in { ... }

Фигурные скобки в конце - это на самом деле способ передачи кода между фигурными скобками (тестовый код) в метод in, заключенный в функцию без аргументов. Так что все это одна и та же идея. Обозначение оператора используется дважды подряд.

Последний вопрос, о котором вы спрашивали, немного другой:

evaluating { ... } should produce [IllegalArgumentException]

Это преобразуется в:

evaluating { ... } сначала оценивается, потому что фигурные скобки дают ему приоритет. Так что это вызов метода, вы вызываете метод с именем «вычисления», передавая код между фигурными скобками как функцию без аргументов. Это возвращает объект, для которого вызывается should. Таким образом, should - это метод для объекта, возвращаемого путем вызова evaluating. То, что should на самом деле берет, является результатом вызова produce. Здесь produce на самом деле является методом, который имеет параметр типа, например [IllegalArgumentException]. Это должно быть сделано таким образом, чтобы компилятор Scala мог «переиграть бедняков» этого параметра типа. Он передает неявный параметр "Manifest" в produce, который может предоставить экземпляр java.lang.Class для IllegalArgumentException. Следовательно, когда вызывается метод should, он имеет функцию, содержащую код, переданный в evaluating, и способ найти java.lang.Class типа исключения, заключенного в квадратные скобки. Таким образом, он выполняет блок кода, заключенный в try, ловит исключение, сравнивает его с ожидаемым. Если исключение не выбрано, или неправильное, метод should выдает TestFailedException. В противном случае метод should просто возвращает без вывода сообщений.

Итак, ответ в том, что строка обнуляется:

(evaluating { ... }).should(produce[IllegalArgumentException] (compilerSuppliedManifest))

И мораль этой истории в том, что подобный код высокого уровня облегчает понимание намерений программиста, но зачастую труднее понять, как на самом деле работает код. В большинстве случаев на практике все, что вас волнует, - это намерение, но время от времени вам нужно знать, как что-то работает. В таких случаях в Scala вы можете передать -Xprint:typer в качестве аргумента командной строки компилятору Scala, и он распечатает версию вашего файла после того, как произойдет десагеринг. Так что вы можете видеть, что к чему, когда вам нужно.

2 голосов
/ 13 октября 2009

Это достаточно просто, потому что это нормальный код - it should эквивалентен it.should, следовательно, в области видимости должно быть значение (или метод) с именем it. И есть !

Эта переменная имеет тип ItWord, который предоставляет метод с именем should, который принимает объект типа BehaveWord. Эти совпадения смешиваются посредством неявных преобразований в ShouldMatchers trait.

ScalaTest на самом деле чрезвычайно хорошо документирован с множеством примеров и описаний того, как все работает.

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