Author: boisvert
Date: Mon Jun 9 20:53:14 2008
New Revision: 665967
URL: http://svn.apache.org/viewvc?rev=665967&view=rev
Log:
BUILDR-85: Add support for ScalaTest, ScalaCheck and Specs testing frameworks
Added:
incubator/buildr/trunk/spec/scala_test_frameworks_spec.rb
Modified:
incubator/buildr/trunk/lib/buildr/java/compilers.rb
incubator/buildr/trunk/lib/buildr/java/test_frameworks.rb
Modified: incubator/buildr/trunk/lib/buildr/java/compilers.rb
URL:
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/java/compilers.rb?rev=665967&r1=665966&r2=665967&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr/java/compilers.rb (original)
+++ incubator/buildr/trunk/lib/buildr/java/compilers.rb Mon Jun 9 20:53:14 2008
@@ -119,7 +119,7 @@
end
OPTIONS = [:warnings, :deprecation, :optimise, :target, :debug, :other]
- Java.classpath << dependencies unless Scalac.use_fsc
+ Java.classpath << dependencies
specify :language=>:scala, :target=>'classes', :target_ext=>'class',
:packaging=>:jar
Modified: incubator/buildr/trunk/lib/buildr/java/test_frameworks.rb
URL:
http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/buildr/java/test_frameworks.rb?rev=665967&r1=665966&r2=665967&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/buildr/java/test_frameworks.rb (original)
+++ incubator/buildr/trunk/lib/buildr/java/test_frameworks.rb Mon Jun 9
20:53:14 2008
@@ -90,7 +90,22 @@
REQUIRES = ["jmock:jmock:jar:#{VERSION}"]
end
+ # Specs is available when using ScalaTest
+ module ScalaSpecs
+ # Specs version number.
+ VERSION = '1.2.9' unless const_defined?('VERSION')
+ # Specs artifact(s)
+ REQUIRES = ["org.specs:specs:jar:#{VERSION}"]
+ end
+ # ScalaCheck is available when using ScalaTest
+ module ScalaCheck
+ # ScalaCheck version number.
+ VERSION = '1.3' unless const_defined?('VERSION')
+ # ScalaCheck artifact(s)
+ REQUIRES = ["org.scalacheck:scalacheck:jar:#{VERSION}"]
+ end
+
# JUnit test framework, the default test framework for Java tests.
#
# Support the following options:
@@ -249,7 +264,7 @@
class TestNG < TestFramework::Base
# TestNG version number.
- VERSION = '5.5' unless const_defined?('VERSION')
+ VERSION = '5.7' unless const_defined?('VERSION')
# TestNG specification.
REQUIRES = ["org.testng:testng:jar:jdk15:#{VERSION}"] + JMock::REQUIRES
@@ -278,11 +293,131 @@
end
-end
+ # ScalaTest framework, the default test framework for Scala tests.
+ #
+ # Support the following options:
+ # * :properties -- Hash of system properties available to the test case.
+ # * :environment -- Hash of environment variables available to the test case.
+ # * :java_args -- Arguments passed as is to the JVM.
+ class ScalaTest < TestFramework::Base
+
+ # ScalaTest version number.
+ VERSION = '0.9.3' unless const_defined?('VERSION')
+
+ # ScalaTest dependencies
+ REQUIRES = ["org.scalatest:scalatest:jar:#{VERSION}"] +
+ JMock::REQUIRES +
+ ScalaSpecs::REQUIRES +
+ ScalaCheck::REQUIRES
+
+ # ScalaTest ant task
+ Java.classpath << "org.apache.ant:ant-junit:jar:#{Ant::VERSION}"
+ Java.classpath << "org.scalatest:scalatest:jar:#{VERSION}"
+ #Java.classpath << REQUIRES
+
+ include TestFramework::JavaTest
+
+ # annotation-based group inclusion
+ attr_accessor :group_includes
+
+ # annotation-based gropu exclusion
+ attr_accessor :group_excludes
+
+ def initialize(test_task, options)
+ super
+ @group_includes = []
+ @group_excludes = []
+ end
+
+ def tests(dependencies) #:nodoc:
+ suites = filter_classes(dependencies, :interfaces =>
%w{org.scalatest.Suite})
+ # we should really filter using :class => %w{org.specs.Specification}
instead of naming convention
+ specs = filter_classes(dependencies, :class_names => [/Specs?$/])
+ [suites, specs].flatten
+ end
+
+ def run(tests, dependencies) #:nodoc:
+ mkpath task.report_to.to_s
+ success = []
+ scalatest = tests.select { |t| t !~ /Specs?$/ }
+ specs = tests.select { |t| t =~ /Specs?$/ }
+
+ # Specs
+ #options = { :nostacktrace => false }.merge(options)
+ nostacktrace = (options[:nostacktrace]) ? "-ns" : ""
+ cmd_options = { :properties => options[:properties],
+ :java_args => options[:java_args],
+ :classpath => dependencies}
+ specs.each do |spec|
+ Java.load
+ begin
+ Java::Commands.java(spec, {:classpath => dependencies})
+ rescue => e
+ print e.message
+ else
+ success << spec
+ end
+ end
+
+ # ScalaTest
+ reporter_options = 'TFGBSAR' # testSucceeded, testFailed, testIgnored,
suiteAborted, runStopped, runAborted, runCompleted
+ scalatest.each do |suite|
+ puts "ScalaTest #{suite.inspect}" if verbose
+ # Use Ant to execute the ScalaTest task, gives us performance and
reporting.
+ reportFile = File.join(task.report_to.to_s, "TEST-#{suite}.txt")
+ Buildr.ant('scalatest') do |ant|
+ ant.taskdef :name=>'scalatest',
:classname=>'org.scalatest.tools.ScalaTestTask'
+ ant.scalatest :runpath=>dependencies.join(File::PATH_SEPARATOR) do
+ ant.suite :classname=>suite
+ ant.reporter :type=>'stdout', :config=>reporter_options
+ ant.reporter :type=>'file', :filename=> reportFile,
:config=>reporter_options
+ ant.includes group_includes.join(" ") if group_includes
+ ant.excludes group_excludes.join(" ") if group_excludes
+ (options[:properties] || []).each { |name, value| ant.property
:name=>name, :value=>value }
+ end
+ end
+
+ # Parse for failures, errors, etc.
+ # This is a bit of a pain right now because ScalaTest doesn't flush its
+ # output synchronously before the Ant test finishes so we have to loop
+ # and wait for an indication that the test run was completed.
+ failed = false
+ completed = false
+ wait = 0
+ while (!completed) do
+ File.open(reportFile, "r") do |input|
+ while (line = input.gets) do
+ failed = (line =~ /(TEST FAILED -)|(RUN STOPPED)|(RUN ABORTED)/)
unless failed
+ completed |= (line =~ /Run completed\./)
+ break if (failed || completed)
+ end
+ end
+ wait += 1
+ break if (failed || wait > 10)
+ unless completed
+ sleep(1)
+ end
+ end
+ success << suite if (completed && !failed)
+ end
+
+ success
+ end # run
+
+ class << self
+ def applies_to?(project) #:nodoc:
+ project.test.compile.language == :scala
+ end
+ end
+
+ end # ScalaTest
+
+end # Buildr
Buildr::TestFramework << Buildr::JUnit
Buildr::TestFramework << Buildr::TestNG
+Buildr::TestFramework << Buildr::ScalaTest
# Backward compatibility crap.
Buildr::JUnit::JUNIT_REQUIRES = Buildr::JUnit::REQUIRES
Added: incubator/buildr/trunk/spec/scala_test_frameworks_spec.rb
URL:
http://svn.apache.org/viewvc/incubator/buildr/trunk/spec/scala_test_frameworks_spec.rb?rev=665967&view=auto
==============================================================================
--- incubator/buildr/trunk/spec/scala_test_frameworks_spec.rb (added)
+++ incubator/buildr/trunk/spec/scala_test_frameworks_spec.rb Mon Jun 9
20:53:14 2008
@@ -0,0 +1,216 @@
+# 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.join(File.dirname(__FILE__), 'spec_helpers')
+
+
+# TODO's
+# -test w/ Specs
+# -test w/ ScalaCheck
+# -failing test
+# -test passing System props
+# -test passing ENV variables
+# -test exclude group
+# -test include Suite's
+# -test exclude Suite's
+
+
+describe Buildr::ScalaTest do
+ it 'should be the default test framework when test cases are in Scala' do
+ write 'src/test/scala/com/example/MySuite.scala', <<-SCALA
+ package com.example
+ import org.scalatest.FunSuite
+ class MySuite extends FunSuite {
+ test("addition") {
+ val sum = 1 + 1
+ assert(sum === 2)
+ }
+ }
+ SCALA
+ define 'foo'
+ project('foo').test.framework.should eql(:scalatest)
+ end
+
+ it 'should be picked if the test language is Scala' do
+ define 'foo' do
+ test.compile.using(:scalac)
+ test.framework.should eql(:scalatest)
+ end
+ end
+
+ it 'should include Scalatest dependencies' do
+ define('foo') { test.using(:scalatest) }
+ project('foo').test.compile.dependencies.should
include(*artifacts(ScalaTest::REQUIRES))
+ project('foo').test.dependencies.should
include(*artifacts(ScalaTest::REQUIRES))
+ end
+
+ it 'should include JMock dependencies' do
+ define('foo') { test.using(:scalatest) }
+ project('foo').test.compile.dependencies.should
include(*artifacts(JMock::REQUIRES))
+ project('foo').test.dependencies.should
include(*artifacts(JMock::REQUIRES))
+ end
+
+ it 'should include Specs dependencies' do
+ define('foo') { test.using(:scalatest) }
+ project('foo').test.compile.dependencies.should
include(*artifacts(ScalaSpecs::REQUIRES))
+ project('foo').test.dependencies.should
include(*artifacts(ScalaSpecs::REQUIRES))
+ end
+
+ it 'should include ScalaCheck dependencies' do
+ define('foo') { test.using(:scalatest) }
+ project('foo').test.compile.dependencies.should
include(*artifacts(ScalaCheck::REQUIRES))
+ project('foo').test.dependencies.should
include(*artifacts(ScalaCheck::REQUIRES))
+ end
+
+ it 'should include public classes extending org.scalatest.FunSuite' do
+ write 'src/test/scala/com/example/MySuite.scala', <<-SCALA
+ package com.example
+ import org.scalatest.FunSuite
+ class MySuite extends FunSuite {
+ test("addition") {
+ val sum = 1 + 1
+ assert(sum === 2)
+ }
+ }
+ SCALA
+ define('foo').test.invoke
+ project('foo').test.tests.should include('com.example.MySuite')
+ end
+
+ it 'should ignore classes not extending org.scalatest.FunSuite' do
+ write 'src/test/scala/com/example/NotASuite.scala', <<-SCALA
+ package com.example
+ class Another {
+ }
+ SCALA
+ define('foo').test.invoke
+ project('foo').test.tests.should be_empty
+ end
+
+ it 'should ignore inner classes' do
+ write 'src/test/scala/com/example/InnerClassTest.scala', <<-SCALA
+ package com.example
+ import org.scalatest.FunSuite
+ class InnerClassTest extends FunSuite {
+ test("addition") {
+ val sum = 1 + 1
+ assert(sum === 2)
+ }
+
+ class InnerSuite extends FunSuite {
+ test("addition") {
+ val sum = 1 + 1
+ assert(sum === 2)
+ }
+ }
+ }
+ SCALA
+ define('foo').test.invoke
+ project('foo').test.tests.should eql(['com.example.InnerClassTest'])
+ end
+
+ it 'should pass when ScalaTest test case passes' do
+ write 'src/test/scala/PassingSuite.scala', <<-SCALA
+ class PassingSuite extends org.scalatest.FunSuite {
+ test("addition") {
+ val sum = 1 + 1
+ assert(sum === 2)
+ }
+ }
+ SCALA
+ lambda { define('foo').test.invoke }.should_not raise_error
+ end
+
+ it 'should fail when ScalaTest test case fails' do
+ write 'src/test/scala/FailingSuite.scala', <<-SCALA
+ class FailingSuite extends org.scalatest.FunSuite {
+ test("failing") {
+ assert(false)
+ }
+ }
+ SCALA
+ lambda { define('foo').test.invoke }.should raise_error(RuntimeError,
/Tests failed/) rescue nil
+ end
+
+ it 'should report failed test names' do
+ write 'src/test/scala/FailingSuite.scala', <<-SCALA
+ class FailingSuite extends org.scalatest.FunSuite {
+ test("failing") {
+ assert(false)
+ }
+ }
+ SCALA
+ define('foo').test.invoke rescue
+ project('foo').test.failed_tests.should include('FailingSuite')
+ end
+
+ it 'should report to reports/scalatest/TEST-TestSuiteName.txt' do
+ write 'src/test/scala/PassingSuite.scala', <<-SCALA
+ class PassingSuite extends org.scalatest.FunSuite {
+ test("passing") {
+ assert(true)
+ }
+ }
+ SCALA
+ define 'foo' do
+ test.report_to.should be(file('reports/scalatest'))
+ end
+ project('foo').test.invoke
+ project('foo').file('reports/scalatest/TEST-PassingSuite.txt').should exist
+ end
+
+ it 'should pass properties to Suite' do
+ write 'src/test/scala/PropertyTestSuite.scala', <<-SCALA
+ import org.scalatest._
+ class PropertyTestSuite extends FunSuite {
+ var properties = Map[String, Any]()
+ test("testProperty") {
+ assert(properties("name") === "value")
+ }
+
+ protected override def runTests(testName: Option[String], reporter:
Reporter, stopper: Stopper,
+ includes: Set[String], excludes:
Set[String], properties: Map[String, Any]) {
+ this.properties = properties;
+ super.runTests(testName, reporter, stopper, includes, excludes,
properties)
+ }
+ }
+ SCALA
+ define('foo').test.using :properties=>{ 'name'=>'value' }
+ project('foo').test.invoke
+ end
+
+ it 'should set current directory' do
+ mkpath 'baz'
+ expected = File.expand_path('baz')
+ expected.gsub!('/', '\\') if expected =~ /^[A-Z]:/ # Java returns back
slashed paths for windows
+ write 'baz/src/test/scala/CurrentDirectoryTestSuite.scala', <<-SCALA
+ class CurrentDirectoryTestSuite extends org.scalatest.FunSuite {
+ test("testCurrentDirectory") {
+ assert("value" === System.getenv("NAME"))
+ assert(#{expected.inspect} === new
java.io.File(".").getCanonicalPath())
+ }
+ }
+ SCALA
+ define 'bar' do
+ define 'baz' do
+ test.include 'CurrentDirectoryTest'
+ end
+ end
+ project('bar:baz').test.invoke
+ end
+
+end
+