mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add docs
This commit is contained in:
parent
a4042a9684
commit
877831a98b
12 changed files with 104 additions and 4 deletions
|
@ -1,16 +1,28 @@
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Base type for handling indented output.
|
||||||
|
# Indents are tracked and automatically printed.
|
||||||
|
# Use `#indent` to increase the indent for the duration of a block.
|
||||||
|
# Use `#line` to produce a line with an indentation prefixing it.
|
||||||
abstract struct Block
|
abstract struct Block
|
||||||
|
# Default indent amount.
|
||||||
private INDENT = 2
|
private INDENT = 2
|
||||||
|
|
||||||
|
# Creates the block.
|
||||||
|
# A default *indent* size can be specified.
|
||||||
def initialize(*, @indent : Int32 = INDENT)
|
def initialize(*, @indent : Int32 = INDENT)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Increases the indent by the a specific *amount* for the duration of the block.
|
||||||
private def indent(amount = INDENT)
|
private def indent(amount = INDENT)
|
||||||
@indent += amount
|
@indent += amount
|
||||||
yield
|
yield
|
||||||
@indent -= amount
|
@indent -= amount
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces a line of output with an indent before it.
|
||||||
|
# The contents of the line should be generated by a block provided to this method.
|
||||||
|
# Ensure that _only_ one line is produced by the block,
|
||||||
|
# otherwise the indent will be lost.
|
||||||
private def line(io)
|
private def line(io)
|
||||||
@indent.times { io << ' ' }
|
@indent.times { io << ' ' }
|
||||||
yield
|
yield
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
require "colorize"
|
require "colorize"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Object that can be stringified pre-pended with a comment mark (#).
|
||||||
struct Comment(T)
|
struct Comment(T)
|
||||||
|
# Default color for a comment.
|
||||||
private COLOR = :cyan
|
private COLOR = :cyan
|
||||||
|
|
||||||
|
# Creates a comment with the specified content.
|
||||||
def initialize(@content : T)
|
def initialize(@content : T)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a colored comment.
|
||||||
def self.colorize(content)
|
def self.colorize(content)
|
||||||
new(content).colorize(COLOR)
|
new(content).colorize(COLOR)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Writes the comment to the output.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << '#'
|
io << '#'
|
||||||
io << ' '
|
io << ' '
|
||||||
|
|
|
@ -4,41 +4,51 @@ require "../../error_result"
|
||||||
require "./result_block"
|
require "./result_block"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays information about an error result.
|
||||||
struct ErrorResultBlock < ResultBlock
|
struct ErrorResultBlock < ResultBlock
|
||||||
|
# Creates the component.
|
||||||
def initialize(index : Int32, example : Example, @result : ErrorResult)
|
def initialize(index : Int32, example : Example, @result : ErrorResult)
|
||||||
super(index, example)
|
super(index, example)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Content displayed on the second line of the block after the label.
|
||||||
private def subtitle
|
private def subtitle
|
||||||
@result.error.message.try(&.each_line.first)
|
@result.error.message.try(&.each_line.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Prefix for the second line of the block.
|
||||||
private def subtitle_label
|
private def subtitle_label
|
||||||
"Error: ".colorize(:red)
|
"Error: ".colorize(:red)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Display error information.
|
||||||
private def content(io)
|
private def content(io)
|
||||||
|
# Fetch the error and message.
|
||||||
|
# If there's no message
|
||||||
error = @result.error
|
error = @result.error
|
||||||
lines = error.message.try(&.lines) || {"<blank>".colorize(:purple)}
|
lines = error.message.try(&.lines) || {"<blank>".colorize(:purple)}
|
||||||
|
|
||||||
|
# Display the error type and first line of the message.
|
||||||
line(io) do
|
line(io) do
|
||||||
io << "#{error.class}: ".colorize(:red)
|
io << "#{error.class}: ".colorize(:red)
|
||||||
io << lines.first
|
io << lines.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Display additional lines after the first if there's any.
|
||||||
lines.skip(1).each do |entry|
|
lines.skip(1).each do |entry|
|
||||||
line(io) do
|
line(io) { io << entry }
|
||||||
io << entry
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
error.backtrace?.try do |backtrace|
|
# Display the backtrace if it's available.
|
||||||
|
if backtrace = error.backtrace?
|
||||||
indent { write_backtrace(io, backtrace) }
|
indent { write_backtrace(io, backtrace) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Writes the backtrace entries to the output.
|
||||||
private def write_backtrace(io, backtrace)
|
private def write_backtrace(io, backtrace)
|
||||||
backtrace.each do |entry|
|
backtrace.each do |entry|
|
||||||
|
# Dim entries that are outside the shard.
|
||||||
entry = entry.colorize.dim unless entry.starts_with?(/(src|spec)\//)
|
entry = entry.colorize.dim unless entry.starts_with?(/(src|spec)\//)
|
||||||
line(io) { io << entry }
|
line(io) { io << entry }
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
require "../../example"
|
||||||
require "./comment"
|
require "./comment"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Provides syntax for running a specific example from the command-line.
|
||||||
struct ExampleCommand
|
struct ExampleCommand
|
||||||
|
# Creates the component with the specified example.
|
||||||
def initialize(@example : Example)
|
def initialize(@example : Example)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces output for running the previously specified example.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "crystal spec "
|
io << "crystal spec "
|
||||||
io << @example.location
|
io << @example.location
|
||||||
|
|
|
@ -4,19 +4,24 @@ require "../../fail_result"
|
||||||
require "./result_block"
|
require "./result_block"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays information about a fail result.
|
||||||
struct FailResultBlock < ResultBlock
|
struct FailResultBlock < ResultBlock
|
||||||
|
# Creates the component.
|
||||||
def initialize(index : Int32, example : Example, @result : FailResult)
|
def initialize(index : Int32, example : Example, @result : FailResult)
|
||||||
super(index, example)
|
super(index, example)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Content displayed on the second line of the block after the label.
|
||||||
private def subtitle
|
private def subtitle
|
||||||
@result.error.message.try(&.each_line.first)
|
@result.error.message.try(&.each_line.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Prefix for the second line of the block.
|
||||||
private def subtitle_label
|
private def subtitle_label
|
||||||
"Failure: ".colorize(:red)
|
"Failure: ".colorize(:red)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Display expectation match data.
|
||||||
private def content(io)
|
private def content(io)
|
||||||
# TODO: Display match data.
|
# TODO: Display match data.
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
|
require "../../example"
|
||||||
require "./example_command"
|
require "./example_command"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Produces a list of commands to run failed examples.
|
||||||
struct FailureCommandList
|
struct FailureCommandList
|
||||||
|
# Creates the component.
|
||||||
|
# Requires a set of *failures* to display commands for.
|
||||||
def initialize(@failures : Enumerable(Example))
|
def initialize(@failures : Enumerable(Example))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the list of commands to run failed examples.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io.puts "Failed examples:"
|
io.puts "Failed examples:"
|
||||||
io.puts
|
io.puts
|
||||||
|
|
|
@ -1,22 +1,28 @@
|
||||||
|
require "colorize"
|
||||||
require "../../example"
|
require "../../example"
|
||||||
require "../../pending_result"
|
require "../../pending_result"
|
||||||
require "./result_block"
|
require "./result_block"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays information about a pending result.
|
||||||
struct PendingResultBlock < ResultBlock
|
struct PendingResultBlock < ResultBlock
|
||||||
|
# Creates the component.
|
||||||
def initialize(index : Int32, example : Example, @result : PendingResult)
|
def initialize(index : Int32, example : Example, @result : PendingResult)
|
||||||
super(index, example)
|
super(index, example)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Content displayed on the second line of the block after the label.
|
||||||
private def subtitle
|
private def subtitle
|
||||||
"No reason given" # TODO: Get reason from result.
|
"No reason given" # TODO: Get reason from result.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Prefix for the second line of the block.
|
||||||
private def subtitle_label
|
private def subtitle_label
|
||||||
# TODO: Could be pending or skipped.
|
# TODO: Could be pending or skipped.
|
||||||
"Pending: ".colorize(:yellow)
|
"Pending: ".colorize(:yellow)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# No content for this type of block.
|
||||||
private def content(io)
|
private def content(io)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,13 @@ require "../../profile"
|
||||||
require "./runtime"
|
require "./runtime"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays profiling information for slow examples.
|
||||||
struct Profile
|
struct Profile
|
||||||
|
# Creates the component with the specified *profile*.
|
||||||
def initialize(@profile : Spectator::Profile)
|
def initialize(@profile : Spectator::Profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the output containing the profiling information.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "Top "
|
io << "Top "
|
||||||
io << @profile.size
|
io << @profile.size
|
||||||
|
@ -20,6 +23,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Writes a single example's timing to the output.
|
||||||
private def example_profile(io, example)
|
private def example_profile(io, example)
|
||||||
io << " "
|
io << " "
|
||||||
io.puts example
|
io.puts example
|
||||||
|
|
|
@ -3,21 +3,47 @@ require "./block"
|
||||||
require "./comment"
|
require "./comment"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Base class that displayed indexed results in block form.
|
||||||
|
# These typically take the form:
|
||||||
|
# ```text
|
||||||
|
# 1) Title
|
||||||
|
# Label: Subtitle
|
||||||
|
#
|
||||||
|
# Content
|
||||||
|
# # Source
|
||||||
|
# ```
|
||||||
abstract struct ResultBlock < Block
|
abstract struct ResultBlock < Block
|
||||||
|
# Creates the block with the specified *index* and for the given *example*.
|
||||||
def initialize(@index : Int32, @example : Example)
|
def initialize(@index : Int32, @example : Example)
|
||||||
super()
|
super()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Content displayed on the first line of the block.
|
||||||
|
# Will be stringified.
|
||||||
|
# By default, uses the example name.
|
||||||
|
# Can be overridden to use a different value.
|
||||||
private def title
|
private def title
|
||||||
@example
|
@example
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Content displayed on the second line of the block after the label.
|
||||||
|
# Will be stringified.
|
||||||
private abstract def subtitle
|
private abstract def subtitle
|
||||||
|
|
||||||
|
# Prefix for the second line of the block.
|
||||||
|
# Will be stringified.
|
||||||
|
# This is typically something like "Error:" or "Failure:"
|
||||||
private abstract def subtitle_label
|
private abstract def subtitle_label
|
||||||
|
|
||||||
|
# Produces the main content of the block.
|
||||||
|
# *io* is the stream to write to.
|
||||||
|
# `#line` and `#indent` (from `Block`) should be used to maintain spacing.
|
||||||
|
private abstract def content(io)
|
||||||
|
|
||||||
|
# Writes the component's output to the specified stream.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
title_line(io)
|
title_line(io)
|
||||||
|
# Ident over to align with the spacing used by the index.
|
||||||
indent(index_digit_count + 2) do
|
indent(index_digit_count + 2) do
|
||||||
subtitle_line(io)
|
subtitle_line(io)
|
||||||
io.puts
|
io.puts
|
||||||
|
@ -26,6 +52,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the title line.
|
||||||
private def title_line(io)
|
private def title_line(io)
|
||||||
line(io) do
|
line(io) do
|
||||||
io << @index
|
io << @index
|
||||||
|
@ -35,6 +62,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the subtitle line.
|
||||||
private def subtitle_line(io)
|
private def subtitle_line(io)
|
||||||
line(io) do
|
line(io) do
|
||||||
io << subtitle_label
|
io << subtitle_label
|
||||||
|
@ -42,6 +70,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the (example) source line.
|
||||||
private def source_line(io)
|
private def source_line(io)
|
||||||
source = if (result = @example.result).responds_to?(:source)
|
source = if (result = @example.result).responds_to?(:source)
|
||||||
result.source
|
result.source
|
||||||
|
@ -51,6 +80,7 @@ module Spectator::Formatting::Components
|
||||||
line(io) { io << Comment.colorize(source) }
|
line(io) { io << Comment.colorize(source) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Computes the number of spaces the index takes
|
||||||
private def index_digit_count
|
private def index_digit_count
|
||||||
(Math.log(@index.to_f + 1) / Math::LOG10).ceil.to_i
|
(Math.log(@index.to_f + 1) / Math::LOG10).ceil.to_i
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
require "colorize"
|
require "colorize"
|
||||||
|
require "../../report"
|
||||||
require "./runtime"
|
require "./runtime"
|
||||||
require "./totals"
|
require "./totals"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
# Statistics information displayed at the end of a run.
|
# Statistics information displayed at the end of a run.
|
||||||
struct Stats
|
struct Stats
|
||||||
|
# Creates the component with stats from *report*.
|
||||||
def initialize(@report : Report)
|
def initialize(@report : Report)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Displays the stats.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
runtime(io)
|
runtime(io)
|
||||||
totals(io)
|
totals(io)
|
||||||
|
@ -16,15 +19,18 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Displays the time it took to run the suite.
|
||||||
private def runtime(io)
|
private def runtime(io)
|
||||||
io << "Finished in "
|
io << "Finished in "
|
||||||
io.puts Runtime.new(@report.runtime)
|
io.puts Runtime.new(@report.runtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Displays the counts for each type of result.
|
||||||
private def totals(io)
|
private def totals(io)
|
||||||
io.puts Totals.colorize(@report.counts)
|
io.puts Totals.colorize(@report.counts)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Displays the random seed.
|
||||||
private def random(io, seed)
|
private def random(io, seed)
|
||||||
io.puts "Randomized with seed: #{seed}".colorize(:cyan)
|
io.puts "Randomized with seed: #{seed}".colorize(:cyan)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,10 +2,14 @@ require "../../profile"
|
||||||
require "./runtime"
|
require "./runtime"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays profiling information for slow examples in a TAP format.
|
||||||
|
# Produces output similar to `Profile`, but formatted for TAP.
|
||||||
struct TAPProfile
|
struct TAPProfile
|
||||||
|
# Creates the component with the specified *profile*.
|
||||||
def initialize(@profile : Spectator::Profile)
|
def initialize(@profile : Spectator::Profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produces the output containing the profiling information.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "# Top "
|
io << "# Top "
|
||||||
io << @profile.size
|
io << @profile.size
|
||||||
|
@ -20,6 +24,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Writes a single example's timing to the output.
|
||||||
private def example_profile(io, example)
|
private def example_profile(io, example)
|
||||||
io << "# "
|
io << "# "
|
||||||
io.puts example
|
io.puts example
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
require "colorize"
|
require "colorize"
|
||||||
|
|
||||||
module Spectator::Formatting::Components
|
module Spectator::Formatting::Components
|
||||||
|
# Displays counts for each type of example result (pass, fail, error, pending).
|
||||||
struct Totals
|
struct Totals
|
||||||
|
# Creates the component with the specified counts.
|
||||||
def initialize(@examples : Int32, @failures : Int32, @errors : Int32, @pending : Int32)
|
def initialize(@examples : Int32, @failures : Int32, @errors : Int32, @pending : Int32)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates the component by pulling numbers from *counts*.
|
||||||
def initialize(counts)
|
def initialize(counts)
|
||||||
@examples = counts.run
|
@examples = counts.run
|
||||||
@failures = counts.fail
|
@failures = counts.fail
|
||||||
|
@ -12,6 +15,10 @@ module Spectator::Formatting::Components
|
||||||
@pending = counts.pending
|
@pending = counts.pending
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates the component, but colors it whether there were pending or failed results.
|
||||||
|
# The component will be red if there were failures (or errors),
|
||||||
|
# yellow if there were pending/skipped tests,
|
||||||
|
# and green if everything passed.
|
||||||
def self.colorize(counts)
|
def self.colorize(counts)
|
||||||
totals = new(counts)
|
totals = new(counts)
|
||||||
if counts.fail > 0
|
if counts.fail > 0
|
||||||
|
@ -23,6 +30,7 @@ module Spectator::Formatting::Components
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Writes the counts to the output.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << @examples
|
io << @examples
|
||||||
io << " examples, "
|
io << " examples, "
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue