1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-27 00:38:11 -07:00

Made test runners into contributors.

This commit is contained in:
Cedric Beust 2015-11-28 06:51:00 -08:00
parent 6630f55197
commit b700e94b5f
13 changed files with 125 additions and 63 deletions

View file

@ -1,9 +1,10 @@
package com.beust.kobalt.api package com.beust.kobalt.api
import com.beust.kobalt.TaskResult import com.beust.kobalt.TaskResult
import com.beust.kobalt.maven.IClasspathDependency
/** /**
* Plugins that can run a project (task "run") should implement this interface. * Plugins that can run a project (task "run" or "test") should implement this interface.
*/ */
interface IRunnerContributor : IContributor { interface IRunnerContributor : IContributor {
companion object { companion object {
@ -23,7 +24,7 @@ interface IRunnerContributor : IContributor {
/** /**
* Run the project. * Run the project.
*/ */
fun run(project: Project, context: KobaltContext) : TaskResult fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>) : TaskResult
} }

View file

@ -2,6 +2,9 @@ package com.beust.kobalt.internal
import com.beust.kobalt.JavaInfo import com.beust.kobalt.JavaInfo
import com.beust.kobalt.SystemProperties import com.beust.kobalt.SystemProperties
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
@ -9,11 +12,15 @@ import com.beust.kobalt.misc.log
import java.io.File import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
abstract class GenericTestRunner(open val project: Project, open val classpath: List<IClasspathDependency>) { abstract class GenericTestRunner : IRunnerContributor {
abstract val mainClass: String abstract val mainClass: String
abstract val args: List<String> abstract fun args(project: Project, classpath: List<IClasspathDependency>) : List<String>
protected fun findTestClasses(): List<String> { override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>)
= TaskResult(runTests(project, context, classpath))
protected fun findTestClasses(project: Project, classpath: List<IClasspathDependency>): List<String> {
val path = KFiles.joinDir(project.directory, project.buildDirectory, KFiles.TEST_CLASSES_DIR) val path = KFiles.joinDir(project.directory, project.buildDirectory, KFiles.TEST_CLASSES_DIR)
val result = KFiles.findRecursively(File(path), arrayListOf(File(".")), { val result = KFiles.findRecursively(File(path), arrayListOf(File(".")), {
file -> file.endsWith(".class") file -> file.endsWith(".class")
@ -39,9 +46,10 @@ abstract class GenericTestRunner(open val project: Project, open val classpath:
/** /**
* @return true if all the tests passed * @return true if all the tests passed
*/ */
fun runTests() : Boolean { fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>) : Boolean {
val jvm = JavaInfo.create(File(SystemProperties.javaBase)) val jvm = JavaInfo.create(File(SystemProperties.javaBase))
val java = jvm.javaExecutable val java = jvm.javaExecutable
val args = args(project, classpath)
if (args.size > 0) { if (args.size > 0) {
val allArgs = arrayListOf<String>().apply { val allArgs = arrayListOf<String>().apply {
add(java!!.absolutePath) add(java!!.absolutePath)

View file

@ -1,12 +1,19 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency import com.beust.kobalt.maven.IClasspathDependency
public class JUnitRunner(override val project: Project, override val classpath: List<IClasspathDependency>) public class JUnitRunner() : GenericTestRunner() {
: GenericTestRunner(project, classpath) {
override val mainClass = "org.junit.runner.JUnitCore" override val mainClass = "org.junit.runner.JUnitCore"
override val args = findTestClasses()
override fun runAffinity(project: Project, context: KobaltContext) =
if (project.testDependencies.any { it.id.contains("junit")}) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY
else 0
override fun args(project: Project, classpath: List<IClasspathDependency>) = findTestClasses(project, classpath)
} }

View file

@ -7,7 +7,9 @@ import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.ExportedProjectProperty import com.beust.kobalt.api.annotation.ExportedProjectProperty
import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.maven.* import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.log import com.beust.kobalt.misc.log
@ -55,33 +57,18 @@ abstract class JvmCompilerPlugin @Inject constructor(
addVariantTasks(project, "compile", runTask = { taskCompile(project) }) addVariantTasks(project, "compile", runTask = { taskCompile(project) })
} }
/**
* @return the test dependencies for this project, including the contributors.
*/
protected fun testDependencies(project: Project) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(makeOutputDir(project).absolutePath))
result.add(FileDependency(makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies, testDependencies,
testProvidedDependencies).forEach {
result.addAll(dependencyManager.calculateDependencies(project, context, projects(), it))
}
}
val result2 = dependencyManager.reorderDependencies(result)
return result2
}
@Task(name = TASK_TEST, description = "Run the tests", runAfter = arrayOf("compile", "compileTest")) @Task(name = TASK_TEST, description = "Run the tests", runAfter = arrayOf("compile", "compileTest"))
fun taskTest(project: Project) : TaskResult { fun taskTest(project: Project) : TaskResult {
lp(project, "Running tests") lp(project, "Running tests")
val success =
if (project.testDependencies.any { it.id.contains("testng")} ) { val runContributor = context.pluginInfo.testRunnerContributors.maxBy { it.runAffinity(project, context)}
TestNgRunner(project, testDependencies(project)).runTests() if (runContributor != null && runContributor.runAffinity(project, context) > 0) {
return runContributor.run(project, context, dependencyManager.testDependencies(project, context,
projects()))
} else { } else {
JUnitRunner(project, testDependencies(project)).runTests() log(2, "Couldn't find a test runner for project ${project.name}, not running any tests")
return TaskResult()
} }
return TaskResult(success)
} }
@Task(name = TASK_CLEAN, description = "Clean the project", runBefore = arrayOf("compile")) @Task(name = TASK_CLEAN, description = "Clean the project", runBefore = arrayOf("compile"))
@ -94,14 +81,6 @@ abstract class JvmCompilerPlugin @Inject constructor(
return TaskResult() return TaskResult()
} }
protected fun makeOutputDir(project: Project) : File = makeDir(project, KFiles.CLASSES_DIR)
protected fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
private fun makeDir(project: Project, suffix: String) : File {
return File(project.directory, project.buildDirectory + File.separator + suffix).apply { mkdirs() }
}
/** /**
* Copy the resources from a source directory to the build one * Copy the resources from a source directory to the build one
*/ */
@ -120,7 +99,7 @@ abstract class JvmCompilerPlugin @Inject constructor(
if (sourceDirs.size > 0) { if (sourceDirs.size > 0) {
lp(project, "Copying $sourceSet resources") lp(project, "Copying $sourceSet resources")
val absOutputDir = File(KFiles.joinDir(project.directory, project.buildDirectory!!, outputDir)) val absOutputDir = File(KFiles.joinDir(project.directory, project.buildDirectory, outputDir))
sourceDirs.map { File(project.directory, it) }.filter { sourceDirs.map { File(project.directory, it) }.filter {
it.exists() it.exists()
} .forEach { } .forEach {

View file

@ -62,8 +62,11 @@ class KobaltPluginXml {
@XmlElement(name = "build-directory-interceptors") @JvmField @XmlElement(name = "build-directory-interceptors") @JvmField
var buildDirectoryInterceptors: ClassNameXml? = null var buildDirectoryInterceptors: ClassNameXml? = null
@XmlElement(name = "run-contributors") @JvmField @XmlElement(name = "runner-contributors") @JvmField
var runContributors: ClassNameXml? = null var runnerContributors: ClassNameXml? = null
@XmlElement(name = "test-runner-contributors") @JvmField
var testRunnerContributors: ClassNameXml? = null
} }
class ContributorXml { class ContributorXml {
@ -91,7 +94,8 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
val compilerInterceptors = arrayListOf<ICompilerInterceptor>() val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoriesIncerceptor>() val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoriesIncerceptor>()
val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryIncerceptor>() val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryIncerceptor>()
val runContributors = arrayListOf<IRunnerContributor>() val runnerContributors = arrayListOf<IRunnerContributor>()
val testRunnerContributors = arrayListOf<IRunnerContributor>()
// Future contributors: // Future contributors:
// source files // source files
@ -165,8 +169,11 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
xml.buildDirectoryInterceptors?.className?.forEach { xml.buildDirectoryInterceptors?.className?.forEach {
buildDirectoryInterceptors.add(factory.instanceOf(forName(it)) as IBuildDirectoryIncerceptor) buildDirectoryInterceptors.add(factory.instanceOf(forName(it)) as IBuildDirectoryIncerceptor)
} }
xml.runContributors?.className?.forEach { xml.runnerContributors?.className?.forEach {
runContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor) runnerContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor)
}
xml.testRunnerContributors?.className?.forEach {
testRunnerContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor)
} }
} }

View file

@ -1,16 +1,21 @@
package com.beust.kobalt.internal package com.beust.kobalt.internal
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KFiles
import java.io.File import java.io.File
public class TestNgRunner(override val project: Project, override val classpath: List<IClasspathDependency>) public class TestNgRunner() : GenericTestRunner() {
: GenericTestRunner(project, classpath) {
override val mainClass = "org.testng.TestNG" override val mainClass = "org.testng.TestNG"
override val args: List<String> override fun runAffinity(project: Project, context: KobaltContext) =
get() = arrayListOf<String>().apply { if (project.testDependencies.any { it.id.contains("testng")}) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY
else 0
override fun args(project: Project, classpath: List<IClasspathDependency>) = arrayListOf<String>().apply {
if (project.testArgs.size > 0) { if (project.testArgs.size > 0) {
addAll(project.testArgs) addAll(project.testArgs)
} else { } else {
@ -19,7 +24,7 @@ public class TestNgRunner(override val project: Project, override val classpath:
add(testngXml.absolutePath) add(testngXml.absolutePath)
} else { } else {
add("-testclass") add("-testclass")
addAll(findTestClasses()) addAll(findTestClasses(project, classpath))
} }
} }
} }

View file

@ -114,4 +114,42 @@ public class DependencyManager @Inject constructor(val executors: KobaltExecutor
return result return result
} }
/**
* @return the test dependencies for this project, including the contributors.
*/
fun dependencies(project: Project, context: KobaltContext,
projects: List<ProjectDescription>) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(KFiles.makeOutputDir(project).absolutePath))
result.add(FileDependency(KFiles.makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies).forEach {
result.addAll(calculateDependencies(project, context, projects, it))
}
}
val result2 = reorderDependencies(result)
return result2
}
/**
* @return the test dependencies for this project, including the contributors.
*/
fun testDependencies(project: Project, context: KobaltContext,
projects: List<ProjectDescription>) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(KFiles.makeOutputDir(project).absolutePath))
result.add(FileDependency(KFiles.makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies, testDependencies,
testProvidedDependencies).forEach {
result.addAll(calculateDependencies(project, context, projects, it))
}
}
val result2 = reorderDependencies(result)
return result2
}
} }

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.misc
import com.beust.kobalt.SystemProperties import com.beust.kobalt.SystemProperties
import com.beust.kobalt.api.Kobalt import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project
import com.beust.kobalt.homeDir import com.beust.kobalt.homeDir
import com.beust.kobalt.internal.build.BuildFile import com.beust.kobalt.internal.build.BuildFile
import java.io.File import java.io.File
@ -239,6 +240,14 @@ class KFiles {
} }
fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath) fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath)
fun makeDir(project: Project, suffix: String) : File {
return File(project.directory, project.buildDirectory + File.separator + suffix).apply { mkdirs() }
}
fun makeOutputDir(project: Project) : File = makeDir(project, KFiles.CLASSES_DIR)
fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
} }
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> { fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {

View file

@ -397,7 +397,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
return if (File(manifest).exists()) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0 return if (File(manifest).exists()) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0
} }
override fun run(project: Project, context: KobaltContext): TaskResult { override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): TaskResult {
val manifest = AndroidFiles.manifest(project, context) val manifest = AndroidFiles.manifest(project, context)
FileInputStream(File(manifest)).use { ins -> FileInputStream(File(manifest)).use { ins ->
// adb shell am start -n com.package.name/com.package.name.ActivityName // adb shell am start -n com.package.name/com.package.name.ActivityName

View file

@ -6,6 +6,7 @@ import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.internal.JvmCompilerPlugin import com.beust.kobalt.internal.JvmCompilerPlugin
import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.RunCommand import com.beust.kobalt.misc.RunCommand
import com.beust.kobalt.misc.warn import com.beust.kobalt.misc.warn
@ -48,15 +49,17 @@ class ApplicationPlugin @Inject constructor(val executors: KobaltExecutors,
@Task(name = "run", description = "Run the main class", runAfter = arrayOf("install")) @Task(name = "run", description = "Run the main class", runAfter = arrayOf("install"))
fun taskRun(project: Project): TaskResult { fun taskRun(project: Project): TaskResult {
val runContributor = context.pluginInfo.runContributors.maxBy { it.runAffinity(project, context)} val runContributor = context.pluginInfo.runnerContributors.maxBy { it.runAffinity(project, context)}
if (runContributor != null && runContributor.runAffinity(project, context) > 0) { if (runContributor != null && runContributor.runAffinity(project, context) > 0) {
return runContributor.run(project, context) return runContributor.run(project, context, dependencyManager.dependencies(project, context, projects()))
} else { } else {
warn("Couldn't find a runner for project ${project.name}") warn("Couldn't find a runner for project ${project.name}")
return TaskResult() return TaskResult()
} }
} }
private fun projects() = context.pluginInfo.projectContributors.flatMap { it.projects() }
private fun isFatJar(packages: List<PackageConfig>, jarName: String): Boolean { private fun isFatJar(packages: List<PackageConfig>, jarName: String): Boolean {
packages.forEach { pc -> packages.forEach { pc ->
pc.jars.forEach { jar -> pc.jars.forEach { jar ->
@ -74,7 +77,7 @@ class ApplicationPlugin @Inject constructor(val executors: KobaltExecutors,
return if (configurationFor(project) != null) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0 return if (configurationFor(project) != null) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0
} }
override fun run(project: Project, context: KobaltContext): TaskResult { override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): TaskResult {
var result = TaskResult() var result = TaskResult()
configurationFor(project)?.let { config -> configurationFor(project)?.let { config ->
if (config.mainClass != null) { if (config.mainClass != null) {

View file

@ -81,8 +81,9 @@ class JavaPlugin @Inject constructor(
val result = val result =
if (sourceFiles.size > 0) { if (sourceFiles.size > 0) {
copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST) copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST)
val buildDir = makeOutputTestDir(project) val buildDir = KFiles.makeOutputTestDir(project)
javaCompiler.compile(project, context, CompilerActionInfo(project.directory, testDependencies(project), javaCompiler.compile(project, context, CompilerActionInfo(project.directory,
dependencyManager.testDependencies(project, context, projects()),
sourceFiles, buildDir, compilerArgsFor(project))) sourceFiles, buildDir, compilerArgsFor(project)))
} else { } else {
warn("Couldn't find any tests to compile") warn("Couldn't find any tests to compile")

View file

@ -69,9 +69,9 @@ class KotlinPlugin @Inject constructor(
val result = val result =
if (sourceFiles.size > 0) { if (sourceFiles.size > 0) {
compilePrivate(project, testDependencies(project), compilePrivate(project, dependencyManager.testDependencies(project, context, projects()),
sourceFiles, sourceFiles,
makeOutputTestDir(project)) KFiles.makeOutputTestDir(project))
} else { } else {
warn("Couldn't find any test files") warn("Couldn't find any test files")
TaskResult() TaskResult()

View file

@ -37,8 +37,12 @@
<compiler-interceptors> <compiler-interceptors>
<class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name> <class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name>
</compiler-interceptors> </compiler-interceptors>
<run-contributors> <runner-contributors>
<class-name>com.beust.kobalt.plugin.application.ApplicationPlugin</class-name> <class-name>com.beust.kobalt.plugin.application.ApplicationPlugin</class-name>
<class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name> <class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name>
</run-contributors> </runner-contributors>
<test-runner-contributors>
<class-name>com.beust.kobalt.internal.JUnitRunner</class-name>
<class-name>com.beust.kobalt.internal.TestNgRunner</class-name>
</test-runner-contributors>
</kobalt-plugin> </kobalt-plugin>