SBT测试不适用于火花测试

时间:2017-12-28 13:25:38

标签: apache-spark sbt derby

我有一个简单的spark函数来测试DF窗口:

    import org.apache.spark.sql.{DataFrame, SparkSession}

    object ScratchPad {

      def main(args: Array[String]): Unit = {
        val spark = SparkSession.builder().master("local[*]").getOrCreate()
        spark.sparkContext.setLogLevel("ERROR")
        get_data_frame(spark).show()
      }

      def get_data_frame(spark: SparkSession): DataFrame = {
        import spark.sqlContext.implicits._
        val hr = spark.sparkContext.parallelize(List(
          ("Steinbeck", "Sales", 100),
          ("Woolf", "IT", 99),
          ("Wodehouse", "Sales", 250),
          ("Hemingway", "IT", 349)
        )
        ).toDF("emp", "dept", "sal")

        import org.apache.spark.sql.expressions.Window
        import org.apache.spark.sql.functions._

        val windowspec = Window.partitionBy($"dept").orderBy($"sal".desc)


        hr.withColumn("rank", row_number().over(windowspec))

      }
    }

我写了一个类似的测试:

    import com.holdenkarau.spark.testing.DataFrameSuiteBase
    import org.apache.spark.sql.Row
    import org.apache.spark.sql.types._
    import org.scalatest.FunSuite

    class TestDF extends FunSuite with DataFrameSuiteBase  {

      test ("DFs equal") {
        val expected=sc.parallelize(List(
          Row("Wodehouse","Sales",250,1),
          Row("Steinbeck","Sales",100,2),
          Row("Hemingway","IT",349,1),
          Row("Woolf","IT",99,2)
        ))

        val schema=StructType(
          List(
          StructField("emp",StringType,true),
          StructField("dept",StringType,true),
          StructField("sal",IntegerType,false),
          StructField("rank",IntegerType,true)
          )
        )

        val e2=sqlContext.createDataFrame(expected,schema)
        val actual=ScratchPad.get_data_frame(sqlContext.sparkSession)
        assertDataFrameEquals(e2,actual)
      }

}

当我右键单击intellij中的类并单击"运行"时工作正常。 当我使用" sbt test"进行相同的测试时,它会失败并显示以下内容:

    java.security.AccessControlException: access denied 
    org.apache.derby.security.SystemPermission( "engine", 
    "usederbyinternals" )
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
        at java.security.AccessController.checkPermission(AccessController.java:884)
        at org.apache.derby.iapi.security.SecurityUtil.checkDerbyInternalsPrivilege(Unknown Source)
        ...

这是我的SBT脚本,没什么好看的 - 必须放入hive依赖,否则测试不会编译:

    name := "WindowingTest"

    version := "0.1"

    scalaVersion := "2.11.5"


    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.2.1"
    libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.2.1"
    libraryDependencies += "org.apache.spark" %% "spark-hive" % "2.2.1"
    libraryDependencies += "com.holdenkarau" %% "spark-testing-base" % "2.2.0_0.8.0" % "test"

谷歌搜索指向derby-6648(https://db.apache.org/derby/releases/release-10.12.1.1.cgi

说: 需要更改应用程序 在SecurityManager下运行Derby的用户必须编辑策略文件,并为derby.jar,derbynet.jar和derbyoptionaltools.jar授予以下附加权限:

权限org.apache.derby.security.SystemPermission" engine"," usederbyinternals";

由于我没有明确安装derby(内部可能由spark使用),我该怎么做?

5 个答案:

答案 0 :(得分:2)

快速而肮脏的黑客解决问题

System.setSecurityManager(null)

无论如何,因为它与自动化测试有关,但它毕竟不是问题;)

答案 1 :(得分:1)

如果您正在寻找一种更清洁的方法,请在build.sbt内进行

test in Test := {
  System.setSecurityManager(null) // SPARK-22918
  (test in Test).value
}

这会将修复程序应用于所有文件中的所有测试,而无需触及测试代码。

答案 2 :(得分:0)

默认情况下,hive使用两个Metastores第一个元存储服务,第二个默认情况下使用默认情况下的metaore_db调用数据库,它使用derby。所以我认为你必须使用配置单元安装和配置derby。 但是我还没有在代码中看到使用hive。 我希望我的回答可以帮助你

答案 3 :(得分:0)

在测试类中添加此行以禁用hive为我工作

      override implicit def enableHiveSupport: Boolean = false

在这里:

https://github.com/holdenk/spark-testing-base/issues/148

答案 4 :(得分:0)

我已经通过排除错误版本的Derby并在build.sbt中包含权利来解决了这个问题:

project.settings(libraryDependencies ++= Seq(
"org.apache.derby" % "derby" % "10.11.1.1" % Test)
  .map {
      case module if module.name.contains("spark") => module.excludeAll(
          ExclusionRule(organization = "org.apache.derby"))
      case module => module
  })

它不使用黑客攻击。只需手动依赖解析。