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._
19
20/*
21This has a bit of redundancy with several other specs, but was the
22original file I used to develop the matchers syntax, and it has a few
23tests that don't exist elsewhere, so I'm keeping it alive for now.
24*/
25class ShouldMatcherSpec extends Spec with ShouldMatchers {
26
27  describe("The be matcher") {
28
29    describe("(for booleans)") {
30
31      it("should do nothing when false is compared to false") {
32        false should be (false)
33      }
34
35      it("should do nothing when true is compared to true") {
36        true should be (true)
37      }
38
39      it("should throw an assertion error when not equal") {
40        val caught = intercept[TestFailedException] {
41          false should be (true)
42        }
43        assert(caught.getMessage === "false was not true")
44      }
45    }
46
47    describe("(for null)") {
48
49      it("should do nothing when null is compared to null") {
50        val o: String = null
51        o should be (null)
52        o should equal (null)
53      }
54
55      it("should throw an assertion error when non-null compared to null") {
56        val caught = intercept[TestFailedException] {
57          val o = "Helloooooo"
58          o should be (null)
59        }
60        assert(caught.getMessage === "\"Helloooooo\" was not null")
61      }
62
63      it("should do nothing when non-null is compared to not null") {
64        val o = "Helloooooo"
65        o should not { be (null) }
66      }
67
68      it("should throw an assertion error when null compared to not null") {
69        val caught1 = intercept[TestFailedException] {
70          val o: String = null
71          o should not { be (null) }
72        }
73        assert(caught1.getMessage === "The reference was null")
74      }
75
76      it("should work when used in a logical expression") {
77        val o: String = null
78        o should { be (null) and equal (null) }
79        o should { equal (null) and be (null) }
80      }
81    }
82
83    describe("(for Nil)") {
84
85      it("should do nothing when an empty list is compared to Nil") {
86        val emptyList = List[String]()
87        emptyList should be (Nil)
88        emptyList should equal (Nil)
89      }
90
91      it("should throw an assertion error when a non-empty list is compared to Nil") {
92        val nonEmptyList = List("Helloooooo")
93        val caught1 = intercept[TestFailedException] {
94          nonEmptyList should be (Nil)
95        }
96        assert(caught1.getMessage === "List(Helloooooo) was not equal to List()")
97        val caught2 = intercept[TestFailedException] {
98          nonEmptyList should equal (Nil)
99        }
100        assert(caught2.getMessage === "List(Helloooooo) did not equal List()")
101      }
102
103      it("should do nothing when non-null is compared to not null") {
104        val nonEmptyList = List("Helloooooo")
105        nonEmptyList should not { be (Nil) }
106        nonEmptyList should not { equal (Nil) }
107      }
108
109      it("should throw an assertion error when null compared to not null") {
110        val emptyList = List[String]()
111        val caught1 = intercept[TestFailedException] {
112          emptyList should not { be (Nil) }
113        }
114        assert(caught1.getMessage === "List() was equal to List()")
115
116        val caught3 = intercept[TestFailedException] {
117          emptyList should not { equal (Nil) }
118        }
119        assert(caught3.getMessage === "List() equaled List()")
120      }
121
122      it("should work when used in a logical expression") {
123        val emptyList = List[Int]()
124        emptyList should { be (Nil) and equal (Nil) }
125        emptyList should { equal (Nil) and be (Nil) } // Nada, and nada is nada
126      }
127    }
128
129    describe("(for None)") {
130
131        /* I think I should have tests for options somewhere
132        val option = Some(1)
133        option should equal (Some(1))
134      val option = Some(1)
135      option should not { equal (Some(2)) }
136
137         */
138      it("should do nothing when a None option is compared to None") {
139        val option: Option[String] = None
140        option should be (None)
141        option should equal (None)
142      }
143
144      it("should throw an assertion error when a Some is compared to None") {
145        val someString = Some("Helloooooo")
146        val caught1 = intercept[TestFailedException] {
147          someString should be (None)
148        }
149        assert(caught1.getMessage === "Some(Helloooooo) was not equal to None")
150        val caught2 = intercept[TestFailedException] {
151          someString should equal (None)
152        }
153        assert(caught2.getMessage === "Some(Helloooooo) did not equal None")
154      }
155
156      it("should do nothing when Some is compared to not None") {
157        val someString = Some("Helloooooo")
158        someString should not { be (None) }
159        someString should not { equal (None) }
160      }
161
162      it("should throw an assertion error when None compared to not None") {
163        val none = None
164        val caught1 = intercept[TestFailedException] {
165          none should not { be (None) }
166        }
167        assert(caught1.getMessage === "None was equal to None")
168
169        val caught3 = intercept[TestFailedException] {
170          none should not { equal (None) }
171        }
172        assert(caught3.getMessage === "None equaled None")
173
174        val noString: Option[String] = None
175        val caught5 = intercept[TestFailedException] {
176          noString should not { be (None) }
177        }
178        assert(caught5.getMessage === "None was equal to None")
179
180        val caught7 = intercept[TestFailedException] {
181          noString should not { equal (None) }
182        }
183        assert(caught7.getMessage === "None equaled None")
184      }
185
186      it("should work when used in a logical expression") {
187        val none = None
188        none should { be (None) and equal (None) }
189        none should { equal (None) and be (None) }
190        val noString: Option[String] = None
191        noString should { be (None) and equal (None) }
192        noString should { equal (None) and be (None) }
193      }
194    }
195
196    describe("(for Any)") {
197      it("should do nothing when equal") {
198        1 should be (1)
199        val option = Some(1)
200        option should be (Some(1))
201      }
202
203      it("should throw an assertion error when not equal") {
204        val caught = intercept[TestFailedException] {
205          1 should be (2)
206        }
207        assert(caught.getMessage === "1 was not equal to 2")
208      }
209
210      it("should do nothing when not equal and used with should not") {
211        1 should not { be (2) }
212        val option = Some(1)
213        option should not { be (Some(2)) }
214      }
215
216      it("should throw an assertion error when equal but used with should not") {
217        val caught = intercept[TestFailedException] {
218          1 should not { be (1) }
219        }
220        assert(caught.getMessage === "1 was equal to 1")
221      }
222    }
223  }
224
225  describe("The have word") {
226
227    it("should work with map and key, right after a 'should'") {
228      val map = Map(1 -> "Howdy")
229      map should contain key (1)
230      map should contain key (1)
231      map should equal { Map(1 -> "Howdy") }
232      val otherMap = Map("Howdy" -> 1)
233      otherMap should contain key ("Howdy")
234      otherMap should equal { Map("Howdy" -> 1) }
235      import scala.collection.immutable.TreeMap
236      val treeMap = TreeMap(1 -> "hi", 2 -> "howdy")
237      treeMap should contain key (1)
238    }
239
240    it("should work with map and key, in a logical expression") {
241      val map = Map(1 -> "Howdy")
242      // The compiler infer the type of the value to be Nothing if I say: map should { contain key 1 and equal (Map(1 -> "Howdy")) }
243      // map should { have.key[Int, String](1) and equal (Map(1 -> "Howdy")) }
244      map should { contain key (1) and equal (Map(1 -> "Howdy")) }
245      val otherMap = Map("Howdy" -> 1)
246      // otherMap should { have.key[String, Int]("Howdy") and equal (Map("Howdy" -> 1)) }
247      otherMap should { contain key ("Howdy") and equal (Map("Howdy" -> 1)) }
248    }
249
250    it("should work with map and key, right after a 'should not'") {
251      val map = Map(1 -> "Howdy")
252      map should not { contain key (2) }
253    }
254
255    it("should work with map and value, right after a 'should'") {
256      val map = Map(1 -> "Howdy")
257      map should contain value ("Howdy")
258      map should contain value ("Howdy")
259      map should equal { Map(1 -> "Howdy") }
260      val otherMap = Map("Howdy" -> 1)
261      otherMap should contain value (1)
262      otherMap should equal { Map("Howdy" -> 1) }
263    }
264
265    it("should work with map and value, in a logical expression") {
266      val map = Map(1 -> "Howdy")
267      map should { equal (Map(1 -> "Howdy")) and (contain value "Howdy") }
268      val otherMap = Map("Howdy" -> 1)
269      otherMap should { contain value (1) and equal (Map("Howdy" -> 1)) }
270    }
271
272    it("should work with map and value, right after a 'should not'") {
273      val map = Map(1 -> "Howdy")
274      map should not { contain value ("Doody") }
275    }
276
277    it("should work with collection and size, in an and expression.") {
278      val list = List(1, 2, 3)
279      list should { have size (3) and equal (List(1, 2, 3)) }
280    }
281
282    it("should work with collection and size, right after a 'should'") {
283
284      val map = Map(1 -> "Howdy")
285      map should have size (1)
286      val caught1 = intercept[TestFailedException] {
287        map should have size (5)
288      }
289      assert(caught1.getMessage.indexOf("did not have size") != -1)
290
291      val list = List(1, 2, 3, 4, 5)
292      list should have size (5)
293      val caught2 = intercept[TestFailedException] {
294        list should have size (6)
295      }
296      assert(caught2.getMessage.indexOf("did not have size") != -1)
297
298      val set = Set(1.0, 2.0, 3.0)
299      set should have size (3)
300      val caught3 = intercept[TestFailedException] {
301        set should have size (0)
302      }
303      assert(caught3.getMessage.indexOf("did not have size") != -1)
304
305      val array = Array[String]()
306      array should have size 0
307      val caught4 = intercept[TestFailedException] {
308        array should have size 2
309      }
310      assert(caught4.getMessage.indexOf("did not have size") != -1)
311    }
312
313    it("should work with collection and size, right after a 'should not'") {
314
315      val map = Map(1 -> "Howdy")
316      map should not { have size (2) }
317      val caught1 = intercept[TestFailedException] {
318        map should not { have size (1) }
319      }
320      assert(caught1.getMessage.indexOf("had size") != -1, caught1.getMessage)
321
322      val list = List(1, 2, 3, 4, 5)
323      list should not { have size (6) }
324      val caught2 = intercept[TestFailedException] {
325        list should not { have size (5) }
326      }
327      assert(caught2.getMessage.indexOf("had size") != -1)
328
329      val set = Set(1.0, 2.0, 3.0)
330      set should not { have size (0) }
331      val caught3 = intercept[TestFailedException] {
332        set should not { have size (3) }
333      }
334      assert(caught3.getMessage.indexOf("had size") != -1)
335
336      val array = Array[String]()
337      array should not { have size (2) }
338      val caught4 = intercept[TestFailedException] {
339        array should not { have size (0) }
340      }
341      assert(caught4.getMessage.indexOf("had size") != -1)
342    }
343  }
344
345  describe("The contain word") {
346
347    it("should work with a set, list, array, and map right after a 'should'") {
348
349      val set = Set(1, 2, 3)
350      set should contain (2)
351      val caught1 = intercept[TestFailedException] {
352        set should contain (5)
353      }
354      assert(caught1.getMessage.indexOf("did not contain element") != -1)
355
356      set should { contain (2) and equal (Set(1, 2, 3)) }
357      val caught1b = intercept[TestFailedException] {
358        set should { contain (5) and equal(Set(1, 2, 3)) }
359      }
360      assert(caught1b.getMessage.indexOf("did not contain element") != -1)
361
362      val list = List("one", "two", "three")
363      list should contain ("two")
364      val caught2 = intercept[TestFailedException] {
365        list should contain ("five")
366      }
367      assert(caught2.getMessage.indexOf("did not contain element") != -1)
368
369      val array = Array("one", "two", "three")
370      array should contain ("one")
371      val caught3 = intercept[TestFailedException] {
372        array should contain ("five")
373      }
374      assert(caught3.getMessage.indexOf("did not contain element") != -1)
375
376      val map = Map(1 -> "one", 2 -> "two", 3 -> "three")
377      val tuple2: Tuple2[Int, String] = 1 -> "one"
378      map should contain (tuple2)
379      val caught4 = intercept[TestFailedException] {
380        map should contain (1 -> "won")
381      }
382      assert(caught4.getMessage.indexOf("did not contain element") != -1)
383    }
384
385    it("should work with a set, list, array, and map right after a 'should not'") {
386
387      val set = Set(1, 2, 3)
388      set should not { contain (5) }
389      val caught1 = intercept[TestFailedException] {
390        set should not { contain (2) }
391      }
392      assert(caught1.getMessage.indexOf("contained element") != -1)
393
394      val list = List("one", "two", "three")
395      list should not { contain ("five") }
396      val caught2 = intercept[TestFailedException] {
397        list should not { contain ("two") }
398      }
399      assert(caught2.getMessage.indexOf("contained element") != -1)
400
401      val array = Array("one", "two", "three")
402      array should not { contain ("five") }
403      val caught3 = intercept[TestFailedException] {
404        array should not { contain ("one") }
405      }
406      assert(caught3.getMessage.indexOf("contained element") != -1)
407
408      val map = Map(1 -> "one", 2 -> "two", 3 -> "three")
409      val tuple2: Tuple2[Int, String] = 1 -> "won"
410      map should not { contain (tuple2) }
411      val caught4 = intercept[TestFailedException] {
412        map should not { contain (1 -> "one") }
413      }
414      assert(caught4.getMessage.indexOf("contained element") != -1)
415    }
416  }
417
418  describe("The be theSameInstanceAs syntax") {
419
420    val string = "Hi"
421    val obj: AnyRef = string
422    val otherString = new String("Hi")
423
424    it("should do nothing if the two objects are the same") {
425      string should be theSameInstanceAs (string)
426      obj should be theSameInstanceAs (string)
427      string should be theSameInstanceAs (obj)
428      otherString should not { be theSameInstanceAs (string) }
429    }
430
431    it("should throw TestFailedException if the two objects are not the same") {
432      val caught1 = intercept[TestFailedException] {
433        string should not { be theSameInstanceAs (string) }
434      }
435      val caught2 = intercept[TestFailedException] {
436        obj should not { be theSameInstanceAs (string) }
437      }
438      val caught3 = intercept[TestFailedException] {
439        string should not { be theSameInstanceAs (obj) }
440      }
441      val caught4 = intercept[TestFailedException] {
442        otherString should be theSameInstanceAs (string)
443      }
444      assert(true) // TODO: test the failure message
445    }
446  }
447
448  describe("The floating point numbers when compared with equals") {
449    it("should do nothing if the floating point number is exactly equal to the specified value") {
450      val sevenDotOh = 7.0
451      sevenDotOh should be (7.0)
452      sevenDotOh should equal (7.0)
453      sevenDotOh should not { be (7.0001) }
454
455      val sixDotOh: Float = 6.0f
456      sixDotOh should be (6.0)
457      sixDotOh should equal (6.0)
458      sixDotOh should not { be (6.0001) }
459    }
460
461    it("should throw TestFailedException if the floating point number is not exactly equal to the specified value") {
462      val sevenDotOh = 7.0001
463      val caught1 = intercept[TestFailedException] {
464        sevenDotOh should be (7.0)
465        // sevenDotOh should be (7.0 exactly)
466      }
467      assert(caught1.getMessage === "7.0001 was not equal to 7.0")
468
469      val caught2 = intercept[TestFailedException] {
470        sevenDotOh should equal (7.0)
471      }
472      assert(caught2.getMessage === "7.0001 did not equal 7.0")
473
474      val caught3 = intercept[TestFailedException] {
475        sevenDotOh should not { be (7.0001) }
476      }
477      assert(caught3.getMessage === "7.0001 was equal to 7.0001")
478
479      val sixDotOh: Float = 6.0001f
480      val caught4 = intercept[TestFailedException] {
481        // sixDotOh should be (6.0f exactly)
482        sixDotOh should be (6.0f)
483      }
484      assert(caught4.getMessage === "6.0001 was not equal to 6.0")
485
486      val caught5 = intercept[TestFailedException] {
487        sixDotOh should equal (6.0f)
488      }
489      assert(caught5.getMessage === "6.0001 did not equal 6.0")
490
491      val caught6 = intercept[TestFailedException] {
492        sixDotOh should not { be (6.0001f) }
493      }
494      assert(caught6.getMessage === "6.0001 was equal to 6.0001")
495    }
496  }
497
498  describe("The floating point 'plusOrMinus' operator") {
499    it("should do nothing if the floating point number is within the specified range") {
500      val sevenDotOh = 7.0
501      sevenDotOh should be (7.1 plusOrMinus 0.2)
502      sevenDotOh should be (6.9 plusOrMinus 0.2)
503      sevenDotOh should not { be (7.5 plusOrMinus 0.2) }
504      sevenDotOh should not { be (6.5 plusOrMinus 0.2) }
505      val minusSevenDotOh = -7.0
506      minusSevenDotOh should be (-7.1 plusOrMinus 0.2)
507      minusSevenDotOh should be (-6.9 plusOrMinus 0.2)
508      minusSevenDotOh should not { be (-7.5 plusOrMinus 0.2) }
509      minusSevenDotOh should not { be (-6.5 plusOrMinus 0.2) }
510    }
511
512    it("should throw TestFailedException if the floating point number is not within the specified range") {
513      val sevenDotOh = 7.0
514      val caught1 = intercept[TestFailedException] {
515        sevenDotOh should not { be (7.1 plusOrMinus 0.2) }
516      }
517      assert(caught1.getMessage === "7.0 was 7.1 plus or minus 0.2")
518
519      val caught2 = intercept[TestFailedException] {
520        sevenDotOh should not { be (6.9 plusOrMinus 0.2) }
521      }
522      assert(caught2.getMessage === "7.0 was 6.9 plus or minus 0.2")
523
524      val caught3 = intercept[TestFailedException] {
525        sevenDotOh should be (7.5 plusOrMinus 0.2)
526      }
527      assert(caught3.getMessage === "7.0 was not 7.5 plus or minus 0.2")
528
529      val caught4 = intercept[TestFailedException] {
530        sevenDotOh should be (6.5 plusOrMinus 0.2)
531      }
532      assert(caught4.getMessage === "7.0 was not 6.5 plus or minus 0.2")
533
534      val minusSevenDotOh = -7.0
535      val caught5 = intercept[TestFailedException] {
536        minusSevenDotOh should not { be (-7.1 plusOrMinus 0.2) }
537      }
538      assert(caught5.getMessage === "-7.0 was -7.1 plus or minus 0.2")
539
540      val caught6 = intercept[TestFailedException] {
541        minusSevenDotOh should not { be (-6.9 plusOrMinus 0.2) }
542      }
543      assert(caught6.getMessage === "-7.0 was -6.9 plus or minus 0.2")
544
545      val caught7 = intercept[TestFailedException] {
546        minusSevenDotOh should be (-7.5 plusOrMinus 0.2)
547      }
548      assert(caught7.getMessage === "-7.0 was not -7.5 plus or minus 0.2")
549
550      val caught8 = intercept[TestFailedException] {
551        minusSevenDotOh should be (-6.5 plusOrMinus 0.2)
552      }
553      assert(caught8.getMessage === "-7.0 was not -6.5 plus or minus 0.2")
554    }
555  }
556}
557