如何为SBT插件添加外部依赖项并使其在项目和插件类路径中可用?:
具体来说,我有一个简单的插件,应该运行我们的TestNG测试套件并进行一些后期处理.这是一个简化版本:
import sbt._
import java.util.ArrayList
import Keys._
import org.testng._
object RunTestSuitesPlugin extends Plugin {
lazy val runTestSuites = TaskKey[Unit]("run-test-suites", "runs TestNG test suites")
lazy val testSuites = SettingKey[Seq[String]]("test-suites", "list of test suites to run")
class JavaListWrapper[T](val seq: Seq[T]) {
def toJavaList = seq.foldLeft(new java.util.ArrayList[T](seq.size)) { (al, e) => al.add(e); al }
}
implicit def listToJavaList[T](l: Seq[T]) = new JavaListWrapper(l)
def runTestSuitesTask = runTestSuites <<= (target, streams, testSuites) map {
(targetDirectory, taskStream, suites) =>
import taskStream.log
log.info("running test suites: " + suites)
runSuites(suites)
}
private def runSuites(testSuites: Seq[String]) = {
var tester = new TestNG
tester.setTestSuites(testSuites.toJavaList)
tester.run()
}
def testSuiteSettings = {
inConfig(Compile)(Seq(
runTestSuitesTask,
testSuites := Seq("testsuites/mysuite.xml"),
libraryDependencies += "org.testng" % "testng" % "5.14"))
}
}
问题是,当我将这个插件添加到一个项目并使用run-test-suites运行它时,它失败了java.lang.NoClassDefFoundError:org / testng / TestNG,即使show full-classpath显示testng.jar在类路径.
因此,在执行插件时使用的类路径与我项目中的类路径不同,所以如何在两个地方都出现插件依赖?
最佳答案 我会尝试一个答案,但我不太熟悉sbt的内部细节.
通常,构建系统的路径(与程序相对)在项目下,如here所述.这通常位于project / plugins.sbt中.听起来很正确,因为你没有理由认为你开发的应用程序应该关注构建系统使用的库,而不是相反.
当您的插件运行应用程序代码时,可能不是那么简单,并且可能存在类路径/类加载器问题.我不确定它会起作用.通常,您的插件应该实现测试框架而不是定义自己的任务. Documentation of testing对于sbt是有限的.
测试框架应该在0700中实现org.scalatools.testing.Framework.您的构建将在添加后将其考虑在内
testFrameworks += new TestFramework("full.class.name")
当你运行普通的测试命令时,它让每个框架都能识别它所处理的测试类(两个可用的标准:扩展一些基类或有一些注释)并运行它们.框架在构建中运行,它被赋予一个类加载器来访问应用程序代码.
您可以查看the framework implementation for junit(随附sbt).还有一个TestNG implementation.我不知道,根据它的文档,它有点非正统,希望它对你有用.