org.scalatest.words.BeWord.scala Maven / Gradle / Ivy
Show all versions of scalatest_2.9.1 Show documentation
/*
* 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.words
import org.scalatest.matchers._
import org.scalautils._
import org.scalatest.FailureMessages
import org.scalatest.UnquotedString
import org.scalatest.Suite
import org.scalatest.Assertions.areEqualComparingArraysStructurally
import org.scalatest.MatchersHelper.matchSymbolToPredicateMethod
import org.scalatest.enablers.Sortable
/**
* This class is part of the ScalaTest matchers DSL. Please see the documentation for ShouldMatchers or MustMatchers for an overview of
* the matchers DSL.
*
*
* Class BeWord contains an apply method that takes a Symbol, which uses reflection
* to find and access a Boolean property and determine if it is true.
* If the symbol passed is 'empty, for example, the apply method
* will use reflection to look for a public Java field named
* "empty", a public method named "empty", or a public method named "isEmpty". If a field, it must be of type Boolean.
* If a method, it must take no parameters and return Boolean. If multiple candidates are found,
* the apply method will select based on the following algorithm:
*
*
*
* Field Method "is" Method Result
* Throws TestFailedException, because no candidates found
* isEmpty()Invokes isEmpty()
* empty() Invokes empty()
* empty()isEmpty()Invokes empty() (this can occur when BeanProperty annotation is used)
* empty Accesses field empty
* empty isEmpty()Invokes isEmpty()
* emptyempty() Invokes empty()
* emptyempty()isEmpty()Invokes empty() (this can occur when BeanProperty annotation is used)
*
*
* @author Bill Venners
*/
final class BeWord {
/**
* This method enables the following syntax:
*
*
* result should be < (7)
* ^
*
*
*
* Note that the less than operator will be invoked on be in this expression, not
* on a result of passing be to should, as with most other operators
* in the matchers DSL, because the less than operator has a higher precedence than should.
* Thus in the above case the first expression evaluated will be be < (7), which results
* in a matcher that is passed to should.
*
*
*
* This method also enables the following syntax:
*
*
*
* result should not (be < (7))
* ^
*
*/
def <[T <% Ordered[T]](right: T): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult =
MatchResult(
left < right,
FailureMessages("wasNotLessThan", left, right),
FailureMessages("wasLessThan", left, right)
)
}
/**
* This method enables the following syntax:
*
*
* result should be > (7)
* ^
*
*
*
* Note that the greater than operator will be invoked on be in this expression, not
* on a result of passing be to should, as with most other operators
* in the matchers DSL, because the greater than operator has a higher precedence than should.
* Thus in the above case the first expression evaluated will be be > (7), which results
* in a matcher that is passed to should.
*
*
*
* This method also enables the following syntax:
*
*
*
* result should not (be > (7))
* ^
*
*/
def >[T <% Ordered[T]](right: T): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult =
MatchResult(
left > right,
FailureMessages("wasNotGreaterThan", left, right),
FailureMessages("wasGreaterThan", left, right)
)
}
/**
* This method enables the following syntax:
*
*
* result should be <= (7)
* ^
*
*
*
* Note that the less than or equal to operator will be invoked on be in this expression, not
* on a result of passing be to should, as with most other operators
* in the matchers DSL, because the less than or equal to operator has a higher precedence than should.
* Thus in the above case the first expression evaluated will be be <= (7), which results
* in a matcher that is passed to should.
*
*
*
* This method also enables the following syntax:
*
*
*
* result should not (be <= (7))
* ^
*
*/
def <=[T <% Ordered[T]](right: T): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult =
MatchResult(
left <= right,
FailureMessages("wasNotLessThanOrEqualTo", left, right),
FailureMessages("wasLessThanOrEqualTo", left, right)
)
}
/**
* This method enables the following syntax:
*
*
* result should be >= (7)
* ^
*
*
*
* Note that the greater than or equal to operator will be invoked on be in this expression, not
* on a result of passing be to should, as with most other operators
* in the matchers DSL, because the greater than or equal to operator has a higher precedence than should.
* Thus in the above case the first expression evaluated will be be >= (7), which results
* in a matcher that is passed to should.
*
*
*
* This method also enables the following syntax:
*
*
*
* result should not (be >= (7))
* ^
*
*/
def >=[T <% Ordered[T]](right: T): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult =
MatchResult(
left >= right,
FailureMessages("wasNotGreaterThanOrEqualTo", left, right),
FailureMessages("wasGreaterThanOrEqualTo", left, right)
)
}
/**
*
* The should be === syntax has been deprecated and will be removed in a future version of ScalaTest. Please use should equal, should ===, shouldEqual,
* should be, or shouldBe instead. Note, the reason this was deprecated was so that === would mean only one thing in ScalaTest: a customizable, type-
* checkable equality comparison.
*
*
*
* This method enables the following syntax:
*
*
*
* result should be === (7)
* ^
*
*
*
* Note that the === operator will be invoked on be in this expression, not
* on a result of passing be to should, as with most other operators
* in the matchers DSL, because the ===n operator has a higher precedence than should.
* Thus in the above case the first expression evaluated will be be === (7), which results
* in a matcher that is passed to should.
*
*
*
* This method also enables the following syntax:
*
*
*
* result should not (be === (7))
* ^
*
*/
@deprecated("The should be === syntax has been deprecated. Please use should equal, should ===, shouldEqual, should be, or shouldBe instead.")
def ===(right: Any): Matcher[Any] =
new Matcher[Any] {
def apply(left: Any): MatchResult = {
val (leftee, rightee) = Suite.getObjectsForFailureMessage(left, right)
MatchResult(
areEqualComparingArraysStructurally(left, right),
FailureMessages("wasNotEqualTo", leftee, rightee),
FailureMessages("wasEqualTo", left, right)
)
}
}
/**
* This method enables the following syntax:
*
*
* fileMock should not { be a ('file) }
* ^
*
*/
def a(right: Symbol): Matcher[AnyRef] =
new Matcher[AnyRef] {
def apply(left: AnyRef): MatchResult = matchSymbolToPredicateMethod(left, right, true, true)
}
/**
* This method enables the following syntax, where fileMock is, for example, of type File and
* file refers to a BePropertyMatcher[File]:
*
*
* fileMock should not { be a (file) }
* ^
*
*/
def a[S <: AnyRef](bePropertyMatcher: BePropertyMatcher[S]): Matcher[S] =
new Matcher[S] {
def apply(left: S): MatchResult = {
val result = bePropertyMatcher(left)
MatchResult(
result.matches,
FailureMessages("wasNotA", left, UnquotedString(result.propertyName)),
FailureMessages("wasA", left, UnquotedString(result.propertyName))
)
}
}
/**
* This method enables the following syntax, where negativeNumber is, for example, of type AMatcher:
*
*
* 8 should not { be a (negativeNumber) }
* ^
*
*/
def a[S](aMatcher: AMatcher[S]): Matcher[S] =
new Matcher[S] {
def apply(left: S): MatchResult = aMatcher(left)
}
/**
* This method enables the following syntax:
*
*
* animal should not { be an ('elephant) }
* ^
*
*/
def an(right: Symbol): Matcher[AnyRef] =
new Matcher[AnyRef] {
def apply(left: AnyRef): MatchResult = matchSymbolToPredicateMethod(left, right, true, false)
}
/**
* This method enables the following syntax, where keyEvent is, for example, of type KeyEvent and
* actionKey refers to a BePropertyMatcher[KeyEvent]:
*
*
* keyEvent should not { be an (actionKey) }
* ^
*
*/
def an[S <: AnyRef](bePropertyMatcher: BePropertyMatcher[S]): Matcher[S] =
new Matcher[S] {
def apply(left: S): MatchResult = {
val result = bePropertyMatcher(left)
MatchResult(
result.matches,
FailureMessages("wasNotAn", left, UnquotedString(result.propertyName)),
FailureMessages("wasAn", left, UnquotedString(result.propertyName))
)
}
}
/**
* This method enables the following syntax, where oddNumber is, for example, of type AnMatcher:
*
*
* 8 should not { be an (oddNumber) }
* ^
*
*/
def an[S](anMatcher: AnMatcher[S]): Matcher[S] =
new Matcher[S] {
def apply(left: S): MatchResult = anMatcher(left)
}
/**
* This method enables the following syntax for the "primitive" numeric types:
*
*
* sevenDotOh should be (7.1 plusOrMinus 0.2)
* ^
*
*/
def apply[U](interval: Interval[U]): Matcher[U] =
new Matcher[U] {
def apply(left: U): MatchResult = {
MatchResult(
interval.isWithin(left),
// left <= right + tolerance && left >= right - tolerance,
FailureMessages("wasNotPlusOrMinus", left, interval.pivot, interval.tolerance),
FailureMessages("wasPlusOrMinus", left, interval.pivot, interval.tolerance)
)
}
}
/**
* This method enables the following syntax:
*
*
* result should be theSameInstancreAs (anotherObject)
* ^
*
*/
def theSameInstanceAs(right: AnyRef): Matcher[AnyRef] =
new Matcher[AnyRef] {
def apply(left: AnyRef): MatchResult =
MatchResult(
left eq right,
FailureMessages("wasNotSameInstanceAs", left, right),
FailureMessages("wasSameInstanceAs", left, right)
)
}
/**
* This method enables the following syntax:
*
*
* result should be (true)
* ^
*
*/
def apply(right: Boolean): Matcher[Boolean] =
new Matcher[Boolean] {
def apply(left: Boolean): MatchResult =
MatchResult(
left == right,
FailureMessages("wasNot", left, right),
FailureMessages("was", left, right)
)
}
/**
* This method enables the following syntax:
*
*
* result should be (null)
* ^
*
*/
def apply(o: Null): Matcher[AnyRef] =
new Matcher[AnyRef] {
def apply(left: AnyRef): MatchResult = {
MatchResult(
left == null,
FailureMessages("wasNotNull", left),
FailureMessages("wasNull"),
FailureMessages("wasNotNull", left),
FailureMessages("midSentenceWasNull")
)
}
}
/* *
* This method enables the following syntax:
*
*
* set should be ('empty)
* ^
*
def apply[T](right: AType[T]): Matcher[Any] =
new Matcher[Any] {
def apply(left: Any): MatchResult =
MatchResult(
right.isAssignableFromClassOf(left),
FailureMessages("wasNotAnInstanceOf", left, UnquotedString(right.className)),
FailureMessages("wasAnInstanceOf"), // TODO, missing the left, right.className here. Write a test and fix it.
FailureMessages("wasNotAnInstanceOf", left, UnquotedString(right.className)),
FailureMessages("wasAnInstanceOf")
)
}
*/
/**
* This method enables the following syntax:
*
*
* set should be ('empty)
* ^
*
*/
def apply(right: Symbol): Matcher[AnyRef] =
new Matcher[AnyRef] {
def apply(left: AnyRef): MatchResult = matchSymbolToPredicateMethod(left, right, false, false)
}
/**
* This method enables the following syntax, where num is, for example, of type Int and
* odd refers to a BeMatcher[Int]:
*
*
* num should be (odd)
* ^
*
*/
def apply[T](right: BeMatcher[T]): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult = right(left)
}
/**
* This method enables the following syntax, where open refers to a BePropertyMatcher:
*
*
* door should be (open)
* ^
*
*/
def apply[T](bePropertyMatcher: BePropertyMatcher[T]): Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult = {
val result = bePropertyMatcher(left)
MatchResult(
result.matches,
FailureMessages("wasNot", left, UnquotedString(result.propertyName)),
FailureMessages("was", left, UnquotedString(result.propertyName))
)
}
}
/**
* This method enables be to be used for equality comparison. Here are some examples:
*
*
* result should be (None)
* ^
* result should be (Some(1))
* ^
* result should be (true)
* ^
* result should be (false)
* ^
* sum should be (19)
* ^
*
*/
def apply(right: Any): Matcher[Any] =
new Matcher[Any] {
def apply(left: Any): MatchResult = {
val (leftee, rightee) = Suite.getObjectsForFailureMessage(left, right)
MatchResult(
areEqualComparingArraysStructurally(left, right),
FailureMessages("wasNotEqualTo", leftee, rightee),
FailureMessages("wasEqualTo", left, right)
)
}
}
/**
* This method enables the following syntax, where open refers to a BePropertyMatcher:
*
*
* List(1, 2, 3) should be (sorted)
* ^
*
*/
def apply(right: SortedWord): MatcherFactory1[Any, Sortable] =
new MatcherFactory1[Any, Sortable] {
def matcher[T <: Any : Sortable]: Matcher[T] =
new Matcher[T] {
def apply(left: T): MatchResult = {
val sortable = implicitly[Sortable[T]]
MatchResult(
sortable.isSorted(left),
FailureMessages("wasNotSorted", left),
FailureMessages("wasSorted", left)
)
}
}
}
/**
* This method enables the following syntax, where fraction refers to a PartialFunction:
*
*
* fraction should (be definedAt (6) and be definedAt (8))
* ^
*
*/
def definedAt[A, U <: PartialFunction[A, _]](right: A): Matcher[U] =
new Matcher[U] {
def apply(left: U): MatchResult =
MatchResult(
left.isDefinedAt(right),
FailureMessages("wasNotDefinedAt", left, right),
FailureMessages("wasDefinedAt", left, right)
)
}
/**
* This method enables the following syntax, where fraction refers to a PartialFunction:
*
*
* fraction should (be (definedAt (6)) and be (definedAt (8)))
* ^
*
*/
def apply[A, U <: PartialFunction[A, _]](resultOfDefinedAt: ResultOfDefinedAt[A]): Matcher[U] =
new Matcher[U] {
def apply(left: U): MatchResult =
MatchResult(
left.isDefinedAt(resultOfDefinedAt.right),
FailureMessages("wasNotDefinedAt", left, resultOfDefinedAt.right),
FailureMessages("wasDefinedAt", left, resultOfDefinedAt.right)
)
}
}