1 /++ 2 Settings parser and structures 3 4 Copyright: © 2017 Szabo Bogdan 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Szabo Bogdan 7 +/ 8 module trial.settings; 9 import std.conv; 10 11 import trial.reporters.result; 12 import trial.reporters.spec; 13 import trial.reporters.specsteps; 14 import trial.reporters.dotmatrix; 15 import trial.reporters.landing; 16 import trial.reporters.progress; 17 18 version(Have_dub) { 19 import dub.internal.vibecompat.data.serialization; 20 } 21 22 /// 23 mixin template SettingsFields() 24 { 25 /* 26 bool colors; 27 bool sort; 28 bool bail;*/ 29 30 /** The reporter list that will be added by the runner at startup 31 * You can use here only the embeded reporters. 32 * If you want to use a custom reporter you can use `static this` constructor 33 * 34 * Examples: 35 * ------------------------ 36 * static this 37 * { 38 * LifeCycleListeners.instance.add(myCustomReporter); 39 * } 40 * ------------------------ 41 */ 42 string[] reporters = ["spec", "result"]; 43 44 /// The test discovery classes that you want to use 45 string[] testDiscovery = ["trial.discovery.unit.UnitTestDiscovery"]; 46 47 /// The number of threads tha you want to use 48 /// `0` means the number of cores that your processor has 49 uint maxThreads = 0; 50 51 /// 52 GlyphSettings glyphs; 53 54 /// Where to generate artifacts 55 string artifactsLocation = ".trial"; 56 57 /// Show the duration with yellow if it takes more `warningTestDuration` msecs 58 uint warningTestDuration = 20; 59 60 /// Show the duration with red if it takes more `dangerTestDuration` msecs 61 uint dangerTestDuration = 100; 62 63 /// A list of plugins that will be added as dependencies from 64 /// code.dlang.org. The plugins will be imported in the main file. 65 /// 66 /// For `trial-my-plugin` the import will be `import trialmyplugin.plugin`. 67 /// You will be able to create a module constructor that will add all your needed 68 /// lifecycle listeners. 69 string[] plugins = []; 70 71 /// The default executor is `SingleRunner`. If you want to use the 72 /// `ParallelExecutor` set this option to `parallel` or if you want 73 /// to use the `ProcessExecutor` set it to `process`. 74 string executor = "default"; 75 } 76 77 /// A structure representing the `trial.json` file 78 struct Settings 79 { 80 version(Have_dub) { 81 @optional { 82 mixin SettingsFields; 83 } 84 } else { 85 mixin SettingsFields; 86 } 87 } 88 89 mixin template GlyphSettingsFields() 90 { 91 /// 92 SpecGlyphs spec; 93 94 /// 95 SpecStepsGlyphs specSteps; 96 97 /// 98 TestResultGlyphs result; 99 100 /// 101 DotMatrixGlyphs dotMatrix; 102 103 /// 104 LandingGlyphs landing; 105 106 /// 107 ProgressGlyphs progress; 108 } 109 110 /// The gliph settings 111 struct GlyphSettings { 112 version(Have_dub) { 113 @optional { 114 mixin GlyphSettingsFields; 115 } 116 } else { 117 mixin GlyphSettingsFields; 118 } 119 } 120 121 /// Converts the settings object to DLang code. It's used by the generator 122 string toCode(Settings settings) 123 { 124 auto executor = settings.executor == "default" ? "" : settings.executor; 125 126 return "Settings(" ~ 127 settings.reporters.to!string ~ ", " ~ 128 settings.testDiscovery.to!string ~ ", " ~ 129 settings.maxThreads.to!string ~ ", " ~ 130 settings.glyphs.toCode ~ ", " ~ 131 `"` ~ settings.artifactsLocation ~ `", ` ~ 132 settings.warningTestDuration.to!string ~ `, ` ~ 133 settings.dangerTestDuration.to!string ~ ", " ~ 134 settings.plugins.to!string ~ ", " ~ 135 `"` ~ executor ~ `"` ~ 136 ")"; 137 } 138 139 /// Converts the GlyphSettings object to DLang code. It's used by the generator 140 string toCode(GlyphSettings settings) { 141 return "GlyphSettings(" ~ 142 specGlyphsToCode(settings.spec) ~ ", " ~ 143 specStepsGlyphsToCode(settings.specSteps) ~ ", " ~ 144 testResultGlyphsToCode(settings.result) ~ ", " ~ 145 dotMatrixGlyphsToCode(settings.dotMatrix) ~ ", " ~ 146 landingGlyphsToCode(settings.landing) ~ ", " ~ 147 progressGlyphsToCode(settings.progress) ~ 148 ")"; 149 } 150 151 version (unittest) 152 { 153 version(Have_fluent_asserts) { 154 import fluent.asserts; 155 } 156 } 157 158 /// it should be able to compile the settings code 159 unittest { 160 mixin("auto settings = " ~ Settings().toCode ~ ";"); 161 } 162 163 /// it should be able to transform the Settings to code 164 unittest 165 { 166 Settings settings; 167 168 settings.toCode.should.equal(`Settings(` ~ 169 `["spec", "result"], ` ~ 170 `["trial.discovery.unit.UnitTestDiscovery"], 0, ` ~ 171 "GlyphSettings(SpecGlyphs(`✓`), " ~ 172 "SpecStepsGlyphs(`┌`, `└`, `│`), "~ 173 "TestResultGlyphs(`✖`), " ~ 174 "DotMatrixGlyphs(`.`,`!`,`?`), " ~ 175 "LandingGlyphs(`✈`,`━`,`⋅`), " ~ 176 "ProgressGlyphs(`░`,`▓`)" ~ 177 "), " ~ 178 `".trial", ` ~ 179 `20, 100, [], ""`~ 180 `)`); 181 }