102030405060708090100110120130140150160170180190200210220230240250260270280290300310320330340350360370380390400410420430440450460470480490500510520530540550560570580590600610620630640650660670680690700710720730740750760770780790800810820830840850860870880890900910920930940950960970980990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340 module trial.reporters.visualtrial; import std.conv; import std.string; import std.algorithm; import std.stdio; import std.datetime; import std.exception; version(Have_fluent_asserts) { import fluentasserts.core.base; import fluentasserts.core.results; } import trial.interfaces; import trial.reporters.writer; enum Tokens : string { beginTest = "BEGIN TEST;", endTest = "END TEST;", suite = "suite", test = "test", file = "file", line = "line", labels = "labels", status = "status", errorFile = "errorFile", errorLine = "errorLine", message = "message" } class VisualTrialReporter : ILifecycleListener, ITestCaseLifecycleListener { private { ReportWriter writer; } this() { writer = defaultWriter; } this(ReportWriter writer) { this.writer = writer; } void begin(ulong testCount) { writer.writeln("", ReportWriter.Context._default); writer.writeln("", ReportWriter.Context._default); } void update() { } void end(SuiteResult[]) { } void begin(string suite, ref TestResult result) { std.stdio.stdout.flush; std.stdio.stderr.flush; writer.writeln("BEGIN TEST;", ReportWriter.Context._default); writer.writeln("suite:" ~ suite, ReportWriter.Context._default); writer.writeln("test:" ~ result.name, ReportWriter.Context._default); writer.writeln("file:" ~ result.fileName, ReportWriter.Context._default); writer.writeln("line:" ~ result.line.to!string, ReportWriter.Context._default); writer.writeln("labels:[" ~ result.labels.map!(a => a.toString).join(", ") ~ "]", ReportWriter.Context._default); std.stdio.stdout.flush; std.stdio.stderr.flush; } void end(string suite, ref TestResult test) { std.stdio.stdout.flush; std.stdio.stderr.flush; writer.writeln("status:" ~ test.status.to!string, ReportWriter.Context._default); if(test.status != TestResult.Status.success) { if(test.throwable !is null) { writer.writeln("errorFile:" ~ test.throwable.file, ReportWriter.Context._default); writer.writeln("errorLine:" ~ test.throwable.line.to!string, ReportWriter.Context._default); writer.writeln("message:" ~ test.throwable.msg.split("\n")[0], ReportWriter.Context._default); writer.write("error:", ReportWriter.Context._default); writer.writeln(test.throwable.toString, ReportWriter.Context._default); } } writer.writeln("END TEST;", ReportWriter.Context._default); std.stdio.stdout.flush; std.stdio.stderr.flush; } } class VisualTrialReporterParser { TestResult testResult; string suite; bool readingTest; alias ResultEvent = void delegate(TestResult); alias OutputEvent = void delegate(string); ResultEvent onResult; OutputEvent onOutput; private { bool readingErrorMessage; } void add(string line) { if(line == Tokens.beginTest) { if(testResult is null) { testResult = new TestResult("unknown"); } readingTest = true; testResult.begin = Clock.currTime; testResult.end = Clock.currTime; return; } if(line == Tokens.endTest) { enforce(testResult !is null, "The test result was not created!"); readingTest = false; if(onResult !is null) { onResult(testResult); } readingErrorMessage = false; testResult = null; return; } if(!readingTest) { return; } if(readingErrorMessage) { testResult.throwable.msg ~= "\n" ~ line; return; } auto pos = line.indexOf(":"); if(pos == -1) { if(onOutput !is null) { onOutput(line); } return; } string token = line[0 .. pos]; string value = line[pos+1 .. $]; switch(token) { case Tokens.suite: suite = value; break; case Tokens.test: testResult.name = value; break; case Tokens.file: testResult.fileName = value; break; case Tokens.line: testResult.line = value.to!size_t; break; case Tokens.labels: testResult.labels = Label.fromJsonArray(value); break; case Tokens.status: testResult.status = value.to!(TestResult.Status); break; case Tokens.errorFile: if(testResult.throwable is null) { testResult.throwable = new ParsedVisualTrialException(); } testResult.throwable.file = value; break; case Tokens.errorLine: if(testResult.throwable is null) { testResult.throwable = new ParsedVisualTrialException(); } testResult.throwable.line = value.to!size_t; break; case Tokens.message: enforce(testResult.throwable !is null, "The throwable must exist!"); testResult.throwable.msg = value; readingErrorMessage = true; break; default: if(onOutput !is null) { onOutput(line); } } } } class ParsedVisualTrialException : Exception { this() { super(""); } }
module trial.reporters.visualtrial; import std.conv; import std.string; import std.algorithm; import std.stdio; import std.datetime; import std.exception; version(Have_fluent_asserts) { import fluentasserts.core.base; import fluentasserts.core.results; } import trial.interfaces; import trial.reporters.writer; enum Tokens : string { beginTest = "BEGIN TEST;", endTest = "END TEST;", suite = "suite", test = "test", file = "file", line = "line", labels = "labels", status = "status", errorFile = "errorFile", errorLine = "errorLine", message = "message" } class VisualTrialReporter : ILifecycleListener, ITestCaseLifecycleListener { private { ReportWriter writer; } this() { writer = defaultWriter; } this(ReportWriter writer) { this.writer = writer; } void begin(ulong testCount) { writer.writeln("", ReportWriter.Context._default); writer.writeln("", ReportWriter.Context._default); } void update() { } void end(SuiteResult[]) { } void begin(string suite, ref TestResult result) { std.stdio.stdout.flush; std.stdio.stderr.flush; writer.writeln("BEGIN TEST;", ReportWriter.Context._default); writer.writeln("suite:" ~ suite, ReportWriter.Context._default); writer.writeln("test:" ~ result.name, ReportWriter.Context._default); writer.writeln("file:" ~ result.fileName, ReportWriter.Context._default); writer.writeln("line:" ~ result.line.to!string, ReportWriter.Context._default); writer.writeln("labels:[" ~ result.labels.map!(a => a.toString).join(", ") ~ "]", ReportWriter.Context._default); std.stdio.stdout.flush; std.stdio.stderr.flush; } void end(string suite, ref TestResult test) { std.stdio.stdout.flush; std.stdio.stderr.flush; writer.writeln("status:" ~ test.status.to!string, ReportWriter.Context._default); if(test.status != TestResult.Status.success) { if(test.throwable !is null) { writer.writeln("errorFile:" ~ test.throwable.file, ReportWriter.Context._default); writer.writeln("errorLine:" ~ test.throwable.line.to!string, ReportWriter.Context._default); writer.writeln("message:" ~ test.throwable.msg.split("\n")[0], ReportWriter.Context._default); writer.write("error:", ReportWriter.Context._default); writer.writeln(test.throwable.toString, ReportWriter.Context._default); } } writer.writeln("END TEST;", ReportWriter.Context._default); std.stdio.stdout.flush; std.stdio.stderr.flush; } } class VisualTrialReporterParser { TestResult testResult; string suite; bool readingTest; alias ResultEvent = void delegate(TestResult); alias OutputEvent = void delegate(string); ResultEvent onResult; OutputEvent onOutput; private { bool readingErrorMessage; } void add(string line) { if(line == Tokens.beginTest) { if(testResult is null) { testResult = new TestResult("unknown"); } readingTest = true; testResult.begin = Clock.currTime; testResult.end = Clock.currTime; return; } if(line == Tokens.endTest) { enforce(testResult !is null, "The test result was not created!"); readingTest = false; if(onResult !is null) { onResult(testResult); } readingErrorMessage = false; testResult = null; return; } if(!readingTest) { return; } if(readingErrorMessage) { testResult.throwable.msg ~= "\n" ~ line; return; } auto pos = line.indexOf(":"); if(pos == -1) { if(onOutput !is null) { onOutput(line); } return; } string token = line[0 .. pos]; string value = line[pos+1 .. $]; switch(token) { case Tokens.suite: suite = value; break; case Tokens.test: testResult.name = value; break; case Tokens.file: testResult.fileName = value; break; case Tokens.line: testResult.line = value.to!size_t; break; case Tokens.labels: testResult.labels = Label.fromJsonArray(value); break; case Tokens.status: testResult.status = value.to!(TestResult.Status); break; case Tokens.errorFile: if(testResult.throwable is null) { testResult.throwable = new ParsedVisualTrialException(); } testResult.throwable.file = value; break; case Tokens.errorLine: if(testResult.throwable is null) { testResult.throwable = new ParsedVisualTrialException(); } testResult.throwable.line = value.to!size_t; break; case Tokens.message: enforce(testResult.throwable !is null, "The throwable must exist!"); testResult.throwable.msg = value; readingErrorMessage = true; break; default: if(onOutput !is null) { onOutput(line); } } } } class ParsedVisualTrialException : Exception { this() { super(""); } }