71 / 79 lines covered (89.9%)
1use BDD::Behave::Benchmark::Format;2use BDD::Behave::Formatter;34unit class BDD::Behave::Formatter::JSON does BDD::Behave::Formatter;56has @!description-stack;7has @!examples;8has Str $!pending-auto-description;9has Bool $!multi-file = False;10has Int $!seed;11has Str $!order = 'defined';12has Bool $!emitted = False;13has Real $!start-time;14has @!load-errors;1516method name(--> Str) { 'json' }1718method !full-description(Str $description --> Str) {19 my @parts = @!description-stack.clone;20 @parts.push: $description;21 @parts.grep(*.defined).join(' ');22}2324method !ex-record($example, Str $status, %extras = %()) {25 my $description = $!pending-auto-description // $example.description;26 my %record = (27 description => $description,28 full_description => self!full-description($description),29 status => $status,30 file => $example.file.Str,31 line => $example.line,32 duration => $example.duration.defined ?? $example.duration.Real !! Real,33 tags => $example.effective-tags.List,34 );35 for %extras.kv -> $k, $v { %record{$k} = $v }36 %record;37}3839method suite-loading(Str :$file) { }4041method suite-start($suite, Bool :$multi-file = False) {42 $!multi-file = $multi-file;43 $!start-time //= now.Real;44}4546method suite-end($suite) { }4748method group-start($group) {49 @!description-stack.push: $group.description;50}5152method group-end($group) {53 @!description-stack.pop;54}5556method group-around-skipped($group) { }5758method example-start($example, Bool :$auto = False) {59 $!pending-auto-description = Str;60}6162method example-auto-description($example, Str :$description) {63 $!pending-auto-description = $description;64}6566method example-pass($example) {67 @!examples.push: self!ex-record($example, 'passed');68 $!pending-auto-description = Str;69}7071method example-fail($example, :$failure-info) {72 my %fail = ();7374 if $failure-info.defined {75 if $failure-info<exception>.defined {76 %fail<type> = 'exception';77 %fail<message> = $failure-info<exception>.message;78 }79 elsif $failure-info<message>.defined {80 %fail<type> = 'exception';81 %fail<message> = $failure-info<message>;82 }83 elsif $failure-info<exception-message>.defined {84 %fail<type> = 'exception';85 %fail<message> = $failure-info<exception-message>;86 }8788 if $failure-info<file>.defined { %fail<file> = $failure-info<file>.Str }89 if $failure-info<line>.defined { %fail<line> = $failure-info<line> }9091 if $failure-info<expectations>.defined && $failure-info<expectations>.elems {92 %fail<expectations> = $failure-info<expectations>.List;93 }94 }9596 @!examples.push: self!ex-record($example, 'failed', %( failure => %fail ));97 $!pending-auto-description = Str;98}99100method example-pending($example) {101 my %extras = ();102 my $reason = $example.get-metadata('pending-reason');103 %extras<pending_reason> = $reason if $reason.defined;104 @!examples.push: self!ex-record($example, 'pending', %extras);105}106107method example-skipped($example) {108 @!examples.push: self!ex-record($example, 'skipped');109}110111method example-around-skipped($example) {112 @!examples.push: self!ex-record(113 $example, 'skipped',114 %( skip_reason => 'around-each did not invoke continuation' ),115 );116}117118method example-slow($example, Real :$threshold) { }119120method run-summary(121 $result,122 Bool :$aborted = False,123 Int :$fail-fast = 0,124 Str :$order = 'defined',125 Int :$seed,126) {127 $!seed = $seed if $seed.defined;128 $!order = $order if $order.defined;129 return if $!multi-file;130 self!emit($result, :$aborted, :$fail-fast);131}132133method profile-summary(@records, Int :$limit) { }134135method benchmark-summary-section(136 @summaries, @regressions,137 Real :$threshold,138 Str :$format,139 IO::Path :$output,140 :$runner,141) { }142143method multi-file-overall(144 $result,145 Str :$order = 'defined',146 Int :$seed,147) {148 $!seed = $seed if $seed.defined;149 $!order = $order;150 self!emit($result);151}152153method multi-file-profile($runner, @records, Int :$limit) { }154method multi-file-benchmark(155 $runner,156 @summaries, @regressions,157 Real :$threshold,158 Str :$format,159 IO::Path :$output,160) { }161162method load-errors(@errors) {163 for @errors -> $err {164 @!load-errors.push: %(165 file => $err<file>.Str,166 message => $err<message>.Str,167 );168 }169}170171method !emit($result, Bool :$aborted = False, Int :$fail-fast = 0) {172 return if $!emitted;173 $!emitted = True;174175 my %summary = (176 total => $result.total,177 passed => $result.passed,178 failed => $result.failed,179 pending => $result.pending,180 skipped => $result.skipped,181 duration => ($!start-time.defined ?? (now.Real - $!start-time) !! Real),182 );183184 my %doc = (185 version => 1,186 summary => %summary,187 summary_line => self!summary-line($result),188 seed => $!seed,189 order => $!order,190 aborted => $aborted,191 examples => @!examples.List,192 load_errors => @!load-errors.List,193 );194195 say BDD::Behave::Benchmark::Format::to-json(%doc);196}197198method !summary-line($result --> Str) {199 my @parts;200 @parts.push: "{$result.total} example" ~ ($result.total == 1 ?? '' !! 's');201 @parts.push: "{$result.failed} failed" if $result.failed > 0;202 @parts.push: "{$result.pending} pending" if $result.pending > 0;203 @parts.push: "{$result.skipped} skipped" if $result.skipped > 0;204 @parts.push: "{$result.passed} passed" if $result.passed > 0;205 @parts.join(', ');206}