mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Create ExampleGroup and use shared ExampleNode type
This commit is contained in:
parent
0f9c1ad09c
commit
fbf574b0b9
3 changed files with 104 additions and 64 deletions
|
@ -1,52 +1,9 @@
|
|||
require "./example_group"
|
||||
require "./example_node"
|
||||
require "./result"
|
||||
require "./source"
|
||||
|
||||
module Spectator
|
||||
# Common base type for all examples.
|
||||
abstract class ExampleBase
|
||||
# Location of the example in source code.
|
||||
getter! source : Source
|
||||
|
||||
# User-provided name or description of the test.
|
||||
# This does not include the group name or descriptions.
|
||||
# Use `#to_s` to get the full name.
|
||||
#
|
||||
# This value will be nil if no name was provided.
|
||||
# In this case, the name should be set
|
||||
# to the description of the first matcher that runs in the example.
|
||||
#
|
||||
# If this value is a `Symbol`, the user specified a type for the name.
|
||||
getter! name : String | Symbol
|
||||
|
||||
# Group the example belongs to.
|
||||
# Hooks are used from this group.
|
||||
getter! group : ExampleGroup
|
||||
|
||||
# Assigns the group the example belongs to.
|
||||
# If the example already belongs to a group,
|
||||
# it will be removed from the previous group before adding it to the new group.
|
||||
def group=(group : ExampleGroup?)
|
||||
if (previous = @group)
|
||||
previous.remove_example(self)
|
||||
end
|
||||
group.add_example(self) if group
|
||||
@group = group
|
||||
end
|
||||
|
||||
# Creates the base of the example.
|
||||
# The *name* describes the purpose of the example.
|
||||
# It can be a `Symbol` to describe a type.
|
||||
# The *source* tracks where the example exists in source code.
|
||||
# The example will be assigned to *group* if it is provided.
|
||||
def initialize(@name : String | Symbol? = nil, @source : Source? = nil, group : ExampleGroup? = nil)
|
||||
# Ensure group is linked.
|
||||
self.group = group
|
||||
end
|
||||
|
||||
# Indicates whether the example already ran.
|
||||
abstract def finished? : Bool
|
||||
|
||||
abstract class ExampleBase < ExampleNode
|
||||
# Retrieves the result of the last time the example ran.
|
||||
# This will be nil if the example hasn't run,
|
||||
# and should not be nil if it has.
|
||||
|
@ -58,25 +15,6 @@ module Spectator
|
|||
result? || raise(NilAssertionError("Example has no result"))
|
||||
end
|
||||
|
||||
# Constructs the full name or description of the example.
|
||||
# This prepends names of groups this example is part of.
|
||||
def to_s(io)
|
||||
name = @name
|
||||
|
||||
# Prefix with group's full name if the example belongs to a group.
|
||||
if (group = @group)
|
||||
group.to_s(io)
|
||||
|
||||
# Add padding between the group name and example name,
|
||||
# only if the names appear to be symbolic.
|
||||
if group.name.is_a?(Symbol) && name.is_a?(String)
|
||||
io << ' ' unless name.starts_with?('#') || name.starts_with?('.')
|
||||
end
|
||||
end
|
||||
|
||||
name.to_s(io)
|
||||
end
|
||||
|
||||
# Exposes information about the example useful for debugging.
|
||||
def inspect(io)
|
||||
raise NotImplementedError.new("#inspect")
|
||||
|
|
38
src/spectator/example_group.cr
Normal file
38
src/spectator/example_group.cr
Normal file
|
@ -0,0 +1,38 @@
|
|||
module Spectator
|
||||
# Collection of examples and sub-groups.
|
||||
class ExampleGroup < ExampleNode
|
||||
include Enumerable(ExampleNode)
|
||||
|
||||
@nodes = [] of ExampleNode
|
||||
|
||||
# Removes the specified *node* from the group.
|
||||
# The node will be unassigned from this group.
|
||||
def delete(node : ExampleNode)
|
||||
# Only remove from the group if it is associated with this group.
|
||||
return unless node.group == self
|
||||
|
||||
node.group = nil
|
||||
@nodes.delete(node)
|
||||
end
|
||||
|
||||
# Yields each node (example and sub-group).
|
||||
def each
|
||||
@nodes.each { |node| yield node }
|
||||
end
|
||||
|
||||
# Adds the specified *node* to the group.
|
||||
# Assigns the node to this group.
|
||||
# If the node already belongs to a group,
|
||||
# it will be removed from the previous group before adding it to this group.
|
||||
def <<(node : ExampleNode)
|
||||
# Remove from existing group if the node is part of one.
|
||||
if (previous = node.group?)
|
||||
previous.delete(node)
|
||||
end
|
||||
|
||||
# Add the node to this group and associate with it.
|
||||
@nodes << node
|
||||
node.group = self
|
||||
end
|
||||
end
|
||||
end
|
64
src/spectator/example_node.cr
Normal file
64
src/spectator/example_node.cr
Normal file
|
@ -0,0 +1,64 @@
|
|||
require "./source"
|
||||
|
||||
module Spectator
|
||||
# A single example or collection (group) of examples in an example tree.
|
||||
abstract class ExampleNode
|
||||
# Location of the node in source code.
|
||||
getter! source : Source
|
||||
|
||||
# User-provided name or description of the test.
|
||||
# This does not include the group name or descriptions.
|
||||
# Use `#to_s` to get the full name.
|
||||
#
|
||||
# This value will be nil if no name was provided.
|
||||
# In this case, and the node is a runnable example,
|
||||
# the name should be set to the description
|
||||
# of the first matcher that runs in the test case.
|
||||
#
|
||||
# If this value is a `Symbol`, the user specified a type for the name.
|
||||
getter! name : String | Symbol
|
||||
|
||||
# Updates the name of the node.
|
||||
protected def name=(@name : String)
|
||||
end
|
||||
|
||||
# Group the node belongs to.
|
||||
getter! group : ExampleGroup
|
||||
|
||||
# Assigns the node to the specified *group*.
|
||||
# This is an internal method and should only be called from `ExampleGroup`.
|
||||
# `ExampleGroup` manages the association of nodes to groups.
|
||||
protected setter group : ExampleGroup?
|
||||
|
||||
# Creates the node.
|
||||
# The *name* describes the purpose of the node.
|
||||
# It can be a `Symbol` to describe a type.
|
||||
# The *source* tracks where the node exists in source code.
|
||||
# The node will be assigned to *group* if it is provided.
|
||||
def initialize(@name : String | Symbol? = nil, @source : Source? = nil, group : ExampleGroup? = nil)
|
||||
# Ensure group is linked.
|
||||
group << self if group
|
||||
end
|
||||
|
||||
# Indicates whether the node has completed.
|
||||
abstract def finished? : Bool
|
||||
|
||||
# Constructs the full name or description of the node.
|
||||
# This prepends names of groups this node is part of.
|
||||
def to_s(io)
|
||||
name = @name
|
||||
|
||||
# Prefix with group's full name if the node belongs to a group.
|
||||
if (group = @group)
|
||||
io << group
|
||||
|
||||
# Add padding between the node names
|
||||
# only if the names don't appear to be symbolic.
|
||||
io << ' ' unless group.name.is_a?(Symbol) && name.is_a?(String) &&
|
||||
(name.starts_with?('#') || name.starts_with?('.'))
|
||||
end
|
||||
|
||||
io << name
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue