Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何获得scala案例类生成的随机数据,并能够;“更改某些值”;用于单元测试?_Scala_Unit Testing_Scalacheck - Fatal编程技术网

如何获得scala案例类生成的随机数据,并能够;“更改某些值”;用于单元测试?

如何获得scala案例类生成的随机数据,并能够;“更改某些值”;用于单元测试?,scala,unit-testing,scalacheck,Scala,Unit Testing,Scalacheck,我正在使用一段具有广泛/深入案例类层次结构的代码。对于单元测试,我希望在类中填充“随机数据”,能够更改我关心的字段的数据 例如: case class Foo(bar: Bar, name: String, value: Int) case class Bar(baz: Baz, price: Double) case class Baz(thing: String) 比如: val randomFoo = GenerateRandomData(Foo) randomFoo.bar.baz =

我正在使用一段具有广泛/深入案例类层次结构的代码。对于单元测试,我希望在类中填充“随机数据”,能够更改我关心的字段的数据

例如:

case class Foo(bar: Bar, name: String, value: Int)
case class Bar(baz: Baz, price: Double)
case class Baz(thing: String)
比如:

val randomFoo = GenerateRandomData(Foo)
randomFoo.bar.baz = Baz("custom for testing")
我听说过
ScalaCheck
Shapeless
ScalaCheck Shapeless
,它们确实提供了某种随机数据生成,但似乎与定制无关


我目前使用的是
ScalaMock
,但它构建了
null
字段,并破坏了“其他”测试的可测试性。我在.Net中使用了类似的东西,比如Auto Fixture,我想知道Scala中是否也有类似的东西。

Scalacheck
提供了一个常量生成器,允许定义自定义/常量字符串:

import org.scalacheck_
val fooGen:Gen[Foo]=
为了{
复制(事物=事物)
val镜头=(lensBar composeLens lensBaz composeLens lensThing)。设置(“测试自定义”)
val fooGen:Gen[Foo]=任意。任意[Foo]。贴图(镜头)
println(fooGen.sample)
//展示
//一些(Foo(Baz(测试自定义),1.22272641326224E-91),)❌䟤䉲㙯癏<,-2147483648))

我想你在找scalaz

它会做你想做的

然而,我必须说,使用随机数据进行单元测试似乎是一个可怕的想法。你要如何调试一个时不时发生的故障


您应该花一些时间设置一组确定性的常量测试对象,这些对象也类似于实际的生产数据,然后在测试中使用这些对象。

您的问题分为两部分。可以使用
Gen.resultOf
在ScalaCheck中自动生成类。这是以前在中提出的。它可能是有可能用更少的样板来做这件事

你问题的第二部分是关于在不可变对象中改变字段的。在大多数情况下,只需使用
case class
提供的
copy
构造函数就足够了。像这样的库可以帮上忙,但我从未使用过它

import org.scalacheck.Arbitrary
import org.scalacheck.Prop
import org.scalacheck.Prop.AnyOperators // Adds ?= operator
import org.scalacheck.Properties
import org.scalacheck.Gen

object FooSpec extends Properties("Foo") {

  val genBaz: Gen[Baz] = Gen.resultOf(Baz)

  implicit val arbBaz = Arbitrary(genBaz)

  val genBar: Gen[Bar] = Gen.resultOf(Bar)

  implicit val arbBar = Arbitrary(genBar)

  val genFoo: Gen[Foo] = Gen.resultOf(Foo)

  implicit val arbFoo = Arbitrary(genFoo)

  val genCustomFoo: Gen[Foo] = {
    Arbitrary.arbitrary[Foo].map { foo =>
      foo.copy(bar = foo.bar.copy(baz = Baz("custom for testing")))
    }
  }

  property("arbFoo") = {
    Prop.forAll { foo: Foo  =>
      foo.bar.baz.thing != "custom for testing"
    }
  }

  property("genCustomFoo") = {
    Prop.forAll(genCustomFoo) { foo: Foo  =>
      foo.bar.baz.thing ?= "custom for testing"
    }
  }
}

使用用于理解的问题是在处理真正大/深的对象时。手动为每个“字段”提供值可能无法扩展到多个测试。我已更新了答案,以包括一个更相关的答案,因为@Dima建议测试涵盖“各个方面”例如,我可能不需要/不关心设置一个成员的地址,而我所做的只是检查他们的“汽车信息”以进行特定测试。测试的重点是“汽车方面”。另一个测试的重点是地址部分,即断言将不同。如果我必须为每个测试用例设置巨型对象,很难知道“什么”是与测试相关的。因此,需要有数据投入到“逻辑工作”中,但“不关心”它。只关心“聚焦元素”可以这么说。在检查了链接后-它似乎可以得到可变部分,但没有随机数据生成部分,对吗?这是否意味着需要使用Scalacheck shapeless+Lense来获得我想要的?是的,Lense只是访问深度嵌套的结构,与数据生成无关(我仍然认为,这是完全错误的方法,尽管可能是短期内最简单的方法)。如果您只关心某些字段,而不关心其他字段,则(1)意味着您的数据结构可能设计得很糟糕,(2)通过为构造函数参数指定默认值解决了这个问题。我听到了。但我很好奇,您是否总是遇到/创建了只包含测试中需要设置的所有相关字段的数据结构?这就是为什么在.Net世界中存在类似于
AutoFixture
的东西的原因。在函数世界中,您可以也许是对的。不幸的是,这些是节俭对象。如果你设置了所有东西,你只能“将它们输入到你的测试中”——这可能是一个完全不同的问题。有很多东西是毫无理由存在的。这不是一个论点。在测试中设置节俭对象没有错