1 module specd.specification; 2 3 import specd.matchers; 4 5 import std.stdio; 6 7 auto describe(string title) { 8 return new SpecificationGroup(title); 9 } 10 11 version(SpecDTests) unittest { 12 13 int executionSequence = 0; 14 int executionFlag = 0; 15 bool executionRan = false; 16 17 describe("A SpecificationGroup with ordered parts").as( 18 (it) { it.should("execute each part", (executionSequence++).must.equal(0)); }, 19 (it) { it.should("execute its parts in order", (executionSequence++).must.equal(1)); } 20 ); 21 22 describe("A SpecificationGroup with unordered parts").should([ 23 "execute each part": { 24 executionFlag |= 1; 25 }, 26 "execute its parts in any order": { 27 executionFlag |= 2; 28 } 29 ]) 30 ; 31 32 assert(executionFlag == 3, "Did not execute all parts of the unordered SpecificationGroup"); 33 34 describe("A SpecificationGroup with a single part") 35 .should("execute the part", executionRan = true); 36 37 assert(executionRan, "Did not execute the single specification"); 38 } 39 40 class Specification { 41 package: 42 string test; 43 MatchException exception; 44 45 this(string test) { 46 this.test = test; 47 this.exception = null; 48 } 49 50 this(string test, MatchException exception) { 51 this.test = test; 52 this.exception = exception; 53 } 54 public: 55 @property bool isSuccess() { return exception is null; } 56 } 57 58 class SpecificationGroup { 59 package: 60 alias Block = void delegate(); 61 alias ItBlock = void delegate(SpecificationGroup); 62 63 static SpecificationGroup[] allSpecs; 64 65 string title; 66 Specification[] results; 67 68 this(string title) { 69 this.title = title; 70 allSpecs ~= this; 71 } 72 73 public: 74 @property bool isSuccess() { 75 foreach(result; results) { 76 if (!result.isSuccess) 77 return false; 78 } 79 return true; 80 } 81 82 @property Specification[] specifications() { return results; } 83 84 void as(ItBlock[] parts ...) { 85 foreach(part; parts) { 86 part(this); 87 } 88 } 89 90 auto should(Block[string] parts) { 91 foreach (key, value; parts) { 92 try { 93 value(); 94 results ~= new Specification(key); 95 } catch (MatchException e) { 96 results ~= new Specification(key, e); 97 } 98 } 99 return this; 100 } 101 auto should(string text, lazy void test) { 102 try { 103 test(); 104 results ~= new Specification(text); 105 } catch (MatchException e) { 106 results ~= new Specification(text, e); 107 } 108 return this; 109 } 110 auto should(string text, ItBlock test) { 111 try { 112 test(this); 113 results ~= new Specification(text); 114 } catch (MatchException e) { 115 results ~= new Specification(text, e); 116 } 117 return this; 118 } 119 }