使用SQLContext暗示Spark中的单元测试

时间:2016-09-09 10:00:54

标签: scala apache-spark

我正在尝试在Spark中运行多个单元测试,并从源代码中复制(并略微调整)该位:

import org.apache.spark.sql.SQLContext
import org.apache.spark.{SparkConf, SparkContext}
import org.scalatest.{BeforeAndAfterAll, Suite}

trait SharedSparkContext extends BeforeAndAfterAll {
  self: Suite =>

  @transient private var _sc: SparkContext = _
  @transient private var _sqlContext: SQLContext = _

  def sc: SparkContext = _sc
  def sqlContext: SQLContext = _sqlContext

  private var conf = new SparkConf(false)

  override def beforeAll() {
    super.beforeAll()
    _sc = new SparkContext("local[*]", "Test Suites", conf)
    _sqlContext = new SQLContext(_sc)
  }

  override def afterAll() {
    try {
      LocalSparkContext.stop(_sc)
      _sc = null
    } finally {
      super.afterAll()
    }
  }
}

只需从源中复制带有伴随对象的LocalSparkContext类。

我考虑过如下使用它,它告诉我stable identifier required,因为def sqlContext没有成员implicits

class MySuite extends FlatSpec with SharedSparkContext {
  import sqlContext.implicits._
  // ...
}

我尝试用以下内容替换它,但这给了我空指针异常:

class MySuite extends FlatSpec with SharedSparkContext {
  val sqlCtxt = sqlContext
  import sqlCtxt.implicits._
  // ...
}

我使用的是Spark 1.4.1,我设置了parallelExecution in test := false

如何才能使其工作(不使用其他软件包)?

1 个答案:

答案 0 :(得分:2)

您可以使用包含所有变量的简单对象,而不是使用特征,这是我为测试所做的事情:

object TestConfiguration extends Serializable {

  private val sparkConf = new SparkConf()
      .setAppName("Tests")
      .setMaster("local")

  private lazy val sparkContext = new SparkContext(sparkConf)

  private lazy val sqlContext = new SQLContext(sparkContext)

  def getSqlContext() = {
    sqlContext
  }  

}  

然后,您将能够在测试套件中使用sqlContext。

class MySuite extends FlatSpec with SharedSparkContext {
  val sqlCtxt = TestConfiguration.getSqlContext
  import sqlCtxt.implicits._
  // ...
}