module Buildr class JUnitTask < Rake::Task attr_accessor :classpath def initialize(*args) super @classpath = [] @paths = [] @include = [] @exclude = [] enhance do |task| if test_cases.empty? puts "#{name}: No tests to run" else passed, failed = Java.junit(test_cases, :classpath=>classpath) fail "#{name}: The following tests failed:\n#{failed.join("\n")}" unless failed.empty? end end end def from(*files) @paths += files self end def include(*files) @include += files self end def exclude(*files) @exclude += files self end def with(*files) @classpath |= artifacts(files.flatten).uniq self end def test_cases() unless @cases @include << "*" if @include.empty? @cases = @paths.map do |path| base = Pathname.new(path) FileList[File.join(path, "**", "*Test.class")]. map { |file| Pathname.new(file).relative_path_from(base).to_s.ext("").gsub(File::SEPARATOR, ".") }. select { |name| @include.any? { |pattern| File.fnmatch(pattern, name) } }. reject { |name| @exclude.any? { |pattern| File.fnmatch(pattern, name) } } end.flatten.sort end @cases end def invoke() setup begin super ensure teardown end end def needed?() return true unless ENV["TESTS"] =~ /(no|off|false|disable)/i end def prerequisites() super + classpath + @paths end def invoke_prerequisites() prerequisites.each { |n| application[n, @scope].invoke } end def setup() Rake::Task[name.sub(/run$/, "setup")].invoke end def teardown() Rake::Task[name.sub(/run$/, "teardown")].invoke end end class Tests def initialize(project) @project = project end def prepare(*tasks, &block) @project.task("tests:prepare").enhance tasks, &block end def compile(*sources, &block) @project.task("tests:compile").from(sources).enhance &block end def resources(*tasks, &block) @project.task("tests:resources").enhance tasks, &block end def setup(*tasks, &block) @project.task("tests:setup").enhance tasks, &block end def run(*tasks, &block) @project.task("tests:run").enhance tasks, &block end def teardown(*tasks, &block) @project.task("tests:teardown").enhance tasks, &block end end class Project inherited_attr :test_src_dir do File.join(src_dir, "test", "java") end inherited_attr :test_resources_dir do File.join(src_dir, "test", "resources") end inherited_attr :test_target_dir do File.join(target_dir, "test-classes") end def tests() @tests ||= Tests.new(self) end def test(*tasks, &block) tests.run *tasks, &block end end # Global task compiles all projects. desc "Run all test cases" Project.local_task task("test") Project.on_define do |project| namespace "tests" do # Compile task requires prepare and performs resources, if anything compiled. #Java::CompileTask.define_task("compile"=>[project.compile, task("prepare")]) { |task| project.tests.resources.invoke } Java::CompileTask.define_task("compile"=>[project.compile, task("prepare")]) { |task| project.tests.resources.invoke } # Resources task is a filter. FilterTask.define_task("resources") JUnitTask.define_task("run"=>task("compile")) task("setup") task("teardown") end project.tests.compile.with Java::JUNIT_REQUIRES project.recursive_task("test"=>project.test) project.enhance do |project| project.tests.compile.from project.path_to(:test_src_dir) if File.exist?(project.path_to(:test_src_dir)) project.tests.compile.into project.path_to(:test_target_dir) unless project.tests.compile.target project.tests.resources.include project.path_to(:test_resources_dir, "*") if File.exists?(project.path_to(:test_resources_dir)) project.tests.resources.into project.tests.compile.target unless project.tests.resources.target project.tests.compile.classpath += project.compile.classpath project.tests.compile.classpath << project.compile.target project.tests.run.from project.tests.compile.target project.tests.run.classpath += project.tests.compile.classpath project.tests.run.classpath << project.tests.compile.target end end rule /^test:.*$/ do |task| test = task.name.scan(/test:(.*)/)[0][0] Project.projects.select { |project| project.base_dir == Rake.application.original_dir }. map { |project| project.task("tests:run") }. each { |task| task.include("*#{test}").invoke } end end