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

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

The newest version!
/*
 * 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.scalatest.exceptions.StackDepthExceptionHelper.getStackDepthFun
import scala.annotation.tailrec

/**
 * Trait containing the inside construct, which allows you to make statements about nested object graphs using pattern matching.
 *
 * 

* For example, given the following case classes: * *

 * case class Address(street: String, city: String, state: String, zip: String)
 * case class Name(first: String, middle: String, last: String)
 * case class Record(name: Name, address: Address, age: Int)
 * 
* * You could write: * *
 * inside (rec) { case Record(name, address, age) =>
 *   inside (name) { case Name(first, middle, last) =>
 *     first should be ("Sally")
 *     middle should be ("Ann")
 *     last should be ("Jones")
 *   }
 *   inside (address) { case Address(street, city, state, zip) =>
 *     street should startWith ("25")
 *     city should endWith ("Angeles")
 *     state should equal ("CA")
 *     zip should be ("12345")
 *   }
 *   age should be < 99
 * }
 * 
* *

* If an assertion fails, the error message will include the toString of each value passed * to inside clauses enclosing the failed assertion. For example, if rec in * the previous expression was defined like this: *

* *
 * val rec = Record(
 *   Name("Sally", "Anna", "Jones"),
 *   Address("25 Main St", "Los Angeles", "CA", "12345"),
 *   38
 * )
 * 
* *

* The error message will read: *

* *
 * "Ann[a]" was not equal to "Ann[]", inside Name(Sally,Anna,Jones),
 * inside Record(Name(Sally,Anna,Jones),Address(25 Main St,Los Angeles,CA,12345),38)
 * 
* */ trait Inside { /** * Inspects inside the passed value using the passed partial function. * *

* The inside method checks to see whether the partial function passed as the second curried * parameter is defined at the value passed as the first parameter, and if so, passes that value to the * partial function. *

* *

* If the partial function is not defined at the passed value, inside will throw a * TestFailedException with a detail message describing the problem. Otherwise, if the * partial function returns normally, inside will return normally. If the partial function * completes abruptly with an exception that mixes in ModifiableMessage (such as * TestFailedException), inside will append the value's toString of * to the exception's detail message, and rethrow it. If the exception thrown by the partial function does not mix * in ModifiableMessage, inside completes abruptly with that same exception. *

* * @param value the value inside of which to inspect * @param pf the partial function to use to inspect inside the passed value * @throws TestFailedException if the passed partial function is not defined at the passed value */ def inside[T](value: T)(pf: PartialFunction[T, Unit]) { def appendInsideMessage(currentMessage: Option[String]) = { val st = Thread.currentThread.getStackTrace val levelCount = st.count { elem => elem.getClassName == "org.scalatest.Inside$class" && elem.getMethodName == "inside" } val indentation = " " * (levelCount - 1) currentMessage match { case Some(msg) => Some(Resources("insidePartialFunctionAppendSomeMsg", msg.trim, indentation, value.toString())) case None => Some(Resources("insidePartialFunctionAppendNone", indentation, value.toString())) } } if (pf.isDefinedAt(value)) { try { pf(value) } catch { case e: org.scalatest.exceptions.ModifiableMessage[_] => throw e.modifyMessage(appendInsideMessage) } } else throw new TestFailedException(sde => Some(Resources("insidePartialFunctionNotDefined", value.toString())), None, getStackDepthFun("Inside.scala", "inside")) //throw new TestFailedException(Resources("insidePartialFunctionNotDefined", value.toString()), 2) } } /** * Companion object that facilitates the importing of the inside construct as * an alternative to mixing it in. One use case is to import the inside construct so you can use * it in the Scala interpreter: * *
 * $ scala -cp scalatest-1.8.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.ShouldMatchers._
 * import matchers.ShouldMatchers._
 * 
 * scala> import Inside._
 * import Inside._
 * 
 * scala> inside (List(1, 2, 3)) { case List(x, y, z) =>
 *     |   y should equal (2)
 *     | }
 *
 * scala> inside (List(1, 2, 3)) { case List(x, y, z) =>
 *      |   x should equal (2)
 *      | }
 * org.scalatest.TestFailedException: 1 did not equal 2, inside List(1, 2, 3)
 *   at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:150)
 *   at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2331)
 *   at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(ShouldMatchers.scala:873)
 *   ...
 * 
*/ object Inside extends Inside




© 2015 - 2024 Weber Informatics LLC | Privacy Policy