2016-01-06 2 views
2

Я нахожу использование specs2 с scalacheck для проверки законов Monoid, немного уродливых, когда вы пытаетесь использовать библиотеку привязки scalazck scalazck. В моем коде используется скаляр Моноид, поэтому я хотел использовать их законы, чтобы проверить, что MyType реализует их.с использованием specs2 с привязкой scalaz-scalacheck к законам тестов

Эта уродство заставляет меня думать, что я пропускаю что-то или неправильно использую API Specs2 или scalacheck-binding API. Сушестились.

Это то, что я сделал: -

Я использую specs2 3,7 с scalaz 2.7.0

Читая инструкцию на «http://etorreborre.github.io/specs2/guide/SPECS2-3.0/org.specs2.guide.UseScalaCheck.html» я продлил свою спецификацию с Scalacheck признака и у меня есть Arbitrary[MyType] в области, поэтому я должен иметь возможность использовать scalacheck OK.

Док упоминалось выше гласит, что мне нужно передать функцию методу prop до тех пор, как прошло функция возвращает Result где scalacheck-х Prop является действительным Result

scalacheck связывания апи дает мне monoid.laws[T] функцию что возвращает Properties, который является Prop так что это должно быть в порядке, она также принимает неявные параметры типов Monoid[T], Equal[T] и Arbitrary[T] все из которых я имею в сфере, где T является MyType

Я хочу, чтобы это сделать:

class MyTypeSpec extends Specification with ScalaCheck { 
    def is = s2""" 
    MyType spec must :- 
    obey the Monoid Laws $testMonoidLaws 
    """ 

    def testMonoidLaws = { 
    import org.scalacheck.{Gen, Arbitrary} 
    import scalaz.scalacheck.ScalazProperties._ 
    implicit val arbMyType: Arbitrary[MyType] = genArbMyTpe() // an helper Arbitrary Gen func i have written 
    prop { monoid.laws[MyType] } 
    } 
} 

но propcannot be applied to (org.scalacheck.Properties) Это требует Т в Произвольном быть типом в параметре функции, так что я сделал это, заметьте, я TRow прочь параметр т , ...

class MyTypeSpec extends Specification with ScalaCheck { 
    def is = s2""" 
    MyType spec must :- 
    obey the Monoid Laws $testMonoidLaws 
    """ 

    def testMonoidLaws = { 
    import org.scalacheck.{Gen, Arbitrary} 
    import scalaz.scalacheck.ScalazProperties._ 
    implicit val arbMyType: Arbitrary[MyType] = genArbMyTpe() //some Arbitrary Gen func 
    prop { (t: Path => monoid.laws[MyType] } 
    } 
} 

Мой тест проходит. ура! Так в чем проблема?

Я не уверен в тестировании. Все, что он говорит, это прошло. Я не получаю никаких выходных данных, как если бы я использовал Scalacheck, рассказывая мне, какие законы он выполнял и прошел. Также я выбрасываю параметр t и позволяю monoid.laws[MyType] найти в видимой области видимости, что кажется неправильным. Работает? Я искал API specs2?

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

Falsified after 0 passed tests. 

Я могу собрать Произвольное [MyType], делая

prop { (p: Path) => monoid.laws[Path] }.collectArg(f => "it was " + f.shows) 

затем запустить его, как так

sbt testOnly MyTypeSpec -- scalacheck.verbose 

, который показывает мне собранные значения t, когда он работает, но когда я выбрасываю t Я не уверен, что это действительно вообще.

Есть ли лучший способ проверить использование Specs2 и скальсальных привязок scalaz, которые менее уродливы и выводит информацию, которая дает мне уверенность в том, что законы были опробованы и протестированы?

Благодаря

Karl

ответ

3

Вы можете использовать Properties напрямую, без использования prop. Вот полный пример:

import org.specs2._ 
import scalaz.scalacheck.ScalazProperties._ 
import org.scalacheck._ 
import scalaz._, Scalaz._ 
import PositiveInt._ 

class TestSpec extends Specification with ScalaCheck { def is = s2""" 

PositiveInt should pass the Monoid laws $e1 

""" 
    def e1 = monoid.laws[PositiveInt] 
} 

case class PositiveInt(i: Int) 

object PositiveInt { 
    implicit def ArbitraryPositiveInt: Arbitrary[PositiveInt] = 
    Arbitrary(Gen.choose(0, 100).map(PositiveInt.apply)) 

    implicit def EqualPositiveInt: Equal[PositiveInt] = 
    Equal.equalA[PositiveInt] 

    implicit def MonoidPositiveInt: Monoid[PositiveInt] = new Monoid[PositiveInt] { 
    val zero = PositiveInt(1) 
    def append(p1: PositiveInt, p2: =>PositiveInt): PositiveInt = 
     PositiveInt(p1.i + p2.i) 
    } 
} 

И поскольку экземпляр Monoid неверен будет завершаться:

[info] TestSpec 
[info] 
[error] x PositiveInt should pass the Monoid laws 
[error] Falsified after 0 passed tests. 
[error] > Labels of failing property: 
[error] monoid.left identity 
[error] > ARG_0: PositiveInt(3) 
[info] 
[info] 
[info] Total for specification TestSpec 
[info] Finished in 185 ms 
[info] 1 example, 1 failure, 0 error 

Неудача указывает первые законы, которые не в состоянии пройти. Однако он не создает нескольких примеров, по одному для каждого закона, для отображения того, какой закон выполняется. Если вы хотите сделать, что вы можете сопоставить каждое свойство законов Properties на пример: класса TestSpec расширяет спецификацию с ScalaCheck {Защиты есть = s2 «»»

PositiveInt should pass the Monoid laws $properties 

""" 

    def properties = toExamples(monoid.laws[PositiveInt]) 

    def toExamples(ps: Properties): Fragments = 
    t^Fragments.foreach(ps.properties) { case (name, prop) => br^name ! prop } 
} 

Этой печать (для прохождения Monoid[PositiveInt] например) :

[info] TestSpec 
[info] 
[info] PositiveInt should pass the Monoid laws 
[info] + monoid.semigroup.associative 
[info] + monoid.left identity 
[info] + monoid.right identity 
[info] 
[info] Total for specification TestSpec 
[info] Finished in 91 ms 
[info] 3 examples, 300 expectations, 0 failure, 0 error 
+0

Спасибо Эрик. Мне было непонятно, что я могу просто вернуть Свойства непосредственно из документации, где все примеры использовали prop. – user2056182

Смежные вопросы