Scala创建以功能样式测试的随机对象



我试图弄清楚哪种情况是这种情况最有用的样式

我有一个图像模型

case class Image(
  id: Int,
  name: String,
  title: String,
  permalink: String,
  url: String 
)

我有一个testhelper对象,当我编写测试时对我有帮助,因为它允许我创建随机图像

package utils
import models.Pet
import scala.util.Random
object TestHelper {
  val random = new Random()
  def randomId = random.nextInt(Integer.MAX_VALUE)
  val nameList: List[String] = List("Joycelyn", "Shaunte", "Aurelio", "Jeane", "Carline", "Major", "Shawanna", "Hayden", "Benjamin", "Roxy", "Ardelia", "Yanira", "Tilda", "Claude", "Jonah", "Ilse", "Kieth", "Elmira", "Reid", "Bethann", "Catherine", "Yasuko", "Kia", "Merri", "Ethelyn", "Mallory", "Eustolia", "Matt", "Lynelle", "Christi", "Alane", "Miles", "Ressie", "Darryl", "Kathy", "Hiedi", "Kacy", "Cecila", "Tamar", "Dwayne", "Charlette", "Wanetta", "Sonja", "Celine", "Vina", "Teresa", "Dagny", "Debera", "Doreatha", "Wilda")
  def randomImage: Image = {
    var id = randomId
    var name = nameList(random.nextInt(nameList.length))
    var title = name
    var permalink = name.toLowerCase
    var logoUrl = s"https://www.images.com/${permalink}"
    Image(id, name, title, permalink, logoUrl)
  }
}

但是我知道,如果我想以功能风格写作,我应该避免使用var。如果我不使用字段name,几次,将所有var s用def s替换为足够的,但是由于我需要重复该值,我不确定如何以功能性的样式编写它

看一下我们的一个libs(无耻免责声明(。

util-samplers

https://github.com/outworkers/util/blob/develop/util-samplers

它使用宏来导航案例类的结构并生成适当的样本。这不是一个魔术子弹,但大多数时候都会处理大多数事情,并且还会在可能的情况下生成有意义的数据。

例如,如果该字段称为名称,您将获得"彼得·史密斯"的样式结果。它也与Scalacheck完全兼容,但总体而言是非常简单的宏。通过让我写它可以保证这很简单。

val imageGenerator = Sample.generator[Image]
implicit val imageArb = Sample.arbitrary[Image]

,您可以将其直接插入功能性的检查器中。

forAll { img: Image => ....
}

如果您根本不想要Scalacheck,请使用基础知识:

import com.outworkers.util.samplers._
class MyTest extends FlatSpec {
  it should "upload an image to S3" in {
    val image = gen[Image]
    val images = genList[Image](25)
  }
}

如果您无法生成类型或宏抱怨,请自己写一个采样器。在大多数情况下,您将拥有类似特质或对象的东西来持有所有这些。

object ExtraSamples {
  implicit val cantAutomateThis: Sample[java.net.Bla] = new Sample[java.net.Bla] {
    override def sample: java.net.Bla = // in here you fill it in manuall....
  }
}

然后,如果您的case class具有java.net.Bla字段,则只需在执行gen的地方import ExtraSamples._即可,您的手动实现将用于构造更复杂的内容。这就是您可以支持开箱即用的任何东西的方式。

scalacheck sapeless

这是对同一问题的不同选择,但是它使用自动化的Typeclass实例派生功能,而不是宏。它的方法与util-samplers并没有大不相同,但是代码可能稍微复杂,但级别更高。

https://github.com/alexarchambault/scalacheck-apeless

import org.scalacheck.ScalacheckShapeless._
//  If you defined:
// case class Foo(i: Int, s: String, blah: Boolean)
// case class Bar(foo: Foo, other: String)
// sealed trait Base
// case class BaseIntString(i: Int, s: String) extends Base
// case class BaseDoubleBoolean(d: Double, b: Boolean) extends Base
//  then you can now do
implicitly[Arbitrary[Foo]]
implicitly[Arbitrary[Bar]]
implicitly[Arbitrary[Base]]

我从来没有进行过一边的比较,并且他们无意互相竞争。第一个非常快速且轻巧,高度很小,因为它只是一个宏,无形的参与度更高,并且汇编时间更高,但就可以自动生成的类型而言,它可能更高级。

您可以使用scalacheck。Scalacheck是功能语言Haskell库QuickCheck的端口,它使您可以以功能样式编写随机测试示例生成器。

在这种特殊情况下,您可以简单地由val s替换所有本地var s,因为无论如何您都不会突变varS。

最新更新