【问题标题】:SBT test does not work for spark testSBT 测试不适用于火花测试
【发布时间】:2018-06-09 01:15:57
【问题描述】:

我有一个简单的 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"

Google 搜索将我指向 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 内部使用的),我该怎么做?

【问题讨论】:

  • 升级 2.2.0 -> 2.2.1 后出现同样的问题
  • 你能运行spark-shell并执行spark.range(5).show吗?这对你有用吗?
  • 这按预期工作-我得到了+---+ |编号| +---+ | 0| | 1| | 2| | 3| | 4| +---+
  • 这是相同的火花票:issues.apache.org/jira/browse/SPARK-22918

标签: apache-spark sbt derby


【解决方案1】:

默认情况下,hive 使用两个 Metastore,第一个是 meta store 服务,第二个是默认调用的数据库 metastore_db,它使用 derby。所以我认为您必须使用 hive 安装和配置 derby。 但我还没有看到你的代码中使用了蜂巢。 希望我的回答能帮到你

【讨论】:

  • 对,必须使用配置单元,否则测试框架(Dataframesuitebase)无法编译。我没有使用蜂巢。
【解决方案2】:

遵循快速而肮脏的 hack 解决了问题

System.setSecurityManager(null)

无论如何,它只与自动化测试有关,也许它毕竟不是那么成问题;)

【讨论】:

  • 这为我解决了这个问题——是的,因为它是一个自动化测试,所以很好。但更大的问题仍然存在。
  • 最终使用:覆盖隐式 def enableHiveSupport:Boolean=false 效果很好
  • 只有在您不使用 Hive 功能时才会起作用 :)
【解决方案3】:

在测试类中添加这一行来禁用 hive 对我有用

      override implicit def enableHiveSupport: Boolean = false

在这里得到它:

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

【讨论】:

  • 只要您在测试期间不需要实际的 Hive 仿真就可以了。在某些情况下,您需要启用配置单元支持并且仍然能够运行测试:)
【解决方案4】:

我已通过排除错误版本的 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
  })

它不使用黑客。只是手动依赖解析。

【讨论】:

    【解决方案5】:

    如果您正在寻找一种更清洁的方式,那么请在build.sbt

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

    这会将修复应用到所有文件中的所有测试,而不会触及测试代码。

    【讨论】:

    • 由于某种原因这不起作用。当我在所有测试中手动添加该行时,它可以工作
    • 对于 SBT 的更新版本:Test / testOptions += Tests.Setup(() => System.setSecurityManager(null))
    猜你喜欢
    • 1970-01-01
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多