Spark 单元测试:如何使用 FunSuite 为所有套件仅初始化一次 sc

Spark Unit Testing: How to initialize sc only once for all the Suites using FunSuite

我想编写 spark 单元测试用例,我正在使用 FunSuite。 但我希望我的 sparkContext 只初始化一次,由所有套件使用,然后在所有套件完成时被杀死。

abstract class baseClass extends FunSuite with BeforeAndAfter{
  before {
    println("initialize spark context")
  }
  after {
    println("kill spark context")
  }

}



@RunWith(classOf[JUnitRunner])
class A extends baseClass{
test("for class A"){
//assert
}

@RunWith(classOf[JUnitRunner])
class B extends baseClass{
test(for class b){
//assert
}
}

但是当我 运行 sbt 测试 我可以看到两个测试都调用了 println 语句 baseClass。 Obsiously 当为 类 A 和 B 创建对象时,抽象 基类被调用。 但是我们如何才能实现我的目的,即在所有测试用例都是 运行

时,spark 上下文只被初始化一次

选项 1:使用出色的 https://github.com/holdenk/spark-testing-base 库,它可以做到这一点(并提供许多其他好东西)。按照自述文件进行操作后,它就像混入 SharedSparkContext 而不是 baseClass 一样简单,您将有一个 sc: SparkContext 值可以在您的测试中使用

选项 2:要自己做,您需要混合 BeforeAndAfterAll 而不是 BeforeAndAfter,并实施 beforeAllafterAll,这正是上面提到的 SharedSparkContext 所做的。

如果您真的想在 套件 之间共享上下文 - 您必须将其设为静态。然后您可以使用 lazy 值使其在首次使用时启动。至于关闭它 - 您可以将其留给每次创建上下文时创建的自动 Shutdown 挂钩。

它看起来像:

abstract class SparkSuiteBase extends FunSuite {
    lazy val sparkContext = SparkSuiteBase.sparkContext
}

// putting the Spark Context inside an object allows reusing it between tests
object SparkSuiteBase {
    private lazy val sparkContext = ??? // create the context here
}

我强烈建议使用 spark-testing-base 库以便在测试期间管理 sparkContext 或 sparkSession 的生命周期。 您不必通过覆盖 beforeAllafterAll 方法和管理 sparkSession/sparkContext.

的生命周期来污染您的测试

您可以通过重写以下方法为所有测试共享一个 sparkSession/sparkContextdef reuseContextIfPossible: Boolean = true

更多详情:https://github.com/holdenk/spark-testing-base/wiki/SharedSparkContext

希望对您有所帮助!