blob: 94ad6798d54995b279c7638c882aeb6290c3160d [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with this
# work for additional information regarding copyright ownership. The ASF
# licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helpers'))
module TestHelper
def touch_last_successful_test_run(test_task, timestamp = Time.now)
test_task.instance_eval do
record_successful_run
File.utime(timestamp, timestamp, last_successful_run_file)
end
end
end
describe Buildr::TestTask do
def test_task
@test_task ||= define('foo').test
end
it 'should respond to :compile and return compile task' do
test_task.compile.should be_kind_of(Buildr::CompileTask)
end
it 'should respond to :compile and add sources to compile' do
test_task.compile 'sources'
test_task.compile.sources.should include('sources')
end
it 'should respond to :compile and add action for test:compile' do
write 'src/test/java/Test.java', 'class Test {}'
test_task.compile { task('action').invoke }
lambda { test_task.compile.invoke }.should run_tasks('action')
end
it 'should execute compile tasks first' do
write 'src/main/java/Nothing.java', 'class Nothing {}'
write 'src/test/java/Test.java', 'class Test {}'
define 'foo'
lambda { project('foo').test.compile.invoke }.should run_tasks(['foo:compile', 'foo:test:compile'])
end
it 'should respond to :resources and return resources task' do
test_task.resources.should be_kind_of(Buildr::ResourcesTask)
end
it 'should respond to :resources and add prerequisites to test:resources' do
file('prereq').should_receive :invoke_prerequisites
test_task.resources 'prereq'
test_task.compile.invoke
end
it 'should respond to :resources and add action for test:resources' do
task 'action'
test_task.resources { task('action').invoke }
lambda { test_task.resources.invoke }.should run_tasks('action')
end
it 'should respond to :setup and return setup task' do
test_task.setup.name.should =~ /test:setup$/
end
it 'should respond to :setup and add prerequisites to test:setup' do
test_task.setup 'prereq'
test_task.setup.prerequisites.should include('prereq')
end
it 'should respond to :setup and add action for test:setup' do
task 'action'
test_task.setup { task('action').invoke }
lambda { test_task.setup.invoke }.should run_tasks('action')
end
it 'should respond to :teardown and return teardown task' do
test_task.teardown.name.should =~ /test:teardown$/
end
it 'should respond to :teardown and add prerequisites to test:teardown' do
test_task.teardown 'prereq'
test_task.teardown.prerequisites.should include('prereq')
end
it 'should respond to :teardown and add action for test:teardown' do
task 'action'
test_task.teardown { task('action').invoke }
lambda { test_task.teardown.invoke }.should run_tasks('action')
end
it 'should respond to :with and return self' do
test_task.with.should be(test_task)
end
it 'should respond to :with and add artifacfs to compile task dependencies' do
test_task.with 'test.jar', 'acme:example:jar:1.0'
test_task.compile.dependencies.should include(File.expand_path('test.jar'))
test_task.compile.dependencies.should include(artifact('acme:example:jar:1.0'))
end
it 'should respond to deprecated classpath' do
test_task.classpath = artifact('acme:example:jar:1.0')
test_task.classpath.should be(artifact('acme:example:jar:1.0'))
end
it 'should respond to dependencies' do
test_task.dependencies = artifact('acme:example:jar:1.0')
test_task.dependencies.should be(artifact('acme:example:jar:1.0'))
end
it 'should respond to :with and add artifacfs to task dependencies' do
test_task.with 'test.jar', 'acme:example:jar:1.0'
test_task.dependencies.should include(File.expand_path('test.jar'))
test_task.dependencies.should include(artifact('acme:example:jar:1.0'))
end
it 'should response to :options and return test framework options' do
test_task.using :foo=>'bar'
test_task.options[:foo].should eql('bar')
end
it 'should respond to :using and return self' do
test_task.using.should be(test_task)
end
it 'should respond to :using and set value options' do
test_task.using('foo'=>'FOO', 'bar'=>'BAR')
test_task.options[:foo].should eql('FOO')
test_task.options[:bar].should eql('BAR')
end
it 'should start without pre-selected test framework' do
test_task.framework.should be_nil
end
it 'should respond to :using and select test framework' do
test_task.using(:testng)
test_task.framework.should eql(:testng)
end
it 'should infer test framework from compiled language' do
lambda { test_task.compile.using(:javac) }.should change { test_task.framework }.to(:junit)
end
it 'should respond to :include and return self' do
test_task.include.should be(test_task)
end
it 'should respond to :include and add inclusion patterns' do
test_task.include 'Foo', 'Bar'
test_task.send(:include?, 'Foo').should be_true
test_task.send(:include?, 'Bar').should be_true
end
it 'should respond to :exclude and return self' do
test_task.exclude.should be(test_task)
end
it 'should respond to :exclude and add exclusion patterns' do
test_task.exclude 'FooTest', 'BarTest'
test_task.send(:include?, 'FooTest').should be_false
test_task.send(:include?, 'BarTest').should be_false
test_task.send(:include?, 'BazTest').should be_true
end
it 'should execute setup task before running tests' do
mock = double('actions')
test_task.setup { mock.setup }
test_task.enhance { mock.tests }
mock.should_receive(:setup).ordered
mock.should_receive(:tests).ordered
test_task.invoke
end
it 'should execute teardown task after running tests' do
mock = double('actions')
test_task.teardown { mock.teardown }
test_task.enhance { mock.tests }
mock.should_receive(:tests).ordered
mock.should_receive(:teardown).ordered
test_task.invoke
end
it 'should not execute teardown if setup failed' do
test_task.setup { fail }
lambda { test_task.invoke rescue nil }.should_not run_task(test_task.teardown)
end
it 'should use the main compile dependencies' do
define('foo') { compile.using(:javac).with 'group:id:jar:1.0' }
project('foo').test.dependencies.should include(artifact('group:id:jar:1.0'))
end
it 'should include the main compile target in its dependencies' do
define('foo') { compile.using(:javac) }
project('foo').test.dependencies.should include(project('foo').compile.target)
end
it 'should include the main compile target in its dependencies, even when using non standard directories' do
write 'src/java/Nothing.java', 'class Nothing {}'
define('foo') { compile path_to('src/java') }
project('foo').test.dependencies.should include(project('foo').compile.target)
end
it 'should include the main resources target in its dependencies' do
write 'src/main/resources/config.xml'
define('foo').test.dependencies.should include(project('foo').resources.target)
end
it 'should use the test compile dependencies' do
define('foo') { test.compile.using(:javac).with 'group:id:jar:1.0' }
project('foo').test.dependencies.should include(artifact('group:id:jar:1.0'))
end
it 'should include the test compile target in its dependencies' do
define('foo') { test.compile.using(:javac) }
project('foo').test.dependencies.should include(project('foo').test.compile.target)
end
it 'should include the test compile target in its dependencies, even when using non standard directories' do
write 'src/test/Test.java', 'class Test {}'
define('foo') { test.compile path_to('src/test') }
project('foo').test.dependencies.should include(project('foo').test.compile.target)
end
it 'should add test compile target ahead of regular compile target' do
write 'src/main/java/Code.java'
write 'src/test/java/Test.java'
define 'foo'
depends = project('foo').test.dependencies
depends.index(project('foo').test.compile.target).should < depends.index(project('foo').compile.target)
end
it 'should include the test resources target in its dependencies' do
write 'src/test/resources/config.xml'
define('foo').test.dependencies.should include(project('foo').test.resources.target)
end
it 'should add test resource target ahead of regular resource target' do
write 'src/main/resources/config.xml'
write 'src/test/resources/config.xml'
define 'foo'
depends = project('foo').test.dependencies
depends.index(project('foo').test.resources.target).should < depends.index(project('foo').resources.target)
end
it 'should not have a last successful run timestamp before the tests are run' do
test_task.timestamp.should == Rake::EARLY
end
it 'should clean after itself (test files)' do
define('foo') { test.compile.using(:javac) }
mkpath project('foo').test.compile.target.to_s
lambda { task('clean').invoke }.should change { File.exist?(project('foo').test.compile.target.to_s) }.to(false)
end
it 'should clean after itself (reports)' do
define 'foo'
mkpath project('foo').test.report_to.to_s
lambda { task('clean').invoke }.should change { File.exist?(project('foo').test.report_to.to_s) }.to(false)
end
it 'should only run tests explicitly specified if options.test is :only' do
Buildr.options.test = :only
write 'bar/src/main/java/Bar.java', 'public class Bar {}'
define('bar', :version=>'1.0', :base_dir=>'bar') { package :jar }
define('foo') { compile.with project('bar') }
lambda { task('foo:test').invoke rescue nil }.should_not run_tasks('bar:test')
end
end
describe Buildr::TestTask, 'with no tests' do
it 'should pass' do
lambda { define('foo').test.invoke }.should_not raise_error
end
it 'should report no failed tests' do
lambda { verbose(true) { define('foo').test.invoke } }.should_not show_error(/fail/i)
end
it 'should return no failed tests' do
define('foo') { test.using(:junit) }
project('foo').test.invoke
project('foo').test.failed_tests.should be_empty
end
it 'should return no passing tests' do
define('foo') { test.using(:junit) }
project('foo').test.invoke
project('foo').test.passed_tests.should be_empty
end
it 'should execute teardown task' do
lambda { define('foo').test.invoke }.should run_task('foo:test:teardown')
end
end
describe Buildr::TestTask, 'with passing tests' do
def test_task
@test_task ||= begin
define 'foo' do
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['PassingTest1', 'PassingTest2'])
@framework.stub(:run).and_return(['PassingTest1', 'PassingTest2'])
end
end
project('foo').test
end
end
it 'should pass' do
lambda { test_task.invoke }.should_not raise_error
end
it 'should report no failed tests' do
lambda { verbose(true) { test_task.invoke } }.should_not show_error(/fail/i)
end
it 'should return passed tests' do
test_task.invoke
test_task.passed_tests.should == ['PassingTest1', 'PassingTest2']
end
it 'should return no failed tests' do
test_task.invoke
test_task.failed_tests.should be_empty
end
it 'should execute teardown task' do
lambda { test_task.invoke }.should run_task('foo:test:teardown')
end
it 'should update the last successful run timestamp' do
before = Time.now ; test_task.invoke ; after = Time.now
(before-1..after+1).should cover(test_task.timestamp)
end
end
describe Buildr::TestTask, 'with failed test' do
include TestHelper
def test_task
@test_task ||= begin
define 'foo' do
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['FailingTest', 'PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
project('foo').test
end
end
it 'should fail' do
lambda { test_task.invoke }.should raise_error(RuntimeError, /Tests failed/)
end
it 'should report failed tests' do
lambda { verbose(true) { test_task.invoke rescue nil } }.should show_error(/FailingTest/)
end
it 'should record failed tests' do
test_task.invoke rescue nil
File.read(project('foo').path_to('target', "#{test_task.framework}-failed")).should == 'FailingTest'
end
it 'should return failed tests' do
test_task.invoke rescue nil
test_task.failed_tests.should == ['FailingTest']
end
it 'should return passing tests as well' do
test_task.invoke rescue nil
test_task.passed_tests.should == ['PassingTest']
end
it 'should know what tests failed last time' do
test_task.invoke rescue nil
project('foo').test.last_failures.should == ['FailingTest']
end
it 'should not fail if fail_on_failure is false' do
test_task.using(:fail_on_failure=>false).invoke
lambda { test_task.invoke }.should_not raise_error
end
it 'should report failed tests even if fail_on_failure is false' do
test_task.using(:fail_on_failure=>false)
lambda { verbose(true) { test_task.invoke } }.should show_error(/FailingTest/)
end
it 'should return failed tests even if fail_on_failure is false' do
test_task.using(:fail_on_failure=>false).invoke
test_task.failed_tests.should == ['FailingTest']
end
it 'should execute teardown task' do
lambda { test_task.invoke rescue nil }.should run_task('foo:test:teardown')
end
it 'should not update the last successful run timestamp' do
a_second_ago = Time.now - 1
touch_last_successful_test_run test_task, a_second_ago
test_task.invoke rescue nil
test_task.timestamp.should <= a_second_ago
end
end
describe Buildr::Project, '#test' do
it 'should return the project\'s test task' do
define('foo') { test.should be(task('test')) }
end
it 'should accept prerequisites for task' do
define('foo') { test 'prereq' }
project('foo').test.prerequisites.should include('prereq')
end
it 'should accept actions for task' do
task 'action'
define('foo') { test { task('action').invoke } }
lambda { project('foo').test.invoke }.should run_tasks('action')
end
it 'should set fail_on_failure true by default' do
define('foo').test.options[:fail_on_failure].should be_true
end
it 'should set fork mode by default' do
define('foo').test.options[:fork].should == :once
end
it 'should set properties to empty hash by default' do
define('foo').test.options[:properties].should == {}
end
it 'should set environment variables to empty hash by default' do
define('foo').test.options[:environment].should == {}
end
it 'should inherit options from parent project' do
define 'foo' do
test.using :fail_on_failure=>false, :fork=>:each, :properties=>{ :foo=>'bar' }, :environment=>{ 'config'=>'config.yaml' }
define 'bar' do
test.using :junit
test.options[:fail_on_failure].should be_false
test.options[:fork].should == :each
test.options[:properties][:foo].should == 'bar'
test.options[:environment]['config'].should == 'config.yaml'
end
end
end
it 'should clone options from parent project when using #using' do
define 'foo' do
define 'bar' do
test.using :fail_on_failure=>false, :fork=>:each, :properties=>{ :foo=>'bar' }, :environment=>{ 'config'=>'config.yaml' }
test.using :junit
end.invoke
test.options[:fail_on_failure].should be_true
test.options[:fork].should == :once
test.options[:properties].should == {}
test.options[:environment].should == {}
end
end
it 'should clone options from parent project when using #options' do
define 'foo' do
define 'bar' do
test.options[:fail_on_failure] = false
test.options[:fork] = :each
test.options[:properties][:foo] = 'bar'
test.options[:environment]['config'] = 'config.yaml'
test.using :junit
end.invoke
test.options[:fail_on_failure].should be_true
test.options[:fork].should == :once
test.options[:properties].should == {}
test.options[:environment].should == {}
end
end
it 'should accept to set a test property in the top project' do
define 'foo' do
test.options[:properties][:foo] = 'bar'
end
project('foo').test.options[:properties][:foo].should == 'bar'
end
it 'should accept to set a test property in a subproject' do
define 'foo' do
define 'bar' do
test.options[:properties][:bar] = 'baz'
end
end
project('foo:bar').test.options[:properties][:bar].should == 'baz'
end
it 'should not change options of unrelated projects when using #options' do
define 'foo' do
test.options[:properties][:foo] = 'bar'
end
define 'bar' do
test.options[:properties].should == {}
end
end
it "should run from project's build task" do
write 'src/main/java/Foo.java'
write 'src/test/java/FooTest.java'
define('foo')
lambda { task('foo:build').invoke }.should run_task('foo:test')
end
end
describe Buildr::Project, '#test.compile' do
it 'should identify compiler from project' do
write 'src/test/java/com/example/Test.java'
define('foo') do
test.compile.compiler.should eql(:javac)
end
end
it 'should include identified sources' do
write 'src/test/java/Test.java'
define('foo') do
test.compile.sources.should include(_('src/test/java'))
end
end
it 'should compile to target/test/<code>' do
define 'foo' do
layout[:target] = _('targeted')
test.compile.using(:javac)
test.compile.target.should eql(file('targeted/test/classes'))
end
end
it 'should use main compile dependencies' do
define 'foo' do
compile.using(:javac).with 'group:id:jar:1.0'
test.compile.using(:javac)
end
project('foo').test.compile.dependencies.should include(artifact('group:id:jar:1.0'))
end
it 'should include the main compiled target in its dependencies' do
define 'foo' do
compile.using(:javac).into 'bytecode'
test.compile.using(:javac)
end
project('foo').test.compile.dependencies.should include(file('bytecode'))
end
it 'should include the test framework dependencies' do
define 'foo' do
test.compile.using(:javac)
test.using(:junit)
end
project('foo').test.compile.dependencies.should include(*artifacts(JUnit.dependencies))
end
it 'should clean after itself' do
write 'src/test/java/Nothing.java', 'class Nothing {}'
define('foo') { test.compile.into 'bytecode' }
project('foo').test.compile.invoke
lambda { project('foo').clean.invoke }.should change { File.exist?('bytecode') }.to(false)
end
end
describe Buildr::Project, '#test.resources' do
it 'should ignore resources unless they exist' do
define('foo').test.resources.sources.should be_empty
project('foo').test.resources.target.should be_nil
end
it 'should pick resources from src/test/resources if found' do
mkpath 'src/test/resources'
define('foo') { test.resources.sources.should include(file('src/test/resources')) }
end
it 'should copy to the resources target directory' do
write 'src/test/resources/config.xml', '</xml>'
define('foo') do
layout[:target] = _('targeted')
end.test.invoke
file('targeted/test/resources/config.xml').should contain('</xml>')
end
it 'should create target directory even if no files to copy' do
define('foo') do
test.resources.filter.into('resources')
end
lambda { file(File.expand_path('resources')).invoke }.should change { File.exist?('resources') }.to(true)
end
it 'should execute alongside compile task' do
task 'action'
define('foo') { test.resources { task('action').invoke } }
lambda { project('foo').test.compile.invoke }.should run_tasks('action')
end
end
describe Buildr::TestTask, '#invoke' do
include TestHelper
def test_task
@test_task ||= define('foo') {
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
}.test
end
it 'should require dependencies to exist' do
lambda { test_task.with('no-such.jar').invoke }.should \
raise_error(RuntimeError, /Don't know how to build/)
end
it 'should run all dependencies as prerequisites' do
file(File.expand_path('no-such.jar')) { task('prereq').invoke }
lambda { test_task.with('no-such.jar').invoke }.should run_tasks(['prereq', 'foo:test'])
end
it 'should run tests if they have never run' do
lambda { test_task.invoke }.should run_task('foo:test')
end
it 'should not run tests if test option is off' do
Buildr.options.test = false
lambda { test_task.invoke }.should_not run_task('foo:test')
end
describe 'when there was a successful test run already' do
before do
@a_second_ago = Time.now - 1
src = ['main/java/Foo.java', 'main/resources/config.xml', 'test/java/FooTest.java', 'test/resources/config-test.xml'].map { |f| File.join('src', f) }
target = ['classes/Foo.class', 'resources/config.xml', 'test/classes/FooTest.class', 'test/resources/config-test.xml'].map { |f| File.join('target', f) }
files = ['buildfile'] + src + target
files.each { |file| write file }
dirs = (src + target).map { |file| file.pathmap('%d') }
(files + dirs ).each { |path| File.utime(@a_second_ago, @a_second_ago, path) }
touch_last_successful_test_run test_task, @a_second_ago
end
it 'should not run tests if nothing changed' do
lambda { test_task.invoke; sleep 1 }.should_not run_task('foo:test')
end
it 'should run tests if options.test is :all' do
Buildr.options.test = :all
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if main compile target changed' do
touch project('foo').compile.target.to_s
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if test compile target changed' do
touch test_task.compile.target.to_s
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if main resources changed' do
touch project('foo').resources.target.to_s
lambda { test_task.invoke }.should run_task('foo:test')
end
it 'should run tests if test resources changed' do
touch test_task.resources.target.to_s
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if compile-dependent project changed' do
write 'bar/src/main/java/Bar.java', 'public class Bar {}'
define('bar', :version=>'1.0', :base_dir=>'bar') { package :jar }
project('foo').compile.with project('bar')
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if test-dependent project changed' do
write 'bar/src/main/java/Bar.java', 'public class Bar {}'
define('bar', :version=>'1.0', :base_dir=>'bar') { package :jar }
test_task.with project('bar')
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should run tests if buildfile changed' do
touch 'buildfile'
test_task.should_receive(:run_tests)
lambda { test_task.invoke; sleep 1 }.should run_task('foo:test')
end
it 'should not run tests if buildfile changed but IGNORE_BUILDFILE is true' do
begin
ENV["IGNORE_BUILDFILE"] = "true"
test_task.should_not_receive(:run_tests)
test_task.invoke
ensure
ENV["IGNORE_BUILDFILE"] = nil
end
end
end
end
describe Rake::Task, 'test' do
it 'should be recursive' do
define('foo') { define 'bar' }
lambda { task('test').invoke }.should run_tasks('foo:test', 'foo:bar:test')
end
it 'should be local task' do
define('foo') { define 'bar' }
lambda do
in_original_dir project('foo:bar').base_dir do
task('test').invoke
end
end.should run_task('foo:bar:test').but_not('foo:test')
end
it 'should stop at first failure' do
define('myproject') do
define('foo') { test { fail } }
define('bar') { test { fail } }
end
lambda { task('test').invoke rescue nil }.should run_tasks('myproject:bar:test').but_not('myproject:foo:test')
end
it 'should ignore failure if options.test is :all' do
define('foo') { test { fail } }
define('bar') { test { fail } }
options.test = :all
lambda { task('test').invoke rescue nil }.should run_tasks('foo:test', 'bar:test')
end
it 'should ignore failure in subprojects if options.test is :all' do
define('foo') {
define('p1') { test { fail } }
define('p2') { test { } }
define('p3') { test { fail } }
}
define('bar') { test { fail } }
options.test = :all
lambda { task('test').invoke rescue nil }.should run_tasks('foo:p1:test', 'foo:p2:test', 'foo:p3:test', 'bar:test')
end
it 'should ignore failure in subprojects if environment variable test is \'all\'' do
define('foo') {
define('p1') { test { fail } }
define('p2') { test { } }
define('p3') { test { fail } }
}
define('bar') { test { fail } }
ENV['test'] = 'all'
lambda { task('test').invoke rescue nil }.should run_tasks('foo:p1:test', 'foo:p2:test', 'foo:p3:test', 'bar:test')
end
it 'should ignore failure if options.test is :all and target is build task ' do
define('foo') { test { fail } }
define('bar') { test { fail } }
options.test = :all
lambda { task('build').invoke rescue nil }.should run_tasks('foo:test', 'bar:test')
end
it 'should ignore failure if environment variable test is \'all\'' do
define('foo') { test { fail } }
define('bar') { test { fail } }
ENV['test'] = 'all'
lambda { task('test').invoke rescue nil }.should run_tasks('foo:test', 'bar:test')
end
it 'should ignore failure if environment variable TEST is \'all\'' do
define('foo') { test { fail } }
define('bar') { test { fail } }
ENV['TEST'] = 'all'
lambda { task('test').invoke rescue nil }.should run_tasks('foo:test', 'bar:test')
end
it 'should execute no tests if options.test is false' do
define('foo') { test { fail } }
define('bar') { test { fail } }
options.test = false
lambda { task('test').invoke rescue nil }.should_not run_tasks('foo:test', 'bar:test')
end
it 'should execute no tests if environment variable test is \'no\'' do
define('foo') { test { fail } }
define('bar') { test { fail } }
ENV['test'] = 'no'
lambda { task('test').invoke rescue nil }.should_not run_tasks('foo:test', 'bar:test')
end
it 'should execute no tests if environment variable TEST is \'no\'' do
define('foo') { test { fail } }
define('bar') { test { fail } }
ENV['TEST'] = 'no'
lambda { task('test').invoke rescue nil }.should_not run_tasks('foo:test', 'bar:test')
end
it "should not compile tests if environment variable test is 'no'" do
write "src/test/java/HelloTest.java", "public class HelloTest { public void testTest() {}}"
define('foo') { test { fail } }
ENV['test'] = 'no'
lambda { task('test').invoke rescue nil }.should_not run_tasks('foo:test:compile')
end
end
describe 'test rule' do
include TestHelper
it 'should execute test task on local project' do
define('foo') { define 'bar' }
lambda { task('test:something').invoke }.should run_task('foo:test')
end
it 'should reset tasks to specific pattern' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
define 'bar' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
end
task('test:something').invoke
['foo', 'foo:bar'].map { |name| project(name) }.each do |project|
project.test.tests.should include('something')
project.test.tests.should_not include('nothing')
end
end
it 'should apply *name* pattern' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['prefix-something-suffix']) }
end
task('test:something').invoke
project('foo').test.tests.should include('prefix-something-suffix')
end
it 'should not apply *name* pattern if asterisks used' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['prefix-something', 'prefix-something-suffix']) }
end
task('test:*something').invoke
project('foo').test.tests.should include('prefix-something')
project('foo').test.tests.should_not include('prefix-something-suffix')
end
it 'should accept multiple tasks separated by commas' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['foo', 'bar', 'baz']) }
end
task('test:foo,bar').invoke
project('foo').test.tests.should include('foo')
project('foo').test.tests.should include('bar')
project('foo').test.tests.should_not include('baz')
end
it 'should execute only the named tests' do
write 'src/test/java/TestSomething.java',
'public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }'
write 'src/test/java/TestFails.java',
'public class TestFails extends junit.framework.TestCase { public void testFailure() { fail(); } }'
define 'foo'
task('test:Something').invoke
end
it 'should execute the named tests even if the test task is not needed' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
touch_last_successful_test_run project('foo').test
task('test:something').invoke
project('foo').test.tests.should include('something')
end
it 'should not execute excluded tests' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
task('test:*,-nothing').invoke
project('foo').test.tests.should include('something')
project('foo').test.tests.should_not include('nothing')
end
it 'should not execute tests in excluded package' do
write 'src/test/java/com/example/foo/TestSomething.java',
'package com.example.foo; public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }'
write 'src/test/java/com/example/bar/TestFails.java',
'package com.example.bar; public class TestFails extends junit.framework.TestCase { public void testFailure() { fail(); } }'
define 'foo' do
test.using(:junit)
end
task('test:-com.example.bar').invoke
project('foo').test.tests.should include('com.example.foo.TestSomething')
project('foo').test.tests.should_not include('com.example.bar.TestFails')
end
it 'should not execute excluded tests with wildcards' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
task('test:something,-s*,-n*').invoke
project('foo').test.tests.should_not include('something')
project('foo').test.tests.should_not include('nothing')
end
it 'should execute all tests except excluded tests' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'anything', 'nothing']) }
end
task('test:-nothing').invoke
project('foo').test.tests.should include('something', 'anything')
project('foo').test.tests.should_not include('nothing')
end
it 'should ignore exclusions in buildfile' do
define 'foo' do
test.using(:junit)
test.exclude 'something'
test.instance_eval { @framework.stub(:tests).and_return(['something', 'anything', 'nothing']) }
end
task('test:-nothing').invoke
project('foo').test.tests.should include('something', 'anything')
project('foo').test.tests.should_not include('nothing')
end
it 'should ignore inclusions in buildfile' do
define 'foo' do
test.using(:junit)
test.include 'something'
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
task('test:nothing').invoke
project('foo').test.tests.should include('nothing')
project('foo').test.tests.should_not include('something')
end
it 'should not execute a test if it''s both included and excluded' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['nothing']) }
end
task('test:nothing,-nothing').invoke
project('foo').test.tests.should_not include('nothing')
end
it 'should not update the last successful test run timestamp' do
define 'foo' do
test.using(:junit)
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
a_second_ago = Time.now - 1
touch_last_successful_test_run project('foo').test, a_second_ago
task('test:something').invoke
project('foo').test.timestamp.should <= a_second_ago
end
end
describe 'test failed' do
include TestHelper
def test_task
@test_task ||= begin
define 'foo' do
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['FailingTest', 'PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
project('foo').test
end
end
it 'should run the tests that failed the last time' do
define 'foo' do
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['FailingTest', 'PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
write project('foo').path_to(:target, "junit-failed"), "FailingTest"
task('test:failed').invoke rescue nil
project('foo').test.tests.should include('FailingTest')
project('foo').test.tests.should_not include('PassingTest')
end
it 'should run failed tests, respecting excluded tests' do
define 'foo' do
test.using(:junit).exclude('ExcludedTest')
test.instance_eval do
@framework.stub(:tests).and_return(['FailingTest', 'PassingTest', 'ExcludedTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
write project('foo').path_to(:target, "junit-failed"), "FailingTest\nExcludedTest"
task('test:failed').invoke rescue nil
project('foo').test.tests.should include('FailingTest')
project('foo').test.tests.should_not include('ExcludedTest')
end
it 'should run only the tests that failed the last time, even when failed tests have dependencies' do
define 'parent' do
define 'foo' do
test.using(:junit)
test.instance_eval do
@framework.stub(:tests).and_return(['PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
define 'bar' do
test.using(:junit)
test.enhance ["parent:foo:test"]
test.instance_eval do
@framework.stub(:tests).and_return(['FailingTest', 'PassingTest'])
@framework.stub(:run).and_return(['PassingTest'])
end
end
end
write project('parent:bar').path_to(:target, "junit-failed"), "FailingTest"
task('test:failed').invoke rescue nil
project('parent:foo').test.tests.should_not include('PassingTest')
project('parent:bar').test.tests.should include('FailingTest')
project('parent:bar').test.tests.should_not include('PassingTest')
end
end
describe Buildr::Options, 'test' do
it 'should be true by default' do
Buildr.options.test.should be_true
end
['skip', 'no', 'off', 'false'].each do |value|
it "should be false if test environment variable is '#{value}'" do
lambda { ENV['test'] = value }.should change { Buildr.options.test }.to(false)
end
end
['skip', 'no', 'off', 'false'].each do |value|
it "should be false if TEST environment variable is '#{value}'" do
lambda { ENV['TEST'] = value }.should change { Buildr.options.test }.to(false)
end
end
it 'should be :all if test environment variable is all' do
lambda { ENV['test'] = 'all' }.should change { Buildr.options.test }.to(:all)
end
it 'should be :all if TEST environment variable is all' do
lambda { ENV['TEST'] = 'all' }.should change { Buildr.options.test }.to(:all)
end
it 'should be true and warn for any other value' do
ENV['TEST'] = 'funky'
lambda { Buildr.options.test.should be(true) }.should show_warning(/expecting the environment variable/i)
end
end
describe Buildr, 'integration' do
it 'should return the same task from all contexts' do
task = task('integration')
define 'foo' do
integration.should be(task)
define 'bar' do
integration.should be(task)
end
end
integration.should be(task)
end
it 'should respond to :setup and return setup task' do
setup = integration.setup
define('foo') { integration.setup.should be(setup) }
end
it 'should respond to :setup and add prerequisites to integration:setup' do
define('foo') { integration.setup 'prereq' }
integration.setup.prerequisites.should include('prereq')
end
it 'should respond to :setup and add action for integration:setup' do
action = task('action')
define('foo') { integration.setup { action.invoke } }
lambda { integration.setup.invoke }.should run_tasks(action)
end
it 'should respond to :teardown and return teardown task' do
teardown = integration.teardown
define('foo') { integration.teardown.should be(teardown) }
end
it 'should respond to :teardown and add prerequisites to integration:teardown' do
define('foo') { integration.teardown 'prereq' }
integration.teardown.prerequisites.should include('prereq')
end
it 'should respond to :teardown and add action for integration:teardown' do
action = task('action')
define('foo') { integration.teardown { action.invoke } }
lambda { integration.teardown.invoke }.should run_tasks(action)
end
end
describe Rake::Task, 'integration' do
it 'should be a local task' do
define('foo') { test.using :integration }
define('bar', :base_dir=>'other') { test.using :integration }
lambda { task('integration').invoke }.should run_task('foo:test').but_not('bar:test')
end
it 'should be a recursive task' do
define 'foo' do
test.using :integration
define('bar') { test.using :integration }
end
lambda { task('integration').invoke }.should run_tasks('foo:test', 'foo:bar:test')
end
it 'should find nested integration tests' do
define 'foo' do
define('bar') { test.using :integration }
end
lambda { task('integration').invoke }.should run_tasks('foo:bar:test').but_not('foo:test')
end
it 'should ignore nested regular tasks' do
define 'foo' do
test.using :integration
define('bar') { test.using :integration=>false }
end
lambda { task('integration').invoke }.should run_tasks('foo:test').but_not('foo:bar:test')
end
it 'should agree not to run the same tasks as test' do
define 'foo' do
define 'bar' do
test.using :integration
define('baz') { test.using :integration=>false }
end
end
lambda { task('test').invoke }.should run_tasks('foo:test', 'foo:bar:baz:test').but_not('foo:bar:test')
lambda { task('integration').invoke }.should run_tasks('foo:bar:test').but_not('foo:test', 'foo:bar:baz:test')
end
it 'should run setup task before any project integration tests' do
define('foo') { test.using :integration }
define('bar') { test.using :integration }
lambda { task('integration').invoke }.should run_tasks([integration.setup, 'bar:test'], [integration.setup, 'foo:test'])
end
it 'should run teardown task after all project integrations tests' do
define('foo') { test.using :integration }
define('bar') { test.using :integration }
lambda { task('integration').invoke }.should run_tasks(['bar:test', integration.teardown], ['foo:test', integration.teardown])
end
it 'should run test cases marked for integration' do
write 'src/test/java/FailingTest.java',
'public class FailingTest extends junit.framework.TestCase { public void testNothing() { assertTrue(false); } }'
define('foo') { test.using :integration }
lambda { task('test').invoke }.should_not raise_error
lambda { task('integration').invoke }.should raise_error(RuntimeError, /tests failed/i)
end
it 'should run setup and teardown tasks marked for integration' do
define('foo') { test.using :integration }
lambda { task('test').invoke }.should run_tasks().but_not('foo:test:setup', 'foo:test:teardown')
lambda { task('integration').invoke }.should run_tasks('foo:test:setup', 'foo:test:teardown')
end
it 'should run test actions marked for integration' do
task 'action'
define 'foo' do
test.using :integration, :junit
end
lambda { task('test').invoke }.should_not change { project('foo').test.passed_tests }
lambda { task('integration').invoke }.should change { project('foo').test.passed_tests }
project('foo').test.passed_tests.should be_empty
end
it 'should not fail if test=all' do
write 'src/test/java/FailingTest.java',
'public class FailingTest extends junit.framework.TestCase { public void testNothing() { assertTrue(false); } }'
define('foo') { test.using :integration }
options.test = :all
lambda { task('integration').invoke }.should_not raise_error
end
it 'should execute by local package task' do
define 'foo', :version=>'1.0' do
test.using :integration
package :jar
end
lambda { task('package').invoke }.should run_tasks(['foo:package', 'foo:test'])
end
it 'should execute by local package task along with unit tests' do
define 'foo', :version=>'1.0' do
test.using :integration
package :jar
define('bar') { test.using :integration=>false }
end
lambda { task('package').invoke }.should run_tasks(['foo:package', 'foo:test'],
['foo:bar:test', 'foo:bar:package'])
end
it 'should not execute by local package task if test=no' do
define 'foo', :version=>'1.0' do
test.using :integration
package :jar
end
options.test = false
lambda { task('package').invoke }.should run_task('foo:package').but_not('foo:test')
end
end
describe 'integration rule' do
it 'should execute integration tests on local project' do
define 'foo' do
test.using :junit, :integration
define 'bar'
end
lambda { task('integration:something').invoke }.should run_task('foo:test')
end
it 'should reset tasks to specific pattern' do
define 'foo' do
test.using :junit, :integration
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
define 'bar' do
test.using :junit, :integration
test.instance_eval { @framework.stub(:tests).and_return(['something', 'nothing']) }
end
end
task('integration:something').invoke
['foo', 'foo:bar'].map { |name| project(name) }.each do |project|
project.test.tests.should include('something')
project.test.tests.should_not include('nothing')
end
end
it 'should apply *name* pattern' do
define 'foo' do
test.using :junit, :integration
test.instance_eval { @framework.stub(:tests).and_return(['prefix-something-suffix']) }
end
task('integration:something').invoke
project('foo').test.tests.should include('prefix-something-suffix')
end
it 'should not apply *name* pattern if asterisks used' do
define 'foo' do
test.using :junit, :integration
test.instance_eval { @framework.stub(:tests).and_return(['prefix-something', 'prefix-something-suffix']) }
end
task('integration:*something').invoke
project('foo').test.tests.should include('prefix-something')
project('foo').test.tests.should_not include('prefix-something-suffix')
end
it 'should accept multiple tasks separated by commas' do
define 'foo' do
test.using :junit, :integration
test.instance_eval { @framework.stub(:tests).and_return(['foo', 'bar', 'baz']) }
end
task('integration:foo,bar').invoke
project('foo').test.tests.should include('foo')
project('foo').test.tests.should include('bar')
project('foo').test.tests.should_not include('baz')
end
it 'should execute only the named tests' do
write 'src/test/java/TestSomething.java',
'public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }'
write 'src/test/java/TestFails.java',
'public class TestFails extends junit.framework.TestCase { public void testFailure() { fail(); } }'
define('foo') { test.using :junit, :integration }
task('integration:Something').invoke
end
end