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

org.scalatest.PartialFunctionValues.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.scalatest

import org.scalactic._
import org.scalatest.exceptions.StackDepthException
import org.scalatest.exceptions.TestFailedException

/**
 * Trait that provides an implicit conversion that adds a valueAt method
 * to PartialFunction, which will return the value (result) of the function applied to the argument passed to valueAt,
 * or throw TestFailedException if the partial function is not defined at the argument.
 *
 * 

* This construct allows you to express in one statement that a partial function should be defined for a particular input, * and that its result value should meet some expectation. Here's an example: *

* *
 * pf.valueAt("IV") should equal (4)
 * 
* *

* Or, using an assertion instead of a matcher expression: *

* *
 * assert(pf.valueAt("IV") === 4)
 * 
* *

* Were you to simply invoke apply on the PartialFunction, passing in an input value, * if the partial function wasn't defined at that input, it would throw some exception, but likely not one * that provides a stack depth: *

* *
 * // Note: a Map[K, V] is a PartialFunction[K, V]
 * val pf: PartialFunction[String, Int] = Map("I" -> 1, "II" -> 2, "III" -> 3, "IV" -> 4)
 *
 * pf("V") should equal (5) // pf("V") throws NoSuchElementException
 * 
* *

* The NoSuchElementException thrown in this situation would cause the test to fail, but without providing a stack depth pointing * to the failing line of test code. This stack depth, provided by TestFailedException (and a * few other ScalaTest exceptions), makes it quicker for * users to navigate to the cause of the failure. Without PartialFunctionValues, to get * a stack depth exception you would need to make two statements, like this: *

* *
 * val pf: PartialFunction[String, Int] = Map("I" -> 1, "II" -> 2, "III" -> 3, "IV" -> 4)
 *
 * pf.isDefinedAt("V") should be (true) // throws TestFailedException
 * pf("V") should equal (5)
 * 
* *

* The PartialFunctionValues trait allows you to state that more concisely: *

* *
 * val pf: PartialFunction[String, Int] = Map("I" -> 1, "II" -> 2, "III" -> 3, "IV" -> 4)
 *
 * pf.valueAt("V") should equal (5) // pf.valueAt("V") throws TestFailedException
 * 
*/ trait PartialFunctionValues { import scala.language.implicitConversions /** * Implicit conversion that adds a valueAt method to PartialFunction. * * @param pf the PartialFunction on which to add the valueAt method */ implicit def convertPartialFunctionToValuable[A, B](pf: PartialFunction[A, B])(implicit pos: source.Position): Valuable[A, B] = new Valuable(pf, pos) /** * Wrapper class that adds a valueAt method to PartialFunction, allowing * you to make statements like: * *
   * pf.valueAt("VI") should equal (6)
   * 
* * @param pf An PartialFunction to convert to Valuable, which provides the valueAt method. */ class Valuable[A, B](pf: PartialFunction[A, B], pos: source.Position) { /** * Returns the result of applying the wrapped PartialFunction to the passed input, if it is defined at that input, else * throws TestFailedException with a detail message indicating the PartialFunction was not defined at the given input. */ def valueAt(input: A): B = { if (pf.isDefinedAt(input)) { pf.apply(input) } else throw new TestFailedException((_: StackDepthException) => Some(Resources.partialFunctionValueNotDefined(input.toString)), None, pos) } } } /** * Companion object that facilitates the importing of PartialFunctionValues members as * an alternative to mixing it in. One use case is to import PartialFunctionValues's members so you can use * the valueAt method on PartialFunction in the Scala interpreter: * *
 * $ scala -cp scalatest-1.7.jar
 * Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
 * Type in expressions to have them evaluated.
 * Type :help for more information.
 * 
 * scala> import org.scalatest._
 * import org.scalatest._
 * 
 * scala> import matchers.Matchers._
 * import matchers.Matchers._
 * 
 * scala> import PartialFunctionValues._
 * import PartialFunctionValues._
 * 
 * scala> val pf: PartialFunction[String, Int] = Map("I" -> 1, "II" -> 2, "III" -> 3, "IV" -> 4)
 * pf: PartialFunction[String,Int] = Map(I -> 1, II -> 2, III -> 3, IV -> 4)
 * 
 * scala> pf("IV") should equal (4)
 * 
 * scala> pf("V") should equal (5)
 * java.util.NoSuchElementException: key not found: V
 *   at scala.collection.MapLike$class.default(MapLike.scala:224)
 *   at scala.collection.immutable.Map$Map4.default(Map.scala:167)
 *   ...
 * 
*/ object PartialFunctionValues extends PartialFunctionValues




© 2015 - 2024 Weber Informatics LLC | Privacy Policy