代码之家  ›  专栏  ›  技术社区  ›  Freewind thk

在使用scalatest和before/after时,如何避免“null”?

  •  1
  • Freewind thk  · 技术社区  · 9 年前

    从此处开始 article about spark testing ,有一些示例代码:

    class SparkExampleSpec extends FlatSpec with BeforeAndAfter {
    
      private val master = "local[2]"
      private val appName = "example-spark"
    
      private var sc: SparkContext = _
    
      before {
        val conf = new SparkConf()
          .setMaster(master)
          .setAppName(appName)
    
        sc = new SparkContext(conf)
      }
    
      after {
        if (sc != null) {
          sc.stop()
        }
      }
      (...)
    

    它有效,但有一个可为null的变量 sc 。这是合理的,但我还是想避免。

    我尝试使用:

    private var sc: Option[SparkContext] = None
    
      before {
        sc = Some(new SparkContext(conf))
      }
    
      after {
        sc.foreach(_.stop())
      }
      (...)
    

    但问题是,我必须使用 供应链管理 Option[SparkContext] 在不像普通测试那样方便的测试中 SparkContext

    有没有办法保持测试正常运行,但我们可以使用 val sc: SparkContext ?

    (我知道在specs2中是可能的,但不知道如何在scalatest中实现,我们现在必须使用scalatest)

    1 回复  |  直到 9 年前
        1
  •  1
  •   Noah    9 年前

    您可以使用 before 只需使用 lazy val 相反,因此当第一个测试调用上下文时,上下文被初始化:

    class SparkExampleSpec extends FlatSpec with BeforeAndAfter {
    
      private val master = "local[2]"
      private val appName = "example-spark"
    
      private lazy val conf = new SparkConf()
        .setMaster(master)
        .setAppName(appName)
      private lazy val sc = new SparkContext(conf)
    
      after {
        sc.stop()
      }
    

    更新:

    所以我以前遇到过类似的事情,我们最终得到了如下的特征模式:

    trait SparkAddOn {
    
      val conf:SparkConf
    
      def withSpark(f: SparkContext => Unit) ={
        val sc: SparkContext = new SparkContext(conf)
        try{
          f(sc)
        } finally {
          sc.stop()
        }
      }
    }
    

    因此,在测试中,您只需使用“withSpark”:

    class SparkExampleSpec extends FlatSpec with SparkAddOn {
    
      private val master = "local[2]"
      private val appName = "example-spark"
    
      val conf = new SparkConf()
        .setMaster(master)
        .setAppName(appName)
    
      "test" should "do something" in withSpark { sc =>
    
      }
    }
    

    最后,我要说的是,我更喜欢Spec2而不是Scalatest,它的设计完全不同,更妙的是,很抱歉你不能切换。