我试图弄清楚哪种情况是这种情况最有用的样式
我有一个图像模型
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,因为无论如何您都不会突变var
S。