对于基本的数据框创建示例,我应该如何在Spark中编写单元测试?

时间:2017-08-08 15:56:33

标签: scala unit-testing apache-spark intellij-idea

我正在努力使用Spark提供的示例文本文件编写用于创建数据框的基本单元测试,如下所示。

class dataLoadTest extends FunSuite with Matchers with BeforeAndAfterEach {

private val master = "local[*]"
private val appName = "data_load_testing"

private var spark: SparkSession = _

override def beforeEach() {
  spark = new SparkSession.Builder().appName(appName).getOrCreate()
}

import spark.implicits._

 case class Person(name: String, age: Int)

  val df = spark.sparkContext
      .textFile("/Applications/spark-2.2.0-bin-hadoop2.7/examples/src/main/resources/people.txt")
      .map(_.split(","))
      .map(attributes => Person(attributes(0),attributes(1).trim.toInt))
      .toDF()

  test("Creating dataframe should produce data from of correct size") {
  assert(df.count() == 3)
  assert(df.take(1).equals(Array("Michael",29)))
}

override def afterEach(): Unit = {
  spark.stop()
}

}

我知道代码本身是有效的(来自spark.implicits._ .... toDF()),因为我已经在Spark-Scala shell中验证了这一点,但是在测试类中我遇到了很多错误; IDE无法识别'import spark.implicits._或toDF(),因此测试不会运行。

我正在使用SparkSession,它会自动创建SparkConf,SparkContext和SQLContext。

我的代码只使用Spark repo中的示例代码。

为什么这不起作用的任何想法?谢谢!

NB。我已经看过StackOverflow上的Spark单元测试问题,就像这样:How to write unit tests in Spark 2.0+? 我用它来编写测试,但我仍然遇到错误。

我正在使用Scala 2.11.8和Spark 2.2.0与SBT和IntelliJ。这些依赖项正确包含在SBT构建文件中。运行测试时的错误是:

错误:(29,10)值toDF不是org.apache.spark.rdd.RDD [dataLoadTest.this.Person]的成员 可能的原因:在'值toDF'之前可能缺少分号?         .toDF()

错误:(20,20)需要稳定的标识符,但找到了dataLoadTest.this.spark.implicits。       import spark.implicits ._

IntelliJ无法识别导入spark.implicits._或.toDF()方法。

我已导入: import org.apache.spark.sql.SparkSession import org.scalatest。{BeforeAndAfterEach,FlatSpec,FunSuite,Matchers}

2 个答案:

答案 0 :(得分:5)

您需要将Private Sub Open_Click() Dim recordID As Integer recordID = Me.ID 'Debug.Print Me.ID 'Stop If Me.ID <> "" Then DoCmd.OpenForm "Add Task", acNormal, , "ID=" & recordID, acFormEdit Else DoCmd.OpenForm "Add Task", acNormal, , , acFormAdd End If End Sub 分配给sqlContext val才能正常工作。由于implicitssparkSessionvar无法使用

所以你需要做

implicits

此外,您可以为测试编写函数,以便您的测试类看起来如下

val sQLContext = spark.sqlContext
import sQLContext.implicits._

答案 1 :(得分:1)

有许多用于单元测试spark的库,其中一个最常用的是

spark-testing-base 作者:Holden Karau

此库的所有内容均为sc,因为下面的SparkContext是一个简单示例

class TestSharedSparkContext extends FunSuite with SharedSparkContext {

  val expectedResult = List(("a", 3),("b", 2),("c", 4))

  test("Word counts should be equal to expected") {
    verifyWordCount(Seq("c a a b a c b c c"))
  }

  def verifyWordCount(seq: Seq[String]): Unit = {
    assertResult(expectedResult)(new WordCount().transform(sc.makeRDD(seq)).collect().toList)
  }
}

在这里,每件事都准备好sc作为SparkContext

另一种方法是创建TestWrapper并使用多个testcases,如下所示

import org.apache.spark.sql.SparkSession

trait TestSparkWrapper {

  lazy val sparkSession: SparkSession = 
    SparkSession.builder().master("local").appName("spark test example ").getOrCreate()

}

使用此TestWrapper对所有tests进行Scala测试,并使用BeforeAndAfterAllBeforeAndAfterEach

希望这有帮助!