All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalatest.ParallelTestExecution.scala Maven / Gradle / Ivy

There is a newer version: 2.0.M6-SNAP27
Show newest version
/*
 * Copyright 2001-2009 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.scalatest    

import tools.DistributedTestRunnerSuite

/**
 * Trait that causes that the tests of any suite it is mixed into to be run in parallel if
 * a Distributor is passed to runTests.
 *
 * 

* ScalaTest's normal approach for running suites of tests in parallel is to run different suites in parallel, * but the tests of any one suite sequentially. This approach should provide sufficient distribution of the work load * in most cases, but some suites may encapsulate multiple long-running tests. Such suites may dominate the execution * time of the run. If so, mixing in this trait into just those suites will allow their long-running tests to run in parallel with each * other, thereby helping to reduce the total time required to run an entire run. *

* *

* Because this trait extends OneInstancePerTest, * each test will be run its own instance of the suite's class. This trait overrides the * runTests method. If no Distributor is passed to runTests, * this trait's implementation simply invokes its supertrait OneInstancePerTest's implementation * of runTests, which will run each test in its own instance sequentially. If a Distributor * is passed, however, this traits' implementation of runTests will, for each test, wrap a new instance of the * suite in a special wrapper suite that will invoke just that one test, and passes the wrapper suites to the Distributor. * The thread or entity that takes a wrapper suite from the Distributor will invoke run * on the wrapper suite, which will run just one test. In this way, different tests of a suite that mixes in * ParallelTestExecution will run in parallel. *

* * @author Bill Venners */ trait ParallelTestExecution extends OneInstancePerTest { this: Suite => // Skipping runTests here, but that's OK, because by mixing in ParallelTestExecution, the programmer decided // that the super.runTests should be replaced by the one defined in ParallelTestExecution. private[scalatest] def runOneTest(testName: String, reporter: Reporter, stopper: Stopper, configMap: Map[String, Any], tracker: Tracker) { runTest(testName, reporter, stopper, configMap, tracker) } /** * Run the tests of this suite in parallel. * * @param testName an optional name of one test to run. If None, all relevant tests should be run. * I.e., None acts like a wildcard that means run all relevant tests in this Suite. * @param reporter the Reporter to which results will be reported * @param stopper the Stopper that will be consulted to determine whether to stop execution early. * @param filter a Filter with which to filter tests based on their tags * @param configMap a Map of key-value pairs that can be used by the executing Suite of tests. * @param distributor an optional Distributor, into which to put nested Suites to be run * by another entity, such as concurrently by a pool of threads. If None, nested Suites will be run sequentially. * @param tracker a Tracker tracking Ordinals being fired by the current thread. * @throws NullPointerException if any of the passed parameters is null. * @throws IllegalArgumentException if testName is defined, but no test with the specified test name * exists in this Suite */ protected abstract override def runTests(testName: Option[String], reporter: Reporter, stopper: Stopper, filter: Filter, configMap: Map[String, Any], distributor: Option[Distributor], tracker: Tracker) { // testName distributor // None None call super, because no distributor // Some None call super, because no distributor // None Some wrap a newInstance and put it in the distributor // Some Some this would be the one where we need to actually run the test, ignore the distributor distributor match { // If there's no distributor, then just run sequentially, via the regular OneInstancePerTest // algorithm case None => super.runTests(testName, reporter,stopper, filter, configMap, distributor, tracker) case Some(distribute) => testName match { // The only way both testName and distributor should be defined is if someone called from the // outside and did this. First run is called with testName None and a defined Distributor, it // will not get here. So in this case, just do the usual OneInstancePerTest thing. // TODO: Make sure it doesn't get back here. Walk through the scenarios. case Some(tn) => super.runTests(testName, reporter, stopper, filter, configMap, distributor, tracker) case None => for (tn <- testNames) { val wrappedInstance = new DistributedTestRunnerSuite( newInstance.asInstanceOf[ParallelTestExecution], tn ) distribute(wrappedInstance, tracker.nextTracker) } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy