我在JUnit中进行了一些测试,我需要检查两个Spark RDD的相等性。
我想到的方法就是:
JavaRDD<SomeClass> expResult = ...;
JavaRDD<SomeClass> result = ...;
assertEquals(expResult.collect(), result.collect());
有没有比这更好的方法?
答案 0 :(得分:5)
如果预期结果相当小,则最适合collect
RDD数据并在本地进行比较(就像您已经写好的那样)。
如果在测试中使用足够大的数据集是必要的,那么几乎没有其他可能性:
免责声明:我对Spark Java API不够熟悉,因此我将在Scala中编写更多示例代码。我希望它不会成为一个问题,因为它可能要么用Java重写,要么转换成几个从Java代码调用的实用函数。
此方法仅在RDD中元素的顺序定义良好(即RDD已排序)时才可用。
val diff = expResult
.zip(result)
.collect { case (a, b) if a != b => a -> b }
.take(100)
diff
数组最多包含100个差异对。如果RDD足够大,并且您希望从本地diff
获取所有项目,则可以使用toLocalIterator
方法。最好不要使用collect
方法,因为你可以运行OOM。
这种方法可能是最快的,因为它不需要随机播放,但只有在RDD中的分区顺序和分区中的项目顺序得到很好定义的情况下才可以使用它。
此方法可用于测试result
RDD是否包含指定的(可能是非唯一的)值而没有任何特定顺序
val diff = expResult.map(_ -> 1)
.cogroup(result.map(_ -> 1))
.collect { case (a, (i1, i2)) if i1.sum != i2.sum => a -> (i1.sum - i2.sum) }
.take(100)
diff
数组将包含差异值以及金额之间的差异。
例如:
expResult
包含某个值的单个实例且result
不包含该值,则该数字将为+1
; result
包含3个其他值的实例,而expResult
只包含1,则该数字将为-2
。这种方法比其他选项更快(即相互减少RDD),因为它只需要一次shuffle。
答案 1 :(得分:0)
就我而言,使用Spark进入Java,只需使用collect方法就行了。 assertEquals的结果总是错误的。
所以这个测试:
assertEquals(
this.fooExpectedRddTest.collect(),
this.fooServiceTest.getRdd().collect()
);
生成此结果:
FooServiceTest.getRdd:143 expected:
scala.collection.convert.Wrappers$SeqWrapper<[
{"a":1,"b":2,"c":1496405614},
{"a":1,"b":3,"c":1496243614},
{"a":2,"b":2,"c":1496416414}
]>
but was:
scala.collection.convert.Wrappers$SeqWrapper<[
{"a":1,"b":2,"c":1496405614},
{"a":1,"b":3,"c":1496243614},
{"a":2,"b":2,"c":1496416414}
]>
我处理这个问题的方法是将它们转换成更容易比较的东西
List<Tuple3<Integer,Integer,Double>> expectedList = this.fooExpectedRddTest.map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
List<Tuple3<Integer,Integer,Double>> receivedList = this.fooServiceTest.getRdd().map(
(Foo foo) -> {
return new Tuple3<Integer,Integer,Double>(
foo.getA(),
foo.getB(),
foo.getC()
);
}
).collect();
assertEquals(
expectedList,
receivedList
);