org.scalatest.Assertions.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 exceptions.TestCanceledException import scala.reflect.Manifest import Assertions.areEqualComparingArraysStructurally import org.scalactic.TripleEquals import exceptions.StackDepthExceptionHelper.getStackDepthFun import exceptions.StackDepthException.toExceptionFunction import Assertions.NormalResult import org.scalactic.{Prettifier, Bool} /** * Trait that contains ScalaTest's basic assertion methods. * *Equalizer. * * ** You can use the assertions provided by this trait in any ScalaTest
* *Suite, * becauseSuite* mixes in this trait. This trait is designed to be used independently of anything else in ScalaTest, though, so you * can mix it into anything. (You can alternatively import the methods defined in this trait. For details, see the documentation * for theAssertionscompanion object. ** In any Scala program, you can write assertions by invoking
* *assertand passing in aBooleanexpression, * such as: ** val left = 2 * val right = 1 * assert(left == right) ** ** If the passed expression is
true,assertwill return normally. Iffalse, * Scala'sassertwill complete abruptly with anAssertionError. This behavior is provided by * theassertmethod defined in objectPredef, whose members are implicitly imported into every * Scala source file. ThisAssertionstrait defines anotherassertmethod that hides the * one inPredef. It behaves the same, except that iffalseis passed it throws *TestFailedExceptioninstead ofAssertionError. * Why? Because unlikeAssertionError,TestFailedExceptioncarries information about exactly * which item in the stack trace represents * the line of test code that failed, which can help users more quickly find an offending line of code in a failing test. ** *
* If you pass the previous
Booleanexpression,left == righttoassertin a ScalaTest test, * a failure will be reported that, becauseassertis implemented as a macro, * includes reporting the left and right values. * * For example, given the same code as above but using ScalaTest assertions: * ** import org.scalatest.Assertions._ * val left = 2 * val right = 1 * assert(left == right) ** ** The detail message in the thrown
* *TestFailedExceptionfrom thisassert* will be: "2 did not equal 1". ** ScalaTest's
* *assertmacro works by recognizing patterns in the AST of the expression passed toassertand, * for a finite set of common expressions, giving an error message that an equivalent ScalaTest matcher * expression would give. Here are some examples, whereais 1,bis 2,cis 3,d* is 4,xsisList(a, b, c), andnumis 1.0: ** assert(a == b || c >= d) * // Error message: 1 did not equal 2, and 3 was not greater than or equal to 4 * * assert(xs.exists(_ == 4)) * // Error message: List(1, 2, 3) did not contain 4 * * assert("hello".startsWith("h") && "goodbye".endsWith("y")) * // Error message: "hello" started with "h", but "goodbye" did not end with "y" * * assert(num.isInstanceOf[Int]) * // Error message: 1.0 was not instance of scala.Int * * assert(Some(2).isEmpty) * // Error message: Some(2) was not empty ** ** For expressions that are not recognized, the macro currently prints out a string * representation of the (desugared) AST and adds
* *"was false". Here are some examples of * error messages for unrecognized expressions: ** assert(None.isDefined) * // Error message: scala.None.isDefined was false * * assert(xs.exists(i => i > 10)) * // Error message: xs.exists(((i: Int) => i.>(10))) was false ** ** You can augment the standard error message by providing a
* *Stringas a second argument * toassert, like this: ** val attempted = 2 * assert(attempted == 1, "Execution was attempted " + left + " times instead of 1 time") ** ** Using this form of
* * *assert, the failure report will be more specific to your problem domain, thereby * helping you debug the problem. ThisAssertionstrait also mixes in the *TripleEquals, which gives you a===operator * that allows you to customizeEquality, perform equality checks with numeric *Tolerance, and enforce type constraints at compile time with * sibling traitsTypeCheckedTripleEqualsand *ConversionCheckedTripleEquals. *Expected results
* * Although theassertmacro provides a natural, readable extension to Scala'sassertmechanism that * provides good error messages, as the operands become lengthy, the code becomes less readable. In addition, the error messages * generated for==and===comparisons * don't distinguish between actual and expected values. The operands are just calledleftandright, * because if one were namedexpectedand the otheractual, it would be difficult for people to * remember which was which. To help with these limitations of assertions,Suiteincludes a method calledassertResultthat * can be used as an alternative toassert. To useassertResult, you place * the expected value in parentheses afterassertResult, followed by curly braces containing code * that should result in the expected value. For example: * ** val a = 5 * val b = 2 * assertResult(2) { * a - b * } ** ** In this case, the expected value is
* * *2, and the code being tested isa - b. This assertion will fail, and * the detail message in theTestFailedExceptionwill read, "Expected 2, but got 3." *Forcing failures
* ** If you just need the test to fail, you can write: *
* ** fail() ** ** Or, if you want the test to fail with a message, write: *
* ** fail("I've got a bad feeling about this") ** * *Intercepted exceptions
* ** Sometimes you need to test whether a method throws an expected exception under certain circumstances, such * as when invalid arguments are passed to the method. You can do this in the JUnit 3 style, like this: *
* ** val s = "hi" * try { * s.charAt(-1) * fail() * } * catch { * case _: IndexOutOfBoundsException => // Expected, so continue * } ** ** If
* *charAtthrowsIndexOutOfBoundsExceptionas expected, control will transfer * to the catch case, which does nothing. If, however,charAtfails to throw an exception, * the next statement,fail(), will be run. Thefailmethod always completes abruptly with * aTestFailedException, thereby signaling a failed test. ** To make this common use case easier to express and read, ScalaTest provides an
* *intercept* method. You use it like this: ** val s = "hi" * intercept[IndexOutOfBoundsException] { * s.charAt(-1) * } ** ** This code behaves much like the previous example. If
* * *charAtthrows an instance ofIndexOutOfBoundsException, *interceptwill return that exception. But ifcharAtcompletes normally, or throws a different * exception,interceptwill complete abruptly with aTestFailedException.interceptreturns the * caught exception so that you can inspect it further if you wish, for example, to ensure that data contained inside * the exception has the expected values. *Checking that a snippet of code does or does not compile
* ** Often when creating libraries you may wish to ensure that certain arrangements of code that * represent potential “user errors” do not compile, so that your library is more error resistant. * ScalaTest's
* *Assertionstrait includes the following syntax for that purpose: ** assertDoesNotCompile("val a: String = 1") ** ** If you want to ensure that a snippet of code does not compile because of a type error (as opposed * to a syntax error), use: *
* ** assertTypeError("val a: String = 1") ** ** Note that the
* *assertTypeErrorcall will only succeed if the given snippet of code does not * compile because of a type error. A syntax error will still result on a thrownTestFailedException. ** If you want to state that a snippet of code does compile, you can make that * more obvious with: *
* ** assertCompiles("val a: Int = 1") ** ** Although the previous three constructs are implemented with macros that determine at compile time whether * the snippet of code represented by the string does or does not compile, errors * are reported as test failures at runtime. *
* * *Assumptions
* ** Trait
* *Assertionsalso provides methods that allow you to cancel a test. * You would cancel a test if a resource required by the test was unavailable. For example, if a test * requires an external database to be online, and it isn't, the test could be canceled to indicate * it was unable to run because of the missing database. Such a test assumes a database is * available, and you can use theassumemethod to indicate this at the beginning of * the test, like this: ** assume(database.isAvailable) ** ** For each overloaded
* *assertmethod, traitAssertionsprovides an * overloadedassumemethod with an identical signature and behavior, except the *assumemethods throwTestCanceledExceptionwhereas the *assertmethods throwTestFailedException. As withassert, *assumehides a Scala method inPredefthat performs a similar * function, but throwsAssertionError. And just as you can withassert, * you will get an error message extracted by a macro from the AST passed toassume, and can * optionally provide a clue string to augment this error message. Here are some examples: ** assume(database.isAvailable, "The database was down again") * assume(database.getAllUsers.count === 9) ** * *Forcing cancelations
* ** For each overloaded
* *failmethod, there's a correspondingcancelmethod * with an identical signature and behavior, except thecancelmethods throw *TestCanceledExceptionwhereas thefailmethods throw *TestFailedException. Thus if you just need to cancel a test, you can write: ** cancel() ** ** If you want to cancel the test with a message, just place the message in the parentheses: *
* ** cancel("Can't run the test because no internet connection was found") ** * *Getting a clue
* ** If you want more information that is provided by default by the methods if this trait, * you can supply a "clue" string in one of several ways. * The extra information (or "clues") you provide will * be included in the detail message of the thrown exception. Both *
* *assertandassertResultprovide a way for a clue to be * included directly,interceptdoes not. * Here's an example of clues provided directly inassert: ** assert(1 + 1 === 3, "this is a clue") ** ** and in
* *assertResult: ** assertResult(3, "this is a clue") { 1 + 1 } ** ** The exceptions thrown by the previous two statements will include the clue * string,
* *"this is a clue", in the exception's detail message. * To get the same clue in the detail message of an exception thrown * by a failedinterceptcall requires usingwithClue: ** withClue("this is a clue") { * intercept[IndexOutOfBoundsException] { * "hi".charAt(-1) * } * } ** ** The
* *withCluemethod will only prepend the clue string to the detail * message of exception types that mix in theModifiableMessagetrait. * See the documentation forModifiableMessagefor more information. * If you wish to place a clue string after a block of code, see the documentation for *AppendedClues. ** Note: ScalaTest's
* * @author Bill Venners */ trait Assertions extends TripleEquals { import language.experimental.macros /** * Assert that a boolean condition is true. * If the condition isassertTypeErrorconstruct is in part inspired by theillTypedmacro * of shapeless. *true, this method returns normally. * Else, it throwsTestFailedException. * ** This method is implemented in terms of a Scala macro that will generate a more helpful error message * for expressions of this form: *
* **
* *- assert(a == b)
*- assert(a != b)
*- assert(a === b)
*- assert(a !== b)
*- assert(a > b)
*- assert(a >= b)
*- assert(a < b)
*- assert(a <= b)
*- assert(a startsWith "prefix")
*- assert(a endsWith "postfix")
*- assert(a contains "something")
*- assert(a eq b)
*- assert(a ne b)
*- assert(a > 0 && b > 5)
*- assert(a > 0 || b > 5)
*- assert(a.isEmpty)
*- assert(!a.isEmpty)
*- assert(a.isInstanceOf[String])
*- assert(a.length == 8)
*- assert(a.size == 8)
*- assert(a.exists(_ == 8))
** At this time, any other form of expression will get a
* * @param condition the boolean condition to assert * @throws TestFailedException if the condition isTestFailedExceptionwith message saying the given * expression was false. In the future, we will enhance this macro to give helpful error messages in more situations. * In ScalaTest 2.0, however, this behavior was sufficient to allow the===that returnsBoolean, * notOption[String]to be the default in tests. This makes===consistent between tests and production * code. If you have pre-existing code you wrote under ScalaTest 1.x, in which you are expecting===to return an *Option[String], use can get that behavior back by mixing in traitLegacyTripleEquals. *false. */ def assert(condition: Boolean): Unit = macro AssertionsMacro.assert /** * Helper class used by code generated by theassertmacro. */ class AssertionsHelper { private def append(currentMessage: Option[String], clue: Any) = { val clueStr = clue.toString if (clueStr.isEmpty) currentMessage else { currentMessage match { case Some(msg) => // clue.toString.head is guaranteed to work, because the previous if check that clue.toString != "" val firstChar = clueStr.head if (firstChar.isWhitespace || firstChar == '.' || firstChar == ',' || firstChar == ';') Some(msg + clueStr) else Some(msg + " " + clueStr) case None => Some(clueStr) } } } /** * Assert that the passed inBoolistrue, else fail withTestFailedException. * * @param bool theBoolto assert for * @param clue optional clue to be included inTestFailedException's error message when assertion failed */ def macroAssert(bool: Bool, clue: Any) { if (clue == null) throw new NullPointerException("clue was null") if (!bool.value) { val failureMessage = if (Bool.isSimpleWithoutExpressionText(bool)) None else Some(bool.failureMessage) throw newAssertionFailedException(append(failureMessage, clue), None, "Assertions.scala", "macroAssert", 2) } } /** * Assume that the passed inBoolistrue, else throwTestCanceledException. * * @param bool theBoolto assume for * @param clue optional clue to be included inTestCanceledException's error message when assertion failed */ def macroAssume(bool: Bool, clue: Any) { if (clue == null) throw new NullPointerException("clue was null") if (!bool.value) { val failureMessage = if (Bool.isSimpleWithoutExpressionText(bool)) None else Some(bool.failureMessage) throw newTestCanceledException(append(failureMessage, clue), None, "Assertions.scala", "macroAssume", 2) } } } /** * Helper instance used by code generated by macro assertion. */ val assertionsHelper = new AssertionsHelper private[scalatest] def newAssertionFailedException(optionalMessage: Option[Any], optionalCause: Option[Throwable], stackDepth: Int): Throwable = (optionalMessage, optionalCause) match { case (None, None) => new TestFailedException(stackDepth) case (None, Some(cause)) => new TestFailedException(cause, stackDepth) case (Some(message), None) => new TestFailedException(message.toString, stackDepth) case (Some(message), Some(cause)) => new TestFailedException(message.toString, cause, stackDepth) } private[scalatest] def newAssertionFailedException(optionalMessage: Option[String], optionalCause: Option[Throwable], fileName: String, methodName: String, stackDepthAdjustment: Int): Throwable = new exceptions.TestFailedException(toExceptionFunction(optionalMessage), optionalCause, getStackDepthFun(fileName, methodName, stackDepthAdjustment)) private def newTestCanceledException(optionalMessage: Option[Any], optionalCause: Option[Throwable], stackDepth: Int): Throwable = (optionalMessage, optionalCause) match { case (None, None) => new TestCanceledException(stackDepth) case (None, Some(cause)) => new TestCanceledException(cause, stackDepth) case (Some(message), None) => new TestCanceledException(message.toString, stackDepth) case (Some(message), Some(cause)) => new TestCanceledException(message.toString, cause, stackDepth) } private[scalatest] def newTestCanceledException(optionalMessage: Option[String], optionalCause: Option[Throwable], fileName: String, methodName: String, stackDepthAdjustment: Int): Throwable = new TestCanceledException(toExceptionFunction(optionalMessage), optionalCause, getStackDepthFun(fileName, methodName, stackDepthAdjustment), None) /** * Assert that a boolean condition, described inString*message, is true. * If the condition istrue, this method returns normally. * Else, it throwsTestFailedExceptionwith a helpful error message * appended with theStringobtained by invokingtoStringon the * specifiedclueas the exception's detail message. * ** This method is implemented in terms of a Scala macro that will generate a more helpful error message * for expressions of this form: *
* **
* *- assert(a == b, "a good clue")
*- assert(a != b, "a good clue")
*- assert(a === b, "a good clue")
*- assert(a !== b, "a good clue")
*- assert(a > b, "a good clue")
*- assert(a >= b, "a good clue")
*- assert(a < b, "a good clue")
*- assert(a <= b, "a good clue")
*- assert(a startsWith "prefix", "a good clue")
*- assert(a endsWith "postfix", "a good clue")
*- assert(a contains "something", "a good clue")
*- assert(a eq b, "a good clue")
*- assert(a ne b, "a good clue")
*- assert(a > 0 && b > 5, "a good clue")
*- assert(a > 0 || b > 5, "a good clue")
*- assert(a.isEmpty, "a good clue")
*- assert(!a.isEmpty, "a good clue")
*- assert(a.isInstanceOf[String], "a good clue")
*- assert(a.length == 8, "a good clue")
*- assert(a.size == 8, "a good clue")
*- assert(a.exists(_ == 8), "a good clue")
** At this time, any other form of expression will just get a
* * @param condition the boolean condition to assert * @param clue An objects whoseTestFailedExceptionwith message saying the given * expression was false. In the future, we will enhance this macro to give helpful error messages in more situations. * In ScalaTest 2.0, however, this behavior was sufficient to allow the===that returnsBoolean, * notOption[String]to be the default in tests. This makes===consistent between tests and production * code. If you have pre-existing code you wrote under ScalaTest 1.x, in which you are expecting===to return an *Option[String], use can get that behavior back by mixing in traitLegacyTripleEquals. *toStringmethod returns a message to include in a failure report. * @throws TestFailedException if the condition isfalse. * @throws NullPointerException ifmessageisnull. */ def assert(condition: Boolean, clue: Any): Unit = macro AssertionsMacro.assertWithClue /** * Assert that anOption[String]isNone. * If the condition isNone, this method returns normally. * Else, it throwsTestFailedExceptionwith theString* value of theSome, as well as the *Stringobtained by invokingtoStringon the * specifiedclue, * included in theTestFailedException's detail message. * ** This form of
* *assertis usually called in conjunction with an * implicit conversion toEqualizer, using a===comparison, as in: ** assert(a === b, "extra info reported if assertion fails") ** ** For more information on how this mechanism works, see the [[org.scalactic.TripleEqualsSupport.Equalizer documentation for *
* * @param o theEqualizer]]. *Option[String]to assert * @param clue An object whosetoStringmethod returns a message to include in a failure report. * @throws TestFailedException if theOption[String]isSome. * @throws NullPointerException ifmessageisnull. */ @deprecated("This method has been deprecated in favor of macro assertion and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.") def assert(o: Option[String], clue: Any) { o match { case Some(s) => throw newAssertionFailedException(Some(clue + "\n" + s), None, 4) case None => } } /** * Assert that anOption[String]isNone. * If the condition isNone, this method returns normally. * Else, it throwsTestFailedExceptionwith theString* value of theSomeincluded in theTestFailedException's * detail message. * ** This form of
* *assertis usually called in conjunction with an * implicit conversion toEqualizer, using a===comparison, as in: ** assert(a === b) ** ** For more information on how this mechanism works, see the [[org.scalactic.TripleEqualsSupport.Equalizer documentation for *
* * @param o theEqualizer]]. *Option[String]to assert * @throws TestFailedException if theOption[String]isSome. */ @deprecated("This method has been deprecated in favor of macro assertion and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.") def assert(o: Option[String]) { o match { case Some(s) => throw newAssertionFailedException(Some(s), None, 4) case None => } } /** * Assume that a boolean condition is true. * If the condition istrue, this method returns normally. * Else, it throwsTestCanceledException. * ** This method is implemented in terms of a Scala macro that will generate a more helpful error message * for expressions of this form: *
* **
* *- assume(a == b)
*- assume(a != b)
*- assume(a === b)
*- assume(a !== b)
*- assume(a > b)
*- assume(a >= b)
*- assume(a < b)
*- assume(a <= b)
*- assume(a startsWith "prefix")
*- assume(a endsWith "postfix")
*- assume(a contains "something")
*- assume(a eq b)
*- assume(a ne b)
*- assume(a > 0 && b > 5)
*- assume(a > 0 || b > 5)
*- assume(a.isEmpty)
*- assume(!a.isEmpty)
*- assume(a.isInstanceOf[String])
*- assume(a.length == 8)
*- assume(a.size == 8)
*- assume(a.exists(_ == 8))
** At this time, any other form of expression will just get a
* * @param condition the boolean condition to assume * @throws TestCanceledException if the condition isTestCanceledExceptionwith message saying the given * expression was false. In the future, we will enhance this macro to give helpful error messages in more situations. * In ScalaTest 2.0, however, this behavior was sufficient to allow the===that returnsBoolean, * notOption[String]to be the default in tests. This makes===consistent between tests and production * code. If you have pre-existing code you wrote under ScalaTest 1.x, in which you are expecting===to return an *Option[String], use can get that behavior back by mixing in traitLegacyTripleEquals. *false. */ def assume(condition: Boolean): Unit = macro AssertionsMacro.assume /** * Assume that a boolean condition, described inString*message, is true. * If the condition istrue, this method returns normally. * Else, it throwsTestCanceledExceptionwith a helpful error message * appended withStringobtained by invokingtoStringon the * specifiedclueas the exception's detail message. * ** This method is implemented in terms of a Scala macro that will generate a more helpful error message * for expressions of this form: *
* **
* *- assume(a == b, "a good clue")
*- assume(a != b, "a good clue")
*- assume(a === b, "a good clue")
*- assume(a !== b, "a good clue")
*- assume(a > b, "a good clue")
*- assume(a >= b, "a good clue")
*- assume(a < b, "a good clue")
*- assume(a <= b, "a good clue")
*- assume(a startsWith "prefix", "a good clue")
*- assume(a endsWith "postfix", "a good clue")
*- assume(a contains "something", "a good clue")
*- assume(a eq b, "a good clue")
*- assume(a ne b, "a good clue")
*- assume(a > 0 && b > 5, "a good clue")
*- assume(a > 0 || b > 5, "a good clue")
*- assume(a.isEmpty, "a good clue")
*- assume(!a.isEmpty, "a good clue")
*- assume(a.isInstanceOf[String], "a good clue")
*- assume(a.length == 8, "a good clue")
*- assume(a.size == 8, "a good clue")
*- assume(a.exists(_ == 8), "a good clue")
** At this time, any other form of expression will just get a
* * @param condition the boolean condition to assume * @param clue An objects whoseTestCanceledExceptionwith message saying the given * expression was false. In the future, we will enhance this macro to give helpful error messages in more situations. * In ScalaTest 2.0, however, this behavior was sufficient to allow the===that returnsBoolean, * notOption[String]to be the default in tests. This makes===consistent between tests and production * code. If you have pre-existing code you wrote under ScalaTest 1.x, in which you are expecting===to return an *Option[String], use can get that behavior back by mixing in traitLegacyTripleEquals. *toStringmethod returns a message to include in a failure report. * @throws TestCanceledException if the condition isfalse. * @throws NullPointerException ifmessageisnull. */ def assume(condition: Boolean, clue: Any): Unit = macro AssertionsMacro.assumeWithClue /** * Assume that anOption[String]isNone. * If the condition isNone, this method returns normally. * Else, it throwsTestCanceledExceptionwith theString* value of theSome, as well as the *Stringobtained by invokingtoStringon the * specifiedclue, * included in theTestCanceledException's detail message. * ** This form of
* *assumeis usually called in conjunction with an * implicit conversion toEqualizer, using a===comparison, as in: ** assume(a === b, "extra info reported if assertion fails") ** ** For more information on how this mechanism works, see the [[org.scalactic.TripleEqualsSupport.Equalizer documentation for *
* * @param o theEqualizer]]. *Option[String]to assert * @param clue An object whosetoStringmethod returns a message to include in a failure report. * @throws TestCanceledException if theOption[String]isSome. * @throws NullPointerException ifmessageisnull. */ @deprecated("This method has been deprecated in favor of macro assumption and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.") def assume(o: Option[String], clue: Any) { o match { case Some(s) => throw newTestCanceledException(Some(clue + "\n" + s), None, 3) case None => } } /** * Assume that anOption[String]isNone. * If the condition isNone, this method returns normally. * Else, it throwsTestCanceledExceptionwith theString* value of theSomeincluded in theTestCanceledException's * detail message. * ** This form of
* *assumeis usually called in conjunction with an * implicit conversion toEqualizer, using a===comparison, as in: ** assume(a === b) ** ** For more information on how this mechanism works, see the [[org.scalactic.TripleEqualsSupport.Equalizer documentation for *
* * @param o theEqualizer]]. *Option[String]to assert * @throws TestCanceledException if theOption[String]isSome. */ // def assume(o: Option[String]) = throwIfSome(o, (a: Any) => newTestCanceledException(Some(a.toString), None, 3)) @deprecated("This method has been deprecated in favor of macro assumption and will be removed in a future version of ScalaTest. If you need this, please copy the source code into your own trait instead.") def assume(o: Option[String]) { o match { case Some(s) => throw newTestCanceledException(Some(s), None, 3) case None => } } /** * Asserts that a given string snippet of code does not pass the Scala type checker, failing if the given * snippet does not pass the Scala parser. * ** Often when creating libraries you may wish to ensure that certain arrangements of code that * represent potential “user errors” do not compile, so that your library is more error resistant. * ScalaTest's
* *Assertionstrait includes the following syntax for that purpose: ** assertTypeError("val a: String = 1") ** ** Although
* *assertTypeErroris implemented with a macro that determines at compile time whether * the snippet of code represented by the passed string type checks, errors (i.e., * snippets of code that do type check) are reported as test failures at runtime. ** Note that the difference between
* * @param code the snippet of code that should not type check */ def assertTypeError(code: String): Unit = macro CompileMacro.assertTypeErrorImpl /** * Asserts that a given string snippet of code does not pass either the Scala parser or type checker. * *assertTypeErrorandassertDoesNotCompileis * thatassertDoesNotCompilewill succeed if the given code does not compile for any reason, * whereasassertTypeErrorwill only succeed if the given code does not compile because of * a type error. If the given code does not compile because of a syntax error, for example,assertDoesNotCompile* will return normally butassertTypeErrorwill throw aTestFailedException. ** Often when creating libraries you may wish to ensure that certain arrangements of code that * represent potential “user errors” do not compile, so that your library is more error resistant. * ScalaTest's
* *Assertionstrait includes the following syntax for that purpose: ** assertDoesNotCompile("val a: String = \"a string") ** ** Although
* *assertDoesNotCompileis implemented with a macro that determines at compile time whether * the snippet of code represented by the passed string doesn't compile, errors (i.e., * snippets of code that do compile) are reported as test failures at runtime. ** Note that the difference between
* * @param code the snippet of code that should not type check */ def assertDoesNotCompile(code: String): Unit = macro CompileMacro.assertDoesNotCompileImpl /** * Asserts that a given string snippet of code passes both the Scala parser and type checker. * *assertTypeErrorandassertDoesNotCompileis * thatassertDoesNotCompilewill succeed if the given code does not compile for any reason, * whereasassertTypeErrorwill only succeed if the given code does not compile because of * a type error. If the given code does not compile because of a syntax error, for example,assertDoesNotCompile* will return normally butassertTypeErrorwill throw aTestFailedException. ** You can use this to make sure a snippet of code compiles: *
* ** assertCompiles("val a: Int = 1") ** ** Although
* * @param code the snippet of code that should compile */ def assertCompiles(code: String): Unit = macro CompileMacro.assertCompilesImpl /* * * Implicit conversion fromassertCompilesis implemented with a macro that determines at compile time whether * the snippet of code represented by the passed string compiles, errors (i.e., * snippets of code that do not compile) are reported as test failures at runtime. *AnytoEqualizer, used to enable * assertions with===comparisons. * ** For more information * on this mechanism, see the documentation for
* Because trait
* *Suitemixes inAssertions, this implicit conversion will always be * available by default in ScalaTestSuites. This is the only implicit conversion that is in scope by default in every * ScalaTestSuite. Other implicit conversions offered by ScalaTest, such as those that support the matchers DSL * orinvokePrivate, must be explicitly invited into your test code, either by mixing in a trait or importing the * members of its companion object. The reason ScalaTest requires you to invite in implicit conversions (with the exception of the * implicit conversion for===operator) is because if one of ScalaTest's implicit conversions clashes with an * implicit conversion used in the code you are trying to test, your program won't compile. Thus there is a chance that if you * are ever trying to use a library or test some code that also offers an implicit conversion involving a===operator, * you could run into the problem of a compiler error due to an ambiguous implicit conversion. If that happens, you can turn off * the implicit conversion offered by thisconvertToEqualizermethod simply by overriding the method in your *Suitesubclass, but not marking it as implicit: ** // In your Suite subclass * override def convertToEqualizer(left: Any) = new Equalizer(left) ** * @param left the object whose type to convert toEqualizer. * @throws NullPointerException ifleftisnull. */ // implicit def convertToEqualizer(left: Any) = new Equalizer(left) /* * Intercept and return an instance of the passed exception class (or an instance of a subclass of the * passed class), which is expected to be thrown by the passed function value. This method invokes the passed * function. If it throws an exception that's an instance of the passed class or one of its * subclasses, this method returns that exception. Else, whether the passed function returns normally * or completes abruptly with a different exception, this method throwsTestFailedException* whose detail message includes theStringobtained by invokingtoStringon the passedclue. * ** Note that the passed
* * @param message An object whoseClassmay represent any type, not justThrowableor one of its subclasses. In * Scala, exceptions can be caught based on traits they implement, so it may at times make sense to pass in a class instance for * a trait. If a class instance is passed for a type that could not possibly be used to catch an exception (such asString, * for example), this method will complete abruptly with aTestFailedException. *toStringmethod returns a message to include in a failure report. * @param f the function value that should throw the expected exception * @return the intercepted exception, if it is of the expected type * @throws TestFailedException if the passed function does not result in a value equal to the * passedexpectedvalue. def intercept[T <: AnyRef](message: Any)(f: => Any)(implicit manifest: Manifest[T]): T = { val clazz = manifest.erasure.asInstanceOf[Class[T]] val messagePrefix = if (message.toString.trim.isEmpty) "" else (message +"\n") val caught = try { f None } catch { case u: Throwable => { if (!clazz.isAssignableFrom(u.getClass)) { val s = Resources("wrongException", clazz.getName, u.getClass.getName) throw newAssertionFailedException(Some(messagePrefix + s), Some(u), 4) } else { Some(u) } } } caught match { case None => val message = messagePrefix + Resources("exceptionExpected", clazz.getName) throw newAssertionFailedException(Some(message), None, 4) case Some(e) => e.asInstanceOf[T] // I know this cast will succeed, becuase iSAssignableFrom succeeded above } } THIS DOESN'T OVERLOAD. I THINK I'LL EITHER NEED TO USE interceptWithMessage OR JUST LEAVE IT OUT. FOR NOW I'LL LEAVE IT OUT. */ /** * Intercept and return an exception that's expected to * be thrown by the passed function value. The thrown exception must be an instance of the * type specified by the type parameter of this method. This method invokes the passed * function. If the function throws an exception that's an instance of the specified type, * this method returns that exception. Else, whether the passed function returns normally * or completes abruptly with a different exception, this method throwsTestFailedException. * ** Note that the type specified as this method's type parameter may represent any subtype of *
* * @param f the function value that should throw the expected exception * @param manifest an implicitAnyRef, not justThrowableor one of its subclasses. In * Scala, exceptions can be caught based on traits they implement, so it may at times make sense * to specify a trait that the intercepted exception's class must mix in. If a class instance is * passed for a type that could not possibly be used to catch an exception (such asString, * for example), this method will complete abruptly with aTestFailedException. *Manifestrepresenting the type of the specified * type parameter. * @return the intercepted exception, if it is of the expected type * @throws TestFailedException if the passed function does not complete abruptly with an exception * that's an instance of the specified type * passedexpectedvalue. */ def intercept[T <: AnyRef](f: => Any)(implicit manifest: Manifest[T]): T = { val clazz = manifest.erasure.asInstanceOf[Class[T]] val caught = try { f None } catch { case u: Throwable => { if (!clazz.isAssignableFrom(u.getClass)) { val s = Resources("wrongException", clazz.getName, u.getClass.getName) throw newAssertionFailedException(Some(s), Some(u), 4) } else { Some(u) } } } caught match { case None => val message = Resources("exceptionExpected", clazz.getName) throw newAssertionFailedException(Some(message), None, 4) case Some(e) => e.asInstanceOf[T] // I know this cast will succeed, becuase isAssignableFrom succeeded above } } /* * Intercept and return an instance of the passed exception class (or an instance of a subclass of the * passed class), which is expected to be thrown by the passed function value. This method invokes the passed * function. If it throws an exception that's an instance of the passed class or one of its * subclasses, this method returns that exception. Else, whether the passed function returns normally * or completes abruptly with a different exception, this method throwsTestFailedException. * ** Note that the passed
* * @param clazz a type to which the expected exception class is assignable, i.e., the exception should be an instance of the type represented byClassmay represent any type, not justThrowableor one of its subclasses. In * Scala, exceptions can be caught based on traits they implement, so it may at times make sense to pass in a class instance for * a trait. If a class instance is passed for a type that could not possibly be used to catch an exception (such asString, * for example), this method will complete abruptly with aTestFailedException. *clazz. * @param f the function value that should throw the expected exception * @return the intercepted exception, if * @throws TestFailedException if the passed function does not complete abruptly with an exception that is assignable to the * passedClass. * @throws IllegalArgumentException if the passedclazzis notThrowableor * one of its subclasses. */ /* def intercept[T <: AnyRef](clazz: java.lang.Class[T])(f: => Unit): T = { // intercept(clazz)(f)(manifest) "hi".asInstanceOf[T] } */ /* def intercept[T <: AnyRef](clazz: java.lang.Class[T])(f: => Unit)(implicit manifest: Manifest[T]): T = { intercept(clazz)(f)(manifest) } */ /** * Trap and return any thrown exception that would normally cause a ScalaTest test to fail, or create and return a newRuntimeException* indicating no exception is thrown. * ** This method is intended to be used in the Scala interpreter to eliminate large stack traces when trying out ScalaTest assertions and * matcher expressions. It is not intended to be used in regular test code. If you want to ensure that a bit of code throws an expected * exception, use
* *intercept, nottrap. Here's an example interpreter session withouttrap: ** scala> import org.scalatest._ * import org.scalatest._ * * scala> import Matchers._ * import Matchers._ * * scala> val x = 12 * a: Int = 12 * * scala> x shouldEqual 13 * org.scalatest.exceptions.TestFailedException: 12 did not equal 13 * at org.scalatest.Assertions$class.newAssertionFailedException(Assertions.scala:449) * at org.scalatest.Assertions$.newAssertionFailedException(Assertions.scala:1203) * at org.scalatest.Assertions$AssertionsHelper.macroAssertTrue(Assertions.scala:417) * at .<init>(<console>:15) * at .<clinit>(<console>) * at .<init>(<console>:7) * at .<clinit>(<console>) * at $print(<console>) * at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) * at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) * at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) * at java.lang.reflect.Method.invoke(Method.java:597) * at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:731) * at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:980) * at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:570) * at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:601) * at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:565) * at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:745) * at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:790) * at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:702) * at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:566) * at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:573) * at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:576) * at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:867) * at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822) * at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822) * at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135) * at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822) * at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:83) * at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96) * at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105) * at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) ** ** That's a pretty tall stack trace. Here's what it looks like when you use
* *trap: ** scala> trap { x shouldEqual 13 } * res1: Throwable = org.scalatest.exceptions.TestFailedException: 12 did not equal 13 ** ** Much less clutter. Bear in mind, however, that if no exception is thrown by the * passed block of code, the
* *trapmethod will create a newNormalResult* (a subclass ofThrowablemade for this purpose only) and return that. If the result was theUnitvalue, it * will simply say that no exception was thrown: ** scala> trap { x shouldEqual 12 } * res2: Throwable = No exception was thrown. ** ** If the passed block of code results in a value other than
* *Unit, theNormalResult'stoStringwill print the value: ** scala> trap { "Dude!" } * res3: Throwable = No exception was thrown. Instead, result was: "Dude!" ** ** Although you can access the result value from the
*/ def trap[T](f: => T): Throwable = { try { new NormalResult(f) } catch { case ex: Throwable if !Suite.anExceptionThatShouldCauseAnAbort(ex) => ex } } /** * Assert that the value passed asNormalResult, its type isAnyand therefore not * very convenient to use. It is not intended thattrapbe used in test code. The sole intended use case fortrapis decluttering * Scala interpreter sessions by eliminating stack traces when executing assertion and matcher expressions. *expectedequals the value passed asactual. * If theactualequals theexpected* (as determined by==),assertResultreturns * normally. Else, ifactualis not equal toexpected,assertResultthrows a *TestFailedExceptionwhose detail message includes the expected and actual values, as well as theString* obtained by invokingtoStringon the passedclue. * * @param expected the expected value * @param clue An object whosetoStringmethod returns a message to include in a failure report. * @param actual the actual value, which should equal the passedexpectedvalue * @throws TestFailedException if the passedactualvalue does not equal the passedexpectedvalue. */ def assertResult(expected: Any, clue: Any)(actual: Any) { if (!areEqualComparingArraysStructurally(actual, expected)) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) val fullMsg = AppendedClues.appendClue(s, clue.toString) throw newAssertionFailedException(Some(fullMsg), None, 4) } } /** * ThisexpectResultmethod has been deprecated; Please useassertResultinstead. * ** To get rid of the deprecation warning, simply replace
*/ @deprecated("This expectResult method has been deprecated. Please replace all invocations of expectResult with an identical invocation of assertResult instead.") def expectResult(expected: Any, clue: Any)(actual: Any) { if (actual != expected) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) throw newAssertionFailedException(Some(clue + "\n" + s), None, 4) } } /** * ThisexpectResultwith *assertResult. The nameexpectResultwill be used for a different purposes in * a future version of ScalaTest. *expectmethod has been deprecated; Please useassertResultinstead. * ** To get rid of the deprecation warning, simply replace
*/ @deprecated("This expect method has been deprecated. Please replace all invocations of expect with an identical invocation of assertResult instead.") def expect(expected: Any, clue: Any)(actual: Any) { if (actual != expected) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) throw newAssertionFailedException(Some(clue + "\n" + s), None, 4) } } /** * Assert that the value passed asexpectwith *assertResult. The nameexpectwill be used for a different purposes in * a future version of ScalaTest. *expectedequals the value passed asactual. * If theactualvalue equals theexpectedvalue * (as determined by==),assertResultreturns * normally. Else,assertResultthrows a *TestFailedExceptionwhose detail message includes the expected and actual values. * * @param expected the expected value * @param actual the actual value, which should equal the passedexpectedvalue * @throws TestFailedException if the passedactualvalue does not equal the passedexpectedvalue. */ def assertResult(expected: Any)(actual: Any) { if (!areEqualComparingArraysStructurally(actual, expected)) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) throw newAssertionFailedException(Some(s), None, 4) } } /** * ThisexpectResultmethod has been deprecated; Please useassertResultinstead. * ** To get rid of the deprecation warning, simply replace
*/ @deprecated("This expectResult method has been deprecated. Please replace all invocations of expectResult with an identical invocation of assertResult instead.") def expectResult(expected: Any)(actual: Any) { if (actual != expected) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) throw newAssertionFailedException(Some(s), None, 4) } } /** * ThisexpectResultwith *assertResult. The nameexpectResultwill be used for a different purposes in * a future version of ScalaTest. *expectmethod has been deprecated; Please useassertResultinstead. * ** To get rid of the deprecation warning, simply replace
*/ @deprecated("This expect method has been deprecated. Please replace all invocations of expect with an identical invocation of assertResult instead.") def expect(expected: Any)(actual: Any) { if (actual != expected) { val (act, exp) = Suite.getObjectsForFailureMessage(actual, expected) val s = FailureMessages("expectedButGot", exp, act) throw newAssertionFailedException(Some(s), None, 4) } } /* * TODO: Delete this if sticking with Nothing instead of Unit as result type of fail. *expectwith *assertResult. The nameexpectwill be used for a different purposes in * a future version of ScalaTest. ** The result type of this and the other overloaded
* *failmethods is *Unitinstead ofNothing, becauseNothing* is a subtype of all other types. If the result type offailwere *Nothing, a block of code that ends in a call tofail()may * fail to compile if the block being passed as a by-name parameter or function to an * overloaded method. The reason is that the compiler selects which overloaded * method to call based on the static types of the parameters passed. Since *Nothingis an instance of everything, it can often make the overloaded * method selection ambiguous. ** For a concrete example, the
* *Conductorclass * in packageorg.scalatest.concurrenthas two overloaded variants of the *threadmethod: ** def thread[T](fun: => T): Thread * * def thread[T](name: String)(fun: => T): Thread ** ** Given these two overloaded methods, the following code will compile given the result type * of
* *failisUnit, but would not compile if the result type were *Nothing: ** thread { fail() } ** ** If the result type of
*/ /** * ThrowsfailwereNothing, the type of the by-name parameter * would be inferred to beNothing, which is a subtype of bothTand *String. Thus the call is ambiguous, because the type matches the first parameter type * of both overloadedthreadmethods.Unit, by constrast, is not * a subtype ofString, so it only matches one overloaded variant and compiles just fine. *TestFailedExceptionto indicate a test failed. */ def fail(): Nothing = { throw newAssertionFailedException(None, None, 4) } /** * ThrowsTestFailedException, with the passed *Stringmessageas the exception's detail * message, to indicate a test failed. * * @param message A message describing the failure. * @throws NullPointerException ifmessageisnull*/ def fail(message: String): Nothing = { if (message == null) throw new NullPointerException("message is null") throw newAssertionFailedException(Some(message), None, 4) } /** * ThrowsTestFailedException, with the passed *Stringmessageas the exception's detail * message andThrowablecause, to indicate a test failed. * * @param message A message describing the failure. * @param cause AThrowablethat indicates the cause of the failure. * @throws NullPointerException ifmessageorcauseisnull*/ def fail(message: String, cause: Throwable): Nothing = { if (message == null) throw new NullPointerException("message is null") if (cause == null) throw new NullPointerException("cause is null") throw newAssertionFailedException(Some(message), Some(cause), 4) } /** * ThrowsTestFailedException, with the passed *Throwablecause, to indicate a test failed. * ThegetMessagemethod of the thrownTestFailedException* will returncause.toString. * * @param cause aThrowablethat indicates the cause of the failure. * @throws NullPointerException ifcauseisnull*/ def fail(cause: Throwable): Nothing = { if (cause == null) throw new NullPointerException("cause is null") throw newAssertionFailedException(None, Some(cause), 4) } /** * ThrowsTestCanceledExceptionto indicate a test was canceled. */ def cancel(): Nothing = { throw newTestCanceledException(None, None, 3) } /** * ThrowsTestCanceledException, with the passed *Stringmessageas the exception's detail * message, to indicate a test was canceled. * * @param message A message describing the cancellation. * @throws NullPointerException ifmessageisnull*/ def cancel(message: String): Nothing = { if (message == null) throw new NullPointerException("message is null") throw newTestCanceledException(Some(message), None, 3) } /** * ThrowsTestCanceledException, with the passed *Stringmessageas the exception's detail * message andThrowablecause, to indicate a test failed. * * @param message A message describing the failure. * @param cause AThrowablethat indicates the cause of the failure. * @throws NullPointerException ifmessageorcauseisnull*/ def cancel(message: String, cause: Throwable): Nothing = { if (message == null) throw new NullPointerException("message is null") if (cause == null) throw new NullPointerException("cause is null") throw newTestCanceledException(Some(message), Some(cause), 3) } /** * ThrowsTestCanceledException, with the passed *Throwablecause, to indicate a test failed. * ThegetMessagemethod of the thrownTestCanceledException* will returncause.toString. * * @param cause aThrowablethat indicates the cause of the cancellation. * @throws NullPointerException ifcauseisnull*/ def cancel(cause: Throwable): Nothing = { if (cause == null) throw new NullPointerException("cause is null") throw newTestCanceledException(None, Some(cause), 3) } /** * Executes the block of code passed as the second parameter, and, if it * completes abruptly with aModifiableMessageexception, * prepends the "clue" string passed as the first parameter to the beginning of the detail message * of that thrown exception, then rethrows it. If clue does not end in a white space * character, one space will be added * between it and the existing detail message (unless the detail message is * not defined). * ** This method allows you to add more information about what went wrong that will be * reported when a test fails. Here's an example: *
* ** withClue("(Employee's name was: " + employee.name + ")") { * intercept[IllegalArgumentException] { * employee.getTask(-1) * } * } ** ** If an invocation of
* *interceptcompleted abruptly with an exception, the resulting message would be something like: ** (Employee's name was Bob Jones) Expected IllegalArgumentException to be thrown, but no exception was thrown ** * @throws NullPointerException if the passedclueisnull*/ def withClue[T](clue: Any)(fun: => T): T = { if (clue == null) throw new NullPointerException("clue was null") def prepend(currentMessage: Option[String]) = currentMessage match { case Some(msg) => if (clue.toString.last.isWhitespace) // TODO: shouldn't I also check if the head of msg isWhite? Some(clue.toString + msg) else Some(clue.toString + " " + msg) case None => Some(clue.toString) } try { val outcome = fun outcome match { case Failed(e: org.scalatest.exceptions.ModifiableMessage[_]) if clue.toString != "" => Failed(e.modifyMessage(prepend)).asInstanceOf[T] case Canceled(e: org.scalatest.exceptions.ModifiableMessage[_]) if clue.toString != "" => Canceled(e.modifyMessage(prepend)).asInstanceOf[T] case _ => outcome } } catch { case e: org.scalatest.exceptions.ModifiableMessage[_] => if (clue != "") throw e.modifyMessage(prepend) else throw e } } /* Hold off on this for now. See how people do with the simple one that takes an Any. def withClueFunction(sfun: Option[String] => Option[String])(fun: => Unit) { fun } */ } /** * Companion object that facilitates the importing ofAssertionsmembers as * an alternative to mixing it in. One use case is to importAssertionsmembers so you can use * them in the Scala interpreter: * ** $scala -classpath scalatest.jar * Welcome to Scala version 2.7.3.final (Java HotSpot(TM) Client VM, Java 1.5.0_16). * Type in expressions to have them evaluated. * Type :help for more information. * * scala> import org.scalatest.Assertions._ * import org.scalatest.Assertions._ * * scala> assert(1 === 2) * org.scalatest.TestFailedException: 1 did not equal 2 * at org.scalatest.Assertions$class.assert(Assertions.scala:211) * at org.scalatest.Assertions$.assert(Assertions.scala:511) * at .<init>(<console>:7) * at .<clinit>(<console>) * at RequestResult$.<init>(<console>:3) * at RequestResult$.<clinit>(<console>) * at RequestResult$result(<console>) * at sun.reflect.NativeMethodAccessorImpl.invoke... * * scala> assertResult(3) { 1 + 3 } * org.scalatest.TestFailedException: Expected 3, but got 4 * at org.scalatest.Assertions$class.expect(Assertions.scala:447) * at org.scalatest.Assertions$.expect(Assertions.scala:511) * at .<init>(<console>:7) * at .<clinit>(<console>) * at RequestResult$.<init>(<console>:3) * at RequestResult$.<clinit>(<console>) * at RequestResult$result(<console>) * at sun.reflect.NativeMethodAccessorImpl.in... * * scala> val caught = intercept[StringIndexOutOfBoundsException] { "hi".charAt(-1) } * caught: StringIndexOutOfBoundsException = java.lang.StringIndexOutOfBoundsException: String index out of range: -1 ** * @author Bill Venners */ object Assertions extends Assertions { case class NormalResult(result: Any) extends Throwable { override def toString = if (result == ()) Resources("noExceptionWasThrown") else Resources("resultWas", Prettifier.default(result)) } private[scalatest] def areEqualComparingArraysStructurally(left: Any, right: Any): Boolean = { // Prior to 2.0 this only called .deep if both sides were arrays. Loosened it // when nearing 2.0.M6 to call .deep if either left or right side is an array. // TODO: this is the same algo as in scalactic.DefaultEquality. Put that one in // a singleton and use it in both places. left match { case leftArray: Array[_] => right match { case rightArray: Array[_] => leftArray.deep == rightArray.deep case _ => leftArray.deep == right } case _ => { right match { case rightArray: Array[_] => left == rightArray.deep case _ => left == right } } } } private[scalatest] def checkExpectedException[T](f: => Any, clazz: Class[T], wrongExceptionResourceName: String, exceptionExpectedResourceName: String, stackDepth: Int): T = { val caught = try { f None } catch { case u: Throwable => { if (!clazz.isAssignableFrom(u.getClass)) { val s = Resources(wrongExceptionResourceName, clazz.getName, u.getClass.getName) throw newAssertionFailedException(Some(s), Some(u), stackDepth) } else { Some(u) } } } caught match { case None => val message = Resources(exceptionExpectedResourceName, clazz.getName) throw newAssertionFailedException(Some(message), None, stackDepth) case Some(e) => e.asInstanceOf[T] // I know this cast will succeed, becuase iSAssignableFrom succeeded above } } private[scalatest] def checkNoException(fun: => Any) { val caught = try { fun } catch { case u: Throwable => { val message = Resources("exceptionNotExpected", u.getClass.getName) throw newAssertionFailedException(Some(message), Some(u), 4) } } } private[scalatest] def checkNotException[T <: AnyRef](f: => Any, exceptionNotExpectedResourceName: String)(implicit manifest: Manifest[T]) { val clazz = manifest.erasure.asInstanceOf[Class[T]] try { f } catch { case u: Throwable => { if (clazz.isAssignableFrom(u.getClass)) { val s = Resources(exceptionNotExpectedResourceName, u.getClass.getName) throw newAssertionFailedException(Some(s), Some(u), 4) } } } } }