代码之家  ›  专栏  ›  技术社区  ›  user1113782

SBT测试不适用于火花测试

  •  9
  • user1113782  · 技术社区  · 7 年前

    我有一个简单的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测试”运行相同的测试时,它会失败,原因如下:

        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脚本,没有什么花哨的东西需要放在配置单元依赖项中,否则测试将无法编译:

        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,德比网。jar和derbyoptionaltools。震击器:

    权限组织。阿帕奇。德比。安全SystemPermission“引擎”、“usederbyinternals”;

    既然我没有显式安装derby(可能由spark内部使用),我该怎么做?

    5 回复  |  直到 7 年前
        1
  •  4
  •   Daimon    7 年前

    以下快速而肮脏的黑客解决了这个问题

    System.setSecurityManager(null)
    

    无论如何,因为它只与自动测试相关,也许它毕竟没有那么大问题;)

        2
  •  1
  •   Ori Popowski    5 年前

    如果你想找一条更干净的路 build.sbt :

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

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

        3
  •  0
  •   hermi zied    7 年前

    默认情况下,配置单元使用两个元存储,第一个是一个元存储服务,第二个是数据库,默认情况下称为metastore\u db,它使用derby。因此,我认为您必须使用hive安装和配置derby。 但我还没有看到您的代码中使用了hive。 我希望我的回答对你有帮助

        4
  •  0
  •   user1113782    7 年前

    在测试类中添加此行以禁用配置单元对我很有用

          override implicit def enableHiveSupport: Boolean = false
    

    这里有:

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

        5
  •  0
  •   Eugene Lopatkin    6 年前

    我通过排除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
      })
    

    它不使用黑客。只需手动解决依赖关系。