gpt4 book ai didi

scala - SBT 测试任务如何管理类路径以及如何从 SBT 测试正确启动 Java 进程

转载 作者:行者123 更新时间:2023-12-04 08:31:43 26 4
gpt4 key购买 nike

在我的 Scala 测试之一中,使用 ProcessBuilder ,我在不同的 JVM 中启动了 3 个 Apache Spark 流应用程序。 (两个或多个 Spark 流应用程序不能在同一个 JVM 中共存。)一个 Spark 应用程序处理数据并摄取到 Apache Kafka,其他应用程序读取。此外,测试涉及写入 NoSQL 数据库。

使用时 ProcessBuilder ,Spark 应用程序的类路径是使用以下方法设置的:
val classPath = System.getProperty("java.class.path")
在 IntelliJ 中运行测试按预期工作,但在 CI 系统上,测试由 SBT 的测试任务调用。 java.class.path在后一种情况下,将仅为 sbt.jar ,因此子 JVM 以 NoClassFoundException 退出,再次,正如预期的那样。 :-)

我正在寻找一种使用测试实际使用的相同类路径从 SBT 测试“跨越”JVM 的方法。例如,如果在项目 core 中调用测试,项目的类路径core应提供给 Spark 应用程序启动的子 JVM。不幸的是,我不知道如何在 SBT 任务中检索正确的类路径 - 然后可以将其提供给子 JVM。

最佳答案

Tests.Setup 可用于访问 SBT 中的类路径:

testOptions in Test += Tests.Setup { classLoader =>
// give Spark classpath via classLoader
}

例如,在我的机器上 Tests.Setup(classLoader => println(classLoader))
> test
ClasspathFilter(
parent = URLClassLoader with NativeCopyLoader with RawResources(
urls = List(/home/mario/sandbox/sbt/so-classpath/target/scala-2.12/test-classes, /home/mario/sandbox/sbt/so-classpath/target/scala-2.12/classes, /home/mario/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.4.jar, /home/mario/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.5.jar, /home/mario/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.5.jar, /home/mario/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.4.jar, /home/mario/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.6.jar),
parent = DualLoader(a = java.net.URLClassLoader@3fcb37f1, b = java.net.URLClassLoader@271053e1),
resourceMap = Set(app.class.path, boot.class.path),
nativeTemp = /tmp/sbt_741bc913/sbt_c770779a
)
root = sun.misc.Launcher$AppClassLoader@33909752
cp = Set(/home/mario/.ivy2/cache/jline/jline/jars/jline-2.14.5.jar, /home/mario/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.4.jar, /home/mario/.ivy2/cache/org.scala-lang/scala-compiler/jars/scala-compiler-2.12.4.jar, /home/mario/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.6.jar, /home/mario/sandbox/sbt/so-classpath/target/scala-2.12/classes, /home/mario/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.5.jar, /home/mario/.sbt/boot/scala-2.10.7/org.scala-sbt/sbt/0.13.17/test-interface-1.0.jar, /home/mario/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.5.jar, /home/mario/sandbox/sbt/so-classpath/target/scala-2.12/test-classes, /home/mario/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.4.jar)
)

我们在哪里看到
.../target/scala-2.12/test-classes
.../target/scala-2.12/classes

存在。

另一方面,要从测试本身中检索类路径:
val classLoader = this.getClass.getClassLoader
// give Spark classpath via classLoader

例如,在我的机器上, println(classLoader)在以下测试中给出
class CubeCalculatorTest extends FunSuite {
test("CubeCalculator.cube") {
val classLoader = this.getClass.getClassLoader
println(classLoader)
assert(CubeCalculator.cube(3) === 27)
}
}

打印
URLClassLoader with NativeCopyLoader with RawResources(
urls = List(/home/mario/sandbox/sbt/so-classpath/target/scala-2.12/test-classes, /home/mario/sandbox/sbt/so-classpath/target/scala-2.12/classes, /home/mario/.ivy2/cache/org.scala-lang/scala-library/jars/scala-library-2.12.4.jar, /home/mario/.ivy2/cache/org.scalatest/scalatest_2.12/bundles/scalatest_2.12-3.0.5.jar, /home/mario/.ivy2/cache/org.scalactic/scalactic_2.12/bundles/scalactic_2.12-3.0.5.jar, /home/mario/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.12.4.jar, /home/mario/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12/bundles/scala-xml_2.12-1.0.6.jar),
parent = DualLoader(a = java.net.URLClassLoader@6307eb76, b = java.net.URLClassLoader@271053e1),
resourceMap = Set(app.class.path, boot.class.path),
nativeTemp = /tmp/sbt_fa64d1a1/sbt_66bd50e2
)

我们又在哪里可以看到
.../target/scala-2.12/test-classes
.../target/scala-2.12/classes

存在。

实际将类路径传递给 ProcessBuilder 在测试中:
import java.net.URLClassLoader
import sys.process._

class CubeCalculatorTest extends FunSuite {
test("CubeCalculator.cube") {
val classLoader = this.getClass.getClassLoader
val classpath = classLoader.asInstanceOf[URLClassLoader].getURLs.map(_.getFile).mkString(":")
s"java -classpath $classpath MyExternalApp".!
...
}
}

关于scala - SBT 测试任务如何管理类路径以及如何从 SBT 测试正确启动 Java 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49989147/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com