1 module dshould; 2 3 import dshould.ShouldType; 4 5 public import dshould.basic; 6 public import dshould.contain; 7 public import dshould.empty; 8 public import dshould.stringcmp; 9 public import dshould.thrown; 10 11 // dispatch based on type 12 void equal(Should, T)(Should should, T value, string file = __FILE__, size_t line = __LINE__) 13 if (isInstanceOf!(ShouldType, Should)) 14 { 15 static if (is(typeof(should.data.lhs()) == string) && is(T == string) && !Should.hasWord!"not") 16 { 17 dshould.stringcmp.equal(should, value, file, line); 18 } 19 else 20 { 21 dshould.basic.equal(should, value, file, line); 22 } 23 } 24 25 auto equal(Should)(Should should) 26 if (isInstanceOf!(ShouldType, Should)) 27 { 28 return should.basic.equal(should); 29 } 30 31 template throwA(T : Throwable) 32 { 33 void throwA(Should, string file = __FILE__)(Should should, string msgTest, size_t line = __LINE__) 34 if (isInstanceOf!(ShouldType, Should)) 35 { 36 dshould.thrown.throwA!T(should, file, line).where.its.msg.should.equal(msgTest, file, line); 37 } 38 39 auto throwA(Should, string file = __FILE__)(Should should, size_t line = __LINE__) 40 if (isInstanceOf!(ShouldType, Should)) 41 { 42 return dshould.thrown.throwA!T(should, file, line); 43 } 44 } 45 46 alias throwAn = throwA; 47 48 @("compares messages in throwA string overload") 49 unittest 50 { 51 2.should.be(5).because("string A") 52 .should.throwA!FluentException("string B") 53 .should.throwA!FluentException; 54 } 55 56 unittest 57 { 58 2.should.be(5).should.throwA!FluentException("test failed: expected 5, but got 2"); 59 } 60 61 @("prints informative errors for int comparison") 62 unittest 63 { 64 2.should.be(3).should.throwA!FluentException("test failed: expected 3, but got 2"); 65 } 66 67 @("prints informative errors for object comparison") 68 unittest 69 { 70 Object obj; 71 72 obj.should.not.be(null) 73 .should.throwA!FluentException("test failed: expected non-null, but got null"); 74 75 obj = new Object; 76 77 obj.should.be(null) 78 .should.throwA!FluentException("test failed: expected null, but got object.Object"); 79 80 obj.should.not.be(obj) 81 .should.throwA!FluentException( 82 "test failed: expected different reference than object.Object, but got object.Object"); 83 84 obj.should.be(new Object) 85 .should.throwA!FluentException( 86 "test failed: expected same reference as object.Object, but got object.Object"); 87 } 88 89 @("prints informative errors for inequalities") 90 unittest 91 { 92 2.should.be.greater.equal(5) 93 .should.throwA!FluentException("test failed: expected value >= 5, but got 2"); 94 95 2.should.not.be.smaller.equal(5) 96 .should.throwA!FluentException("test failed: expected value not <= 5, but got 2"); 97 } 98 99 @("prints informative errors for array emptiness") 100 unittest 101 { 102 [].should.not.be.empty 103 .should.throwA!FluentException("test failed: expected nonempty array"); 104 105 [5].should.be.empty 106 .should.throwA!FluentException("test failed: expected empty array, but got [5]"); 107 } 108 109 @("prints informative errors for approximate checks") 110 unittest 111 { 112 2.should.approximately(0.5).be(4) 113 .should.throwA!FluentException("test failed: expected 4 ± 0.5, but got 2"); 114 115 (2.4).should.not.approximately(0.5).be(2) 116 .should.throwA!FluentException("test failed: expected value outside 2 ± 0.5, but got 2.4"); 117 } 118 119 @("asserts when forgetting to terminate should expression") 120 unittest 121 { 122 import core.exception : AssertError; 123 124 void test() 125 { 126 2.should; 127 } 128 129 test.should.throwAn!AssertError("unterminated should-chain!"); 130 }