1/* 2 * Copyright 2001-2008 Artima, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package org.scalatest.matchers 17 18import org.scalatest._ 19import org.scalatest.prop.Checkers 20import org.scalacheck._ 21import Arbitrary._ 22import Prop._ 23import scala.reflect.BeanProperty 24 25class ShouldBeMatcherSpec extends Spec with ShouldMatchers with Checkers with ReturnsNormallyThrowsAssertion with BookPropertyMatchers { 26 27 class OddMatcher extends BeMatcher[Int] { 28 def apply(left: Int): MatchResult = { 29 MatchResult( 30 left % 2 == 1, 31 left.toString + " was even", 32 left.toString + " was odd" 33 ) 34 } 35 } 36 val odd = new OddMatcher 37 val even = not (odd) 38 39 describe("The BeMatcher syntax") { 40 41 it("should do nothing if a BeMatcher matches") { 42 1 should be (odd) 43 2 should be (even) 44 } 45 46 it("should throw TestFailedException if a BeMatcher does not match") { 47 48 val caught1 = intercept[TestFailedException] { 49 4 should be (odd) 50 } 51 assert(caught1.getMessage === "4 was even") 52 53 val caught2 = intercept[TestFailedException] { 54 5 should be (even) 55 } 56 assert(caught2.getMessage === "5 was odd") 57 } 58 59 it("should do nothing if a BeMatcher does not match, when used with not") { 60 2 should not be (odd) 61 1 should not be (even) 62 22 should not (not (be (even))) 63 1 should not (not (be (odd))) 64 } 65 66 it("should throw TestFailedException if a BeMatcher matches, when used with not") { 67 68 val caught1 = intercept[TestFailedException] { 69 3 should not be (odd) 70 } 71 assert(caught1.getMessage === "3 was odd") 72 73 val caught2 = intercept[TestFailedException] { 74 6 should not be (even) 75 } 76 assert(caught2.getMessage === "6 was even") 77 78 val caught3 = intercept[TestFailedException] { 79 6 should not (not (be (odd))) 80 } 81 assert(caught3.getMessage === "6 was even") 82 } 83 84 it("should do nothing if a BeMatcher matches, when used in a logical-and expression") { 85 1 should (be (odd) and be (odd)) 86 1 should (be (odd) and (be (odd))) 87 2 should (be (even) and be (even)) 88 2 should (be (even) and (be (even))) 89 } 90 91 it("should throw TestFailedException if at least one BeMatcher does not match, when used in a logical-or expression") { 92 93 // both false 94 val caught1 = intercept[TestFailedException] { 95 2 should (be (odd) and be (odd)) 96 } 97 assert(caught1.getMessage === "2 was even") 98 99 val caught2 = intercept[TestFailedException] { 100 2 should (be (odd) and (be (odd))) 101 } 102 assert(caught2.getMessage === "2 was even") 103 104 val caught3 = intercept[TestFailedException] { 105 1 should (be (even) and be (even)) 106 } 107 assert(caught3.getMessage === "1 was odd") 108 109 val caught4 = intercept[TestFailedException] { 110 1 should (be (even) and (be (even))) 111 } 112 assert(caught4.getMessage === "1 was odd") 113 114 115 // first false 116 val caught5 = intercept[TestFailedException] { 117 1 should (be (even) and be (odd)) 118 } 119 assert(caught5.getMessage === "1 was odd") 120 121 val caught6 = intercept[TestFailedException] { 122 1 should (be (even) and (be (odd))) 123 } 124 assert(caught6.getMessage === "1 was odd") 125 126 val caught7 = intercept[TestFailedException] { 127 2 should (be (odd) and be (even)) 128 } 129 assert(caught7.getMessage === "2 was even") 130 131 val caught8 = intercept[TestFailedException] { 132 2 should (be (odd) and (be (even))) 133 } 134 assert(caught8.getMessage === "2 was even") 135 136 137// TODO: Remember to try a BeMatcher[Any] one, to make sure it works on an Int 138 139 // second false 140 val caught9 = intercept[TestFailedException] { 141 1 should (be (odd) and be (even)) 142 } 143 assert(caught9.getMessage === "1 was odd, but 1 was odd") 144 145 val caught10 = intercept[TestFailedException] { 146 1 should (be (odd) and (be (even))) 147 } 148 assert(caught10.getMessage === "1 was odd, but 1 was odd") 149 150 val caught11 = intercept[TestFailedException] { 151 2 should (be (even) and be (odd)) 152 } 153 assert(caught11.getMessage === "2 was even, but 2 was even") 154 155 val caught12 = intercept[TestFailedException] { 156 2 should (be (even) and (be (odd))) 157 } 158 assert(caught12.getMessage === "2 was even, but 2 was even") 159 } 160 161 it("should do nothing if at least one BeMatcher matches, when used in a logical-or expression") { 162 163 // both true 164 1 should (be (odd) or be (odd)) 165 1 should (be (odd) or (be (odd))) 166 2 should (be (even) or be (even)) 167 2 should (be (even) or (be (even))) 168 169 // first false 170 1 should (be (even) or be (odd)) 171 1 should (be (even) or (be (odd))) 172 2 should (be (odd) or be (even)) 173 2 should (be (odd) or (be (even))) 174 175 // second false 176 1 should (be (odd) or be (even)) 177 1 should (be (odd) or (be (even))) 178 2 should (be (even) or be (odd)) 179 2 should (be (even) or (be (odd))) 180 } 181 182 it("should throw TestFailedException if a BeMatcher does not match, when used in a logical-or expression") { 183 184 val caught1 = intercept[TestFailedException] { 185 2 should (be (odd) or be (odd)) 186 } 187 assert(caught1.getMessage === "2 was even, and 2 was even") 188 189 val caught2 = intercept[TestFailedException] { 190 2 should (be (odd) or (be (odd))) 191 } 192 assert(caught2.getMessage === "2 was even, and 2 was even") 193 194 val caught3 = intercept[TestFailedException] { 195 1 should (be (even) or be (even)) 196 } 197 assert(caught3.getMessage === "1 was odd, and 1 was odd") 198 199 val caught4 = intercept[TestFailedException] { 200 1 should (be (even) or (be (even))) 201 } 202 assert(caught4.getMessage === "1 was odd, and 1 was odd") 203 } 204 205 it("should do nothing if a BeMatcher does not match, when used in a logical-and expression with not") { 206 2 should (not be (odd) and not be (odd)) 207 2 should (not be (odd) and not (be (odd))) 208 2 should (not be (odd) and (not (be (odd)))) 209 1 should (not be (even) and not be (even)) 210 1 should (not be (even) and not (be (even))) 211 1 should (not be (even) and (not (be (even)))) 212 } 213 214 it("should throw TestFailedException if at least one BeMatcher matches, when used in a logical-and expression with not") { 215 216 // both true 217 val caught1 = intercept[TestFailedException] { 218 1 should (not be (odd) and not be (odd)) 219 } 220 assert(caught1.getMessage === "1 was odd") 221 222 val caught2 = intercept[TestFailedException] { 223 1 should (not be (odd) and not (be (odd))) 224 } 225 assert(caught2.getMessage === "1 was odd") 226 227 val caught3 = intercept[TestFailedException] { 228 1 should (not be (odd) and (not (be (odd)))) 229 } 230 assert(caught3.getMessage === "1 was odd") 231 232 val caught4 = intercept[TestFailedException] { 233 2 should (not be (even) and not be (even)) 234 } 235 assert(caught4.getMessage === "2 was even") 236 237 val caught5 = intercept[TestFailedException] { 238 2 should (not be (even) and not (be (even))) 239 } 240 assert(caught5.getMessage === "2 was even") 241 242 val caught6 = intercept[TestFailedException] { 243 2 should (not be (even) and (not (be (even)))) 244 } 245 assert(caught6.getMessage === "2 was even") 246 247 248 // first false 249 val caught7 = intercept[TestFailedException] { 250 1 should (not be (even) and not be (odd)) 251 } 252 assert(caught7.getMessage === "1 was odd, but 1 was odd") 253 254 val caught8 = intercept[TestFailedException] { 255 1 should (not be (even) and not (be (odd))) 256 } 257 assert(caught8.getMessage === "1 was odd, but 1 was odd") 258 259 val caught9 = intercept[TestFailedException] { 260 1 should (not be (even) and (not (be (odd)))) 261 } 262 assert(caught9.getMessage === "1 was odd, but 1 was odd") 263 264 val caught10 = intercept[TestFailedException] { 265 2 should (not be (odd) and not be (even)) 266 } 267 assert(caught10.getMessage === "2 was even, but 2 was even") 268 269 val caught11 = intercept[TestFailedException] { 270 2 should (not be (odd) and not (be (even))) 271 } 272 assert(caught11.getMessage === "2 was even, but 2 was even") 273 274 val caught12 = intercept[TestFailedException] { 275 2 should (not be (odd) and (not (be (even)))) 276 } 277 assert(caught12.getMessage === "2 was even, but 2 was even") 278 279 280 // second false 281 val caught13 = intercept[TestFailedException] { 282 1 should (not be (odd) and not be (even)) 283 } 284 assert(caught13.getMessage === "1 was odd") 285 286 val caught14 = intercept[TestFailedException] { 287 1 should (not be (odd) and not (be (even))) 288 } 289 assert(caught14.getMessage === "1 was odd") 290 291 val caught15 = intercept[TestFailedException] { 292 1 should (not be (odd) and (not (be (even)))) 293 } 294 assert(caught15.getMessage === "1 was odd") 295 296 val caught16 = intercept[TestFailedException] { 297 2 should (not be (even) and not be (odd)) 298 } 299 assert(caught16.getMessage === "2 was even") 300 301 val caught17 = intercept[TestFailedException] { 302 2 should (not be (even) and not (be (odd))) 303 } 304 assert(caught17.getMessage === "2 was even") 305 306 val caught18 = intercept[TestFailedException] { 307 2 should (not be (even) and (not (be (odd)))) 308 } 309 assert(caught18.getMessage === "2 was even") 310 } 311 312 it("should do nothing if at least one BeMatcher doesn't match, when used in a logical-or expression when used with not") { 313 314 // both false 315 2 should (not be (odd) or not be (odd)) 316 2 should (not be (odd) or not (be (odd))) 317 2 should (not be (odd) or (not (be (odd)))) 318 1 should (not be (even) or not be (even)) 319 1 should (not be (even) or not (be (even))) 320 1 should (not be (even) or (not (be (even)))) 321 322 // first false 323 1 should (not be (even) or not be (odd)) 324 1 should (not be (even) or not (be (odd))) 325 1 should (not be (even) or (not (be (odd)))) 326 2 should (not be (odd) or not be (even)) 327 2 should (not be (odd) or not (be (even))) 328 2 should (not be (odd) or (not (be (even)))) 329 330 // second false 331 1 should (not be (odd) or not be (even)) 332 1 should (not be (odd) or not (be (even))) 333 1 should (not be (odd) or (not (be (even)))) 334 2 should (not be (even) or not be (odd)) 335 2 should (not be (even) or not (be (odd))) 336 2 should (not be (even) or (not (be (odd)))) 337 } 338 339 it("should throw TestFailedException if both BeMatcher match, when used in a logical-or expression with not") { 340 341 val caught1 = intercept[TestFailedException] { 342 1 should (not be (odd) or not be (odd)) 343 } 344 assert(caught1.getMessage === "1 was odd, and 1 was odd") 345 346 val caught2 = intercept[TestFailedException] { 347 1 should (not be (odd) or not (be (odd))) 348 } 349 assert(caught2.getMessage === "1 was odd, and 1 was odd") 350 351 val caught3 = intercept[TestFailedException] { 352 1 should (not be (odd) or (not (be (odd)))) 353 } 354 assert(caught3.getMessage === "1 was odd, and 1 was odd") 355 356 val caught4 = intercept[TestFailedException] { 357 2 should (not be (even) or not be (even)) 358 } 359 assert(caught4.getMessage === "2 was even, and 2 was even") 360 361 val caught5 = intercept[TestFailedException] { 362 2 should (not be (even) or not (be (even))) 363 } 364 assert(caught5.getMessage === "2 was even, and 2 was even") 365 366 val caught6 = intercept[TestFailedException] { 367 2 should (not be (even) or (not (be (even)))) 368 } 369 assert(caught6.getMessage === "2 was even, and 2 was even") 370 } 371 372 it("should work when the types aren't exactly the same") { 373 374 class UnlikableMatcher extends BeMatcher[Any] { 375 def apply(left: Any): MatchResult = { 376 MatchResult( 377 false, 378 left.toString + " was not to my liking", 379 left.toString + " was to my liking" 380 ) 381 } 382 } 383 val unlikable = new UnlikableMatcher 384 val likable = not (unlikable) 385 386 1 should be (likable) 387 2 should not be (unlikable) 388 389 val caught1 = intercept[TestFailedException] { 390 1 should be (unlikable) 391 } 392 assert(caught1.getMessage === "1 was not to my liking") 393 394 val caught2 = intercept[TestFailedException] { 395 "The dish" should not be (likable) 396 } 397 assert(caught2.getMessage === "The dish was not to my liking") 398 } 399 } 400 describe("the compose method on BeMatcher") { 401 it("should return another BeMatcher") { 402 val oddAsInt = odd compose { (s: String) => s.toInt } 403 "3" should be (oddAsInt) 404 "4" should not be (oddAsInt) 405 } 406 } 407 describe("A factory method on BeMatcher's companion object") { 408 it("should produce a be-matcher that executes the passed function when its apply is called") { 409 val f = { (s: String) => MatchResult(s.length < 3, "s was not less than 3", "s was less than 3") } 410 val lessThanThreeInLength = BeMatcher(f) 411 "" should be (lessThanThreeInLength) 412 "x" should be (lessThanThreeInLength) 413 "xx" should be (lessThanThreeInLength) 414 "xxx" should not be (lessThanThreeInLength) 415 "xxxx" should not be (lessThanThreeInLength) 416 } 417 } 418} 419