org.scalatestplus.junit.JUnitRunner.scala Maven / Gradle / Ivy
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed 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.
*/
package org.scalatestplus.junit
import org.scalatest._
import org.junit.runner.notification.RunNotifier
import org.junit.runner.notification.Failure
import org.junit.runner.Description
import org.junit.runner.manipulation.{Filter => TestFilter, Filterable, NoTestsRemainException}
/*
I think that Stopper really should be a no-op, like it is, because the user has
no way to stop it. This is wierd, because it will call nested suites. So the tests
just pile up. Oh, I see, the darn information about which test it is is in the
stupid Description displayName. We probably need to add optional test name and
suite class name to Report, just to satisfy JUnit integration.
*/
/**
* A JUnit Runner
that knows how to run any ScalaTest Suite
.
* This enables you to provide a JUnit RunWith
annotation on any
* ScalaTest Suite
. Here's an example:
*
*
* import org.junit.runner.RunWith
* import org.scalatest.junit.JUnitRunner
* import org.scalatest.FunSuite
*
* @RunWith(classOf[JUnitRunner])
* class MySuite extends FunSuite {
* // ...
* }
*
*
*
* This RunWith
annotation will enable the MySuite
class
* to be run by JUnit 4.
*
*
* @param suiteClass suite class to be run
*
* @author Bill Venners
* @author Daniel Watson
* @author Jon-Anders Teigen
* @author Colin Howe
*/
final class JUnitRunner(suiteClass: java.lang.Class[_ <: Suite]) extends org.junit.runner.Runner with Filterable {
private val canInstantiate = JUnitHelper.checkForPublicNoArgConstructor(suiteClass)
require(canInstantiate, "Must pass an org.scalatest.Suite with a public no-arg constructor")
private val suiteToRun = suiteClass.newInstance
/**
* Get a JUnit Description
for this ScalaTest Suite
of tests.
*
* return a Description
of this suite of tests
*/
val getDescription = createDescription(suiteToRun)
private def createDescription(suite: Suite): Description = {
val description = Description.createSuiteDescription(suite.getClass)
// If we don't add the testNames and nested suites in, we get
// Unrooted Tests show up in Eclipse
for (name <- suite.testNames) {
description.addChild(Description.createTestDescription(suite.getClass, name))
}
for (nestedSuite <- suite.nestedSuites) {
description.addChild(createDescription(nestedSuite))
}
description
}
/**
* Run this Suite
of tests, reporting results to the passed RunNotifier
.
* This class's implementation of this method invokes run
on an instance of the
* suiteClass
Class
passed to the primary constructor, passing
* in a Reporter
that forwards to the RunNotifier
passed to this
* method as notifier
.
*
* @param notifier the JUnit RunNotifier
to which to report the results of executing
* this suite of tests
*/
def run(notifier: RunNotifier): Unit = {
try {
// TODO: What should this Tracker be?
suiteToRun.run(None, Args(new RunNotifierReporter(notifier),
Stopper.default, Filter(), ConfigMap.empty, None,
new Tracker))
}
catch {
case e: Exception =>
notifier.fireTestFailure(new Failure(getDescription, e))
}
}
/**
* Returns the number of tests that are expected to run when this ScalaTest Suite
* is run.
*
* @return the expected number of tests that will run when this suite is run
*/
override def testCount() = suiteToRun.expectedTestCount(Filter())
override def filter(filter: TestFilter): Unit = {
if (!filter.shouldRun(getDescription)) throw new NoTestsRemainException
}
}