1 module shoul; 2 3 import std.conv; 4 import std.stdio; 5 6 public auto should(T)(T v) 7 { 8 return Should!T(v); 9 } 10 11 private struct Should(T) 12 { 13 T actual; 14 bool negative; 15 this(T actual) 16 { 17 this.actual = actual; 18 } 19 20 void opEquals(R)(const R other) const 21 { 22 assert(negative ^ (other == actual), text("expected - " ~ (negative ? "not " : ""), other, ", but got - ", actual)); 23 } 24 25 auto not() 26 { 27 this.negative = !this.negative; 28 return this; 29 } 30 31 void opBinary(string op, R)(const R rhs) const 32 { 33 static if (op == "in") 34 { 35 import std.algorithm : canFind; 36 37 static if (__traits(compiles, (actual in rhs))) 38 { 39 assert(negative ^ ((actual in rhs) != null), text("expected - ", actual, " in ", rhs)); 40 } 41 else 42 { 43 assert(negative ^ canFind(rhs, actual), text("expected - ", actual, " in ", rhs)); 44 } 45 } 46 else 47 static assert(0, "not supported op"); 48 } 49 50 void less(R)(R rhs) 51 { 52 assert(negative ^ (actual < rhs), text("expected - ", actual, " < ", rhs)); 53 } 54 55 void more(R)(R rhs) 56 { 57 assert(negative ^ (actual > rhs), text("expected - ", actual, " > ", rhs)); 58 } 59 } 60 61 @("Equal") @should 62 unittest 63 { 64 10.should == 10; 65 10.should.not == 11; 66 try 67 10.should.not == 10; 68 catch (Throwable e) 69 { 70 } 71 } 72 73 @("In") @should 74 unittest 75 { 76 10.should in [10, 11, 12]; 77 10.should.not in [11, 12, 13]; 78 try 79 10.should.not in [10, 11, 12]; 80 catch (Throwable e) 81 { 82 } 83 10.should in [10: 11, 12: 13]; 84 "Hello".should in "Hello World"; 85 } 86 87 @("Less") @should 88 unittest 89 { 90 10.should.less = 11; 91 10.should.not.less = 10; 92 10.should.not.less = 9; 93 } 94 95 @("more") @should 96 unittest 97 { 98 10.should.more = 9; 99 10.should.not.more = 10; 100 10.should.not.more = 11; 101 }