【问题标题】:Spark Unit Testing: How to initialize sc only once for all the Suites using FunSuiteSpark 单元测试:如何使用 FunSuite 为所有套件仅初始化一次 sc
【发布时间】:2020-02-18 21:46:25
【问题描述】:

我想编写 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 test 我可以看到两个测试都调用了 println 语句 baseClass。显然,当为 A 和 B 类创建对象时,Abstract 基类被调用。 但是我们如何才能实现我的目的,即当所有测试用例都运行时,火花上下文只被初始化一次

【问题讨论】:

    标签: scala apache-spark spark-streaming scalatest


    【解决方案1】:

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

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

    【讨论】:

    • 我已经提供了类似的答案并删除了。基于 cmets(“不认为这是有效的,它显示了相同的结果。正在从两个测试类调用 print 语句”)我相信 OP 希望所有套件都具有相同的上下文。跨度>
    • 是的。使用 Option2: sbt test 后会打印两次语句。初始化火花上下文 初始化火花上下文 杀死火花上下文 杀死火花上下文
    • 是的..我相信我的项目中的两个类创建了两个不同的套件。所以我的要求是在不同的套件之间共享 sc。已相应地编辑了我的问题
    【解决方案2】:

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

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

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

    希望对你有帮助!

    【讨论】:

    • 注意:使用 spark-testing-base 在某些时候会让你使用 hive,这可能不是你想要的。
    【解决方案3】:

    如果您真的想在 套件 之间共享上下文 - 您必须将其设为静态。然后您可以使用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
    }
    

    【讨论】:

    • 谢谢 .. 偏离原始问题。有什么办法可以将这两个类 A 和 B 添加到一个套件中??
    • 一个扩展 FunSuite 的类 一个套件.. 所以我不知道怎么做。您可以在一个套件类中创建许多测试来测试多个类 - 不确定通过分离 A 和 B 来实现什么区别。
    • 我想在不同的测试类中测试不同的src类。所以想创建两个不同的测试类 A 和 B
    • 这是有道理的,但是 - 为什么要坚持单套房?无论如何,这确实是题外话,请说明您的原始问题是否得到了回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    相关资源
    最近更新 更多