Scala Check/Scala Test: Генераторы Compose

Есть ли способ составить генераторы в scala test/scala check?

Например, вот пример тестового случая, который я хотел бы написать:

"The classifier" when {
  "given a string containing a state" should {
    "classify it as a state" in {
      val states = Seq(
        "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware",
        "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky",
        "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi",
        "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
        "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania",
        "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont",
        "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"
      )

      val inputData = for {
        zip <- Gen.const("10001")
        name <- Gen.oneOf(
          Gen.oneOf(states) + "HARRINGTON, JOHN",
          "HARRINGTON, JOHN " + Gen.oneOf(states),
          "HARRINGTON, " + Gen.oneOf(states) + " MD,JOHN"
        )
      } yield (zip, name)

      forAll (inputData) { case (zip: String, name: String) =>
        Clasifier.classify(zip, name) shouldBe Classification.STATE
      }
    }
  }
}

Обратите внимание на генератор name для понимания, чтобы получить inputData val.

Как я могу добиться чего-то подобного?

Обновление: я заставил это работать, но не уверен, что поступаю правильно.

      val inputData = for {
        zip <- Gen.const("10001")
        name <- Gen.oneOf(
          s"${Gen.oneOf(states).sample.get} HARRINGTON, JOHN",
          s"HARRINGTON, JOHN ${Gen.oneOf(states).sample.get}",
          s"HARRINGTON, ${Gen.oneOf(states).sample.get} MD,JOHN"
        )
      } yield (zip, name)

Сообщение об ошибке (ожидаемый сбой) не очень помогает в том, что я делаю:

TestFailedException was thrown during property evaluation.
  Message: STATE was not equal to INDIVIDUAL
  Location: (Classifier$Test.scala:142)
  Occurred when passed generated values (
    arg0 = (,) // 12 shrinks
  )

PS: Как и просили в комментарии, вот как я ожидаю, что входные данные будут выглядеть так:

"Alabama Harringgon, John",
"Harriongton, Alabama John",
"Harrington, John Alabama",
"Maryland Harrington, John",
"Harrington, Maryland John",
"Harrington, John Maryland",
etc.

person nemo    schedule 23.08.2017    source источник
comment
Возможно, в этом случае генератор неприменим. Пожалуйста, дай мне знать.   -  person nemo    schedule 23.08.2017
comment
Не могли бы вы привести пример того, каким должен быть ваш inputData? Просто чтобы знать, имеет ли смысл ваша реализация с учетом ваших требований.   -  person pedromss    schedule 01.09.2017
comment
Добавлен пример ввода данных!   -  person nemo    schedule 03.09.2017


Ответы (1)


Если вы хотите составить свои генераторы, вы можете просто включить состояние в for comprehension следующим образом:

val inputData = for {
    zip <- Gen.const("10001")
    state <- Gen.oneOf(states)
    name <- Gen.oneOf(
      state + "HARRINGTON, JOHN",
      "HARRINGTON, JOHN " + state,
      "HARRINGTON, " + state + " MD,JOHN"
    )
  } yield (zip, name)

Выполнение sample.get, как вы делаете в своем обновленном примере, вызовет исключение, если результатом примера будет None, что не будет тем, что вы хотите.

Причина, по которой вы получаете бесполезное сообщение об ошибке, заключается в сжатии, когда scalacheck попытается уменьшить значения до минимальных значений, которые завершатся ошибкой, в этом случае, когда оба значения являются пустыми строками. В большинстве случаев я обнаружил, что это не то поведение, которое вам нужно, и вы можете остановить его от сокращения значений, включив неявное выражение, подобное этому:

implicit val noShrinkString: Shrink[String] = Shrink.shrinkAny
implicit def noShrinkList[A]: Shrink[List[A]] = Shrink.shrinkAny

Первая строка останавливает сжатие строк, а вторая останавливает сжатие списков, назначая им один и тот же экземпляр сжатия типа Any, который вообще не должен сжиматься.

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

person Kurt Logan    schedule 13.10.2018