Как работает синтаксис ScalaTest?

Я занимался программированием в 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. Это аккуратно.

13.10.2009 07:04:33
ScalaTest с открытым исходным кодом, не так ли? Так что, если вы хотите знать, как это делается, просто посмотрите на исходный код.
Jesper 13.10.2009 07:07:11
Такие вещи, как глобальные неявные преобразования, затрудняют понимание трюков синтаксиса. Но если у вас есть конкретные идеи о том, как читать / просматривать, пожалуйста, поделитесь.
Yang 13.10.2009 18:36:29
2 ОТВЕТА
РЕШЕНИЕ

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

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тип исключения, заключенный в квадратные скобки. Таким образом, он выполняет блок кода, заключенный в a try, ловит исключение, сравнивает его с ожидаемым. Если исключение не выбрано, или неверное, shouldметод генерирует a TestFailedException. В противном случае shouldметод просто возвращается молча.

Таким образом, ответ заключается в том, что строка разбирается на:

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

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

13
1.07.2019 22:19:40

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

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

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

2
13.10.2009 07:40:18
Спасибо за указатель на нужное место в документации. Извините, it shouldвопрос был на самом деле очевиден (не уверен, как я это пропустил), но я все еще в замешательстве _ should produce _.
Yang 13.10.2009 18:37:41