/* * Copyright 2001-2008 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.matchers import org.scalatest._ import org.scalatest.prop.Checkers import org.scalacheck._ import Arbitrary._ import Prop._ import scala.reflect.BeanProperty class ShouldBeMatcherSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion with BookPropertyMatchers { class OddMatcher extends BeMatcher[Int] { def apply(left: Int): MatchResult = { MatchResult( left % 2 == 1, left.toString + " was even", left.toString + " was odd" ) } } val odd = new OddMatcher val even = not (odd) describe("The BeMatcher syntax") { it("should do nothing if a BeMatcher matches") { 1 should be (odd) 2 should be (even) } it("should throw TestFailedException if a BeMatcher does not match") { val caught1 = intercept[TestFailedException] { 4 should be (odd) } assert(caught1.getMessage === "4 was even") val caught2 = intercept[TestFailedException] { 5 should be (even) } assert(caught2.getMessage === "5 was odd") } it("should do nothing if a BeMatcher does not match, when used with not") { 2 should not be (odd) 1 should not be (even) 22 should not (not (be (even))) 1 should not (not (be (odd))) } it("should throw TestFailedException if a BeMatcher matches, when used with not") { val caught1 = intercept[TestFailedException] { 3 should not be (odd) } assert(caught1.getMessage === "3 was odd") val caught2 = intercept[TestFailedException] { 6 should not be (even) } assert(caught2.getMessage === "6 was even") val caught3 = intercept[TestFailedException] { 6 should not (not (be (odd))) } assert(caught3.getMessage === "6 was even") } it("should do nothing if a BeMatcher matches, when used in a logical-and expression") { 1 should (be (odd) and be (odd)) 1 should (be (odd) and (be (odd))) 2 should (be (even) and be (even)) 2 should (be (even) and (be (even))) } it("should throw TestFailedException if at least one BeMatcher does not match, when used in a logical-or expression") { // both false val caught1 = intercept[TestFailedException] { 2 should (be (odd) and be (odd)) } assert(caught1.getMessage === "2 was even") val caught2 = intercept[TestFailedException] { 2 should (be (odd) and (be (odd))) } assert(caught2.getMessage === "2 was even") val caught3 = intercept[TestFailedException] { 1 should (be (even) and be (even)) } assert(caught3.getMessage === "1 was odd") val caught4 = intercept[TestFailedException] { 1 should (be (even) and (be (even))) } assert(caught4.getMessage === "1 was odd") // first false val caught5 = intercept[TestFailedException] { 1 should (be (even) and be (odd)) } assert(caught5.getMessage === "1 was odd") val caught6 = intercept[TestFailedException] { 1 should (be (even) and (be (odd))) } assert(caught6.getMessage === "1 was odd") val caught7 = intercept[TestFailedException] { 2 should (be (odd) and be (even)) } assert(caught7.getMessage === "2 was even") val caught8 = intercept[TestFailedException] { 2 should (be (odd) and (be (even))) } assert(caught8.getMessage === "2 was even") // TODO: Remember to try a BeMatcher[Any] one, to make sure it works on an Int // second false val caught9 = intercept[TestFailedException] { 1 should (be (odd) and be (even)) } assert(caught9.getMessage === "1 was odd, but 1 was odd") val caught10 = intercept[TestFailedException] { 1 should (be (odd) and (be (even))) } assert(caught10.getMessage === "1 was odd, but 1 was odd") val caught11 = intercept[TestFailedException] { 2 should (be (even) and be (odd)) } assert(caught11.getMessage === "2 was even, but 2 was even") val caught12 = intercept[TestFailedException] { 2 should (be (even) and (be (odd))) } assert(caught12.getMessage === "2 was even, but 2 was even") } it("should do nothing if at least one BeMatcher matches, when used in a logical-or expression") { // both true 1 should (be (odd) or be (odd)) 1 should (be (odd) or (be (odd))) 2 should (be (even) or be (even)) 2 should (be (even) or (be (even))) // first false 1 should (be (even) or be (odd)) 1 should (be (even) or (be (odd))) 2 should (be (odd) or be (even)) 2 should (be (odd) or (be (even))) // second false 1 should (be (odd) or be (even)) 1 should (be (odd) or (be (even))) 2 should (be (even) or be (odd)) 2 should (be (even) or (be (odd))) } it("should throw TestFailedException if a BeMatcher does not match, when used in a logical-or expression") { val caught1 = intercept[TestFailedException] { 2 should (be (odd) or be (odd)) } assert(caught1.getMessage === "2 was even, and 2 was even") val caught2 = intercept[TestFailedException] { 2 should (be (odd) or (be (odd))) } assert(caught2.getMessage === "2 was even, and 2 was even") val caught3 = intercept[TestFailedException] { 1 should (be (even) or be (even)) } assert(caught3.getMessage === "1 was odd, and 1 was odd") val caught4 = intercept[TestFailedException] { 1 should (be (even) or (be (even))) } assert(caught4.getMessage === "1 was odd, and 1 was odd") } it("should do nothing if a BeMatcher does not match, when used in a logical-and expression with not") { 2 should (not be (odd) and not be (odd)) 2 should (not be (odd) and not (be (odd))) 2 should (not be (odd) and (not (be (odd)))) 1 should (not be (even) and not be (even)) 1 should (not be (even) and not (be (even))) 1 should (not be (even) and (not (be (even)))) } it("should throw TestFailedException if at least one BeMatcher matches, when used in a logical-and expression with not") { // both true val caught1 = intercept[TestFailedException] { 1 should (not be (odd) and not be (odd)) } assert(caught1.getMessage === "1 was odd") val caught2 = intercept[TestFailedException] { 1 should (not be (odd) and not (be (odd))) } assert(caught2.getMessage === "1 was odd") val caught3 = intercept[TestFailedException] { 1 should (not be (odd) and (not (be (odd)))) } assert(caught3.getMessage === "1 was odd") val caught4 = intercept[TestFailedException] { 2 should (not be (even) and not be (even)) } assert(caught4.getMessage === "2 was even") val caught5 = intercept[TestFailedException] { 2 should (not be (even) and not (be (even))) } assert(caught5.getMessage === "2 was even") val caught6 = intercept[TestFailedException] { 2 should (not be (even) and (not (be (even)))) } assert(caught6.getMessage === "2 was even") // first false val caught7 = intercept[TestFailedException] { 1 should (not be (even) and not be (odd)) } assert(caught7.getMessage === "1 was odd, but 1 was odd") val caught8 = intercept[TestFailedException] { 1 should (not be (even) and not (be (odd))) } assert(caught8.getMessage === "1 was odd, but 1 was odd") val caught9 = intercept[TestFailedException] { 1 should (not be (even) and (not (be (odd)))) } assert(caught9.getMessage === "1 was odd, but 1 was odd") val caught10 = intercept[TestFailedException] { 2 should (not be (odd) and not be (even)) } assert(caught10.getMessage === "2 was even, but 2 was even") val caught11 = intercept[TestFailedException] { 2 should (not be (odd) and not (be (even))) } assert(caught11.getMessage === "2 was even, but 2 was even") val caught12 = intercept[TestFailedException] { 2 should (not be (odd) and (not (be (even)))) } assert(caught12.getMessage === "2 was even, but 2 was even") // second false val caught13 = intercept[TestFailedException] { 1 should (not be (odd) and not be (even)) } assert(caught13.getMessage === "1 was odd") val caught14 = intercept[TestFailedException] { 1 should (not be (odd) and not (be (even))) } assert(caught14.getMessage === "1 was odd") val caught15 = intercept[TestFailedException] { 1 should (not be (odd) and (not (be (even)))) } assert(caught15.getMessage === "1 was odd") val caught16 = intercept[TestFailedException] { 2 should (not be (even) and not be (odd)) } assert(caught16.getMessage === "2 was even") val caught17 = intercept[TestFailedException] { 2 should (not be (even) and not (be (odd))) } assert(caught17.getMessage === "2 was even") val caught18 = intercept[TestFailedException] { 2 should (not be (even) and (not (be (odd)))) } assert(caught18.getMessage === "2 was even") } it("should do nothing if at least one BeMatcher doesn't match, when used in a logical-or expression when used with not") { // both false 2 should (not be (odd) or not be (odd)) 2 should (not be (odd) or not (be (odd))) 2 should (not be (odd) or (not (be (odd)))) 1 should (not be (even) or not be (even)) 1 should (not be (even) or not (be (even))) 1 should (not be (even) or (not (be (even)))) // first false 1 should (not be (even) or not be (odd)) 1 should (not be (even) or not (be (odd))) 1 should (not be (even) or (not (be (odd)))) 2 should (not be (odd) or not be (even)) 2 should (not be (odd) or not (be (even))) 2 should (not be (odd) or (not (be (even)))) // second false 1 should (not be (odd) or not be (even)) 1 should (not be (odd) or not (be (even))) 1 should (not be (odd) or (not (be (even)))) 2 should (not be (even) or not be (odd)) 2 should (not be (even) or not (be (odd))) 2 should (not be (even) or (not (be (odd)))) } it("should throw TestFailedException if both BeMatcher match, when used in a logical-or expression with not") { val caught1 = intercept[TestFailedException] { 1 should (not be (odd) or not be (odd)) } assert(caught1.getMessage === "1 was odd, and 1 was odd") val caught2 = intercept[TestFailedException] { 1 should (not be (odd) or not (be (odd))) } assert(caught2.getMessage === "1 was odd, and 1 was odd") val caught3 = intercept[TestFailedException] { 1 should (not be (odd) or (not (be (odd)))) } assert(caught3.getMessage === "1 was odd, and 1 was odd") val caught4 = intercept[TestFailedException] { 2 should (not be (even) or not be (even)) } assert(caught4.getMessage === "2 was even, and 2 was even") val caught5 = intercept[TestFailedException] { 2 should (not be (even) or not (be (even))) } assert(caught5.getMessage === "2 was even, and 2 was even") val caught6 = intercept[TestFailedException] { 2 should (not be (even) or (not (be (even)))) } assert(caught6.getMessage === "2 was even, and 2 was even") } it("should work when the types aren't exactly the same") { class UnlikableMatcher extends BeMatcher[Any] { def apply(left: Any): MatchResult = { MatchResult( false, left.toString + " was not to my liking", left.toString + " was to my liking" ) } } val unlikable = new UnlikableMatcher val likable = not (unlikable) 1 should be (likable) 2 should not be (unlikable) val caught1 = intercept[TestFailedException] { 1 should be (unlikable) } assert(caught1.getMessage === "1 was not to my liking") val caught2 = intercept[TestFailedException] { "The dish" should not be (likable) } assert(caught2.getMessage === "The dish was not to my liking") } } describe("the compose method on BeMatcher") { it("should return another BeMatcher") { val oddAsInt = odd compose { (s: String) => s.toInt } "3" should be (oddAsInt) "4" should not be (oddAsInt) } } describe("A factory method on BeMatcher's companion object") { it("should produce a be-matcher that executes the passed function when its apply is called") { val f = { (s: String) => MatchResult(s.length < 3, "s was not less than 3", "s was less than 3") } val lessThanThreeInLength = BeMatcher(f) "" should be (lessThanThreeInLength) "x" should be (lessThanThreeInLength) "xx" should be (lessThanThreeInLength) "xxx" should not be (lessThanThreeInLength) "xxxx" should not be (lessThanThreeInLength) } } }