1 module feature_test.core; 2 3 debug (featureTest) { 4 import feature_test.exceptions; 5 import feature_test.runner; 6 7 import colorize; 8 9 import std.stdio; 10 import std.algorithm; 11 12 alias FTImplementation = void delegate(FeatureTest); 13 alias FTDelegate = void delegate(); 14 15 struct FeatureTestScenario { 16 string name; 17 FTDelegate implementation; 18 } 19 20 class FeatureTest { 21 alias info = FeatureTestRunner.info; 22 23 @property ref string name() { return _name; } 24 @property ref string description() { return _description; } 25 @property string[] tags() { return _tags; } 26 @property ref FeatureTestScenario[] scenarios() { return _scenarios; } 27 28 void addTags(string[] tags ...) { 29 foreach(tag; tags) { if (!_tags.canFind(tag)) _tags ~= tag; } 30 } 31 32 final void addBeforeAll(FTDelegate d) { 33 _beforeAllCallbacks ~= d; 34 } 35 36 final void addBeforeEach(FTDelegate d) { 37 _beforeEachCallbacks ~= d; 38 } 39 40 final void addAfterEach(FTDelegate d) { 41 _afterEachCallbacks ~= d; 42 } 43 44 final void addAfterAll(FTDelegate d) { 45 _afterAllCallbacks ~= d; 46 } 47 48 // To be overridden 49 void beforeAll() { 50 } 51 52 // To be overridden 53 void beforeEach() { 54 } 55 56 // To be overridden 57 void afterEach() { 58 } 59 60 // To be overridden 61 void afterAll() { 62 } 63 64 void scenario(string name, FTDelegate implementation) { 65 _scenarios ~= FeatureTestScenario(name, implementation); 66 } 67 68 package: 69 void _beforeAll() { 70 beforeAll; 71 runCallbacks(_beforeAllCallbacks); 72 } 73 74 void _beforeEach() { 75 beforeEach; 76 runCallbacks(_beforeEachCallbacks); 77 } 78 79 void _afterEach() { 80 runCallbacks(_afterEachCallbacks); 81 afterEach; 82 } 83 84 void _afterAll() { 85 runCallbacks(_afterAllCallbacks); 86 afterAll; 87 } 88 89 private: 90 string _name; 91 string _description; 92 string[] _tags; 93 94 FeatureTestScenario[] _scenarios; 95 FTDelegate[] _beforeEachCallbacks, _afterEachCallbacks, _beforeAllCallbacks, _afterAllCallbacks; 96 97 void runCallbacks(FTDelegate[] callbacks) { 98 foreach(callback; callbacks) callback(); 99 } 100 } 101 102 void feature(T)(string name, string description, void delegate(T) implementation, string[] tags ...) { 103 if (FeatureTestRunner.shouldInclude(tags)) { 104 auto f = new T(); 105 f.name = name; 106 f.description = description; 107 f.addTags(tags); 108 implementation(f); 109 FeatureTestRunner.features ~= f; 110 } 111 } 112 113 void feature(T)(string name, void delegate(T) implementation, string[] tags ...) { 114 feature!T(name, "", implementation, tags); 115 } 116 117 void feature(string name, string description, void delegate(FeatureTest) implementation, string[] tags ...) { 118 feature!FeatureTest(name, description, implementation, tags); 119 } 120 121 void feature(string name, void delegate(FeatureTest) implementation, string[] tags ...) { 122 feature!FeatureTest(name, "", implementation, tags); 123 } 124 125 /// Marks a scenario as pending 126 void featureTestPending(string file = __FILE__, typeof(__LINE__) line = __LINE__) { 127 throw new FeatureTestException(file, line); 128 } 129 }