mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Allow metadata to be stored as nil
This commit is contained in:
parent
fbe877690d
commit
275b217c6c
13 changed files with 41 additions and 24 deletions
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Changed
|
### Changed
|
||||||
- Simplify string representation of mock-related types.
|
- Simplify string representation of mock-related types.
|
||||||
- Remove unnecessary redefinitions of methods when adding stub functionality to a type.
|
- Remove unnecessary redefinitions of methods when adding stub functionality to a type.
|
||||||
|
- Allow metadata to be stored as nil to reduce overhead when tracking nodes without tags.
|
||||||
|
|
||||||
## [0.11.4]
|
## [0.11.4]
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -6,6 +6,9 @@ module Spectator::DSL
|
||||||
private macro _spectator_metadata(name, source, *tags, **metadata)
|
private macro _spectator_metadata(name, source, *tags, **metadata)
|
||||||
private def self.{{name.id}}
|
private def self.{{name.id}}
|
||||||
%metadata = {{source.id}}.dup
|
%metadata = {{source.id}}.dup
|
||||||
|
{% unless tags.empty? && metadata.empty? %}
|
||||||
|
%metadata ||= ::Spectator::Metadata.new
|
||||||
|
{% end %}
|
||||||
{% for k in tags %}
|
{% for k in tags %}
|
||||||
%metadata[{{k.id.symbolize}}] = nil
|
%metadata[{{k.id.symbolize}}] = nil
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
|
@ -40,7 +40,7 @@ module Spectator
|
||||||
# Note: The metadata will not be merged with the parent metadata.
|
# Note: The metadata will not be merged with the parent metadata.
|
||||||
def initialize(@context : Context, @entrypoint : self ->,
|
def initialize(@context : Context, @entrypoint : self ->,
|
||||||
name : String? = nil, location : Location? = nil,
|
name : String? = nil, location : Location? = nil,
|
||||||
@group : ExampleGroup? = nil, metadata = Metadata.new)
|
@group : ExampleGroup? = nil, metadata = nil)
|
||||||
super(name, location, metadata)
|
super(name, location, metadata)
|
||||||
|
|
||||||
# Ensure group is linked.
|
# Ensure group is linked.
|
||||||
|
@ -58,7 +58,7 @@ module Spectator
|
||||||
# Note: The metadata will not be merged with the parent metadata.
|
# Note: The metadata will not be merged with the parent metadata.
|
||||||
def initialize(@context : Context, @entrypoint : self ->,
|
def initialize(@context : Context, @entrypoint : self ->,
|
||||||
@name_proc : Example -> String, location : Location? = nil,
|
@name_proc : Example -> String, location : Location? = nil,
|
||||||
@group : ExampleGroup? = nil, metadata = Metadata.new)
|
@group : ExampleGroup? = nil, metadata = nil)
|
||||||
super(nil, location, metadata)
|
super(nil, location, metadata)
|
||||||
|
|
||||||
# Ensure group is linked.
|
# Ensure group is linked.
|
||||||
|
@ -75,7 +75,7 @@ module Spectator
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
# Note: The metadata will not be merged with the parent metadata.
|
# Note: The metadata will not be merged with the parent metadata.
|
||||||
def initialize(name : String? = nil, location : Location? = nil,
|
def initialize(name : String? = nil, location : Location? = nil,
|
||||||
@group : ExampleGroup? = nil, metadata = Metadata.new, &block : self ->)
|
@group : ExampleGroup? = nil, metadata = nil, &block : self ->)
|
||||||
super(name, location, metadata)
|
super(name, location, metadata)
|
||||||
|
|
||||||
@context = NullContext.new
|
@context = NullContext.new
|
||||||
|
@ -93,9 +93,10 @@ module Spectator
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
# Note: The metadata will not be merged with the parent metadata.
|
# Note: The metadata will not be merged with the parent metadata.
|
||||||
def self.pending(name : String? = nil, location : Location? = nil,
|
def self.pending(name : String? = nil, location : Location? = nil,
|
||||||
group : ExampleGroup? = nil, metadata = Metadata.new, reason = nil)
|
group : ExampleGroup? = nil, metadata = nil, reason = nil)
|
||||||
# Add pending tag and reason if they don't exist.
|
# Add pending tag and reason if they don't exist.
|
||||||
metadata = metadata.merge({:pending => nil, :reason => reason}) { |_, v, _| v }
|
tags = {:pending => nil, :reason => reason}
|
||||||
|
metadata = metadata ? metadata.merge(tags) { |_, v, _| v } : tags
|
||||||
new(name, location, group, metadata) { nil }
|
new(name, location, group, metadata) { nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Spectator
|
||||||
# The *entrypoint* indicates the proc used to invoke the test code in the example.
|
# The *entrypoint* indicates the proc used to invoke the test code in the example.
|
||||||
# The *name*, *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
# The *name*, *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
||||||
def initialize(@context_builder : -> Context, @entrypoint : Example ->,
|
def initialize(@context_builder : -> Context, @entrypoint : Example ->,
|
||||||
@name : String? = nil, @location : Location? = nil, @metadata : Metadata = Metadata.new)
|
@name : String? = nil, @location : Location? = nil, @metadata : Metadata? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates the builder.
|
# Creates the builder.
|
||||||
|
@ -24,7 +24,7 @@ module Spectator
|
||||||
# The *name* is an interpolated string that runs in the context of the example.
|
# The *name* is an interpolated string that runs in the context of the example.
|
||||||
# *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
# *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
||||||
def initialize(@context_builder : -> Context, @entrypoint : Example ->,
|
def initialize(@context_builder : -> Context, @entrypoint : Example ->,
|
||||||
@name : Example -> String, @location : Location? = nil, @metadata : Metadata = Metadata.new)
|
@name : Example -> String, @location : Location? = nil, @metadata : Metadata? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Constructs an example with previously defined attributes and context.
|
# Constructs an example with previously defined attributes and context.
|
||||||
|
|
|
@ -79,7 +79,7 @@ module Spectator
|
||||||
# This group will be assigned to the parent *group* if it is provided.
|
# This group will be assigned to the parent *group* if it is provided.
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
def initialize(@name : Label = nil, @location : Location? = nil,
|
def initialize(@name : Label = nil, @location : Location? = nil,
|
||||||
@group : ExampleGroup? = nil, @metadata : Metadata = Metadata.new)
|
@group : ExampleGroup? = nil, @metadata : Metadata? = nil)
|
||||||
# Ensure group is linked.
|
# Ensure group is linked.
|
||||||
group << self if group
|
group << self if group
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,7 +28,7 @@ module Spectator
|
||||||
# Creates the builder.
|
# Creates the builder.
|
||||||
# Initially, the builder will have no children and no hooks.
|
# Initially, the builder will have no children and no hooks.
|
||||||
# The *name*, *location*, and *metadata* will be applied to the `ExampleGroup` produced by `#build`.
|
# The *name*, *location*, and *metadata* will be applied to the `ExampleGroup` produced by `#build`.
|
||||||
def initialize(@name : Label = nil, @location : Location? = nil, @metadata : Metadata = Metadata.new)
|
def initialize(@name : Label = nil, @location : Location? = nil, @metadata : Metadata? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Constructs an example group with previously defined attributes, children, and hooks.
|
# Constructs an example group with previously defined attributes, children, and hooks.
|
||||||
|
|
|
@ -18,7 +18,7 @@ module Spectator
|
||||||
# This group will be assigned to the parent *group* if it is provided.
|
# This group will be assigned to the parent *group* if it is provided.
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
def initialize(@item : T, name : Label = nil, location : Location? = nil,
|
def initialize(@item : T, name : Label = nil, location : Location? = nil,
|
||||||
group : ExampleGroup? = nil, metadata : Metadata = Metadata.new)
|
group : ExampleGroup? = nil, metadata : Metadata? = nil)
|
||||||
super(name, location, group, metadata)
|
super(name, location, group, metadata)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Spectator
|
||||||
# The *collection* is the set of items to create sub-nodes for.
|
# The *collection* is the set of items to create sub-nodes for.
|
||||||
# The *iterators* is a list of optional names given to items in the collection.
|
# The *iterators* is a list of optional names given to items in the collection.
|
||||||
def initialize(@collection : Enumerable(T), name : String? = nil, @iterators : Array(String) = [] of String,
|
def initialize(@collection : Enumerable(T), name : String? = nil, @iterators : Array(String) = [] of String,
|
||||||
location : Location? = nil, metadata : Metadata = Metadata.new)
|
location : Location? = nil, metadata : Metadata? = nil)
|
||||||
super(name, location, metadata)
|
super(name, location, metadata)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,16 @@ module Spectator
|
||||||
end
|
end
|
||||||
|
|
||||||
# User-defined tags and values used for filtering and behavior modification.
|
# User-defined tags and values used for filtering and behavior modification.
|
||||||
getter metadata : Metadata
|
def metadata : Metadata
|
||||||
|
@metadata ||= Metadata.new
|
||||||
|
end
|
||||||
|
|
||||||
# Creates the node.
|
# Creates the node.
|
||||||
# The *name* describes the purpose of the node.
|
# The *name* describes the purpose of the node.
|
||||||
# It can be a `Symbol` to describe a type.
|
# It can be a `Symbol` to describe a type.
|
||||||
# The *location* tracks where the node exists in source code.
|
# The *location* tracks where the node exists in source code.
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
def initialize(@name : Label = nil, @location : Location? = nil, @metadata : Metadata = Metadata.new)
|
def initialize(@name : Label = nil, @location : Location? = nil, @metadata : Metadata? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Indicates whether the node has completed.
|
# Indicates whether the node has completed.
|
||||||
|
@ -46,17 +48,25 @@ module Spectator
|
||||||
# Checks if the node has been marked as pending.
|
# Checks if the node has been marked as pending.
|
||||||
# Pending items should be skipped during execution.
|
# Pending items should be skipped during execution.
|
||||||
def pending?
|
def pending?
|
||||||
metadata.has_key?(:pending) || metadata.has_key?(:skip)
|
return false unless md = @metadata
|
||||||
|
|
||||||
|
md.has_key?(:pending) || md.has_key?(:skip)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Gets the reason the node has been marked as pending.
|
# Gets the reason the node has been marked as pending.
|
||||||
def pending_reason
|
def pending_reason
|
||||||
metadata[:pending]? || metadata[:skip]? || metadata[:reason]? || DEFAULT_PENDING_REASON
|
return DEFAULT_PENDING_REASON unless md = @metadata
|
||||||
|
|
||||||
|
md[:pending]? || md[:skip]? || md[:reason]? || DEFAULT_PENDING_REASON
|
||||||
end
|
end
|
||||||
|
|
||||||
# Retrieves just the tag names applied to the node.
|
# Retrieves just the tag names applied to the node.
|
||||||
def tags
|
def tags
|
||||||
Tags.new(metadata.keys)
|
if md = @metadata
|
||||||
|
Tags.new(md.keys)
|
||||||
|
else
|
||||||
|
Tags.new
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Non-nil name used to show the node name.
|
# Non-nil name used to show the node name.
|
||||||
|
|
|
@ -11,7 +11,7 @@ module Spectator
|
||||||
# The *name*, *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
# The *name*, *location*, and *metadata* will be applied to the `Example` produced by `#build`.
|
||||||
# A default *reason* can be given in case the user didn't provide one.
|
# A default *reason* can be given in case the user didn't provide one.
|
||||||
def initialize(@name : String? = nil, @location : Location? = nil,
|
def initialize(@name : String? = nil, @location : Location? = nil,
|
||||||
@metadata : Metadata = Metadata.new, @reason : String? = nil)
|
@metadata : Metadata? = nil, @reason : String? = nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Constructs an example with previously defined attributes.
|
# Constructs an example with previously defined attributes.
|
||||||
|
|
|
@ -60,7 +60,7 @@ module Spectator
|
||||||
#
|
#
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
# For instance, adding a "pending" tag will mark tests as pending and skip execution.
|
# For instance, adding a "pending" tag will mark tests as pending and skip execution.
|
||||||
def start_group(name, location = nil, metadata = Metadata.new) : Nil
|
def start_group(name, location = nil, metadata = nil) : Nil
|
||||||
Log.trace { "Start group: #{name.inspect} @ #{location}; metadata: #{metadata}" }
|
Log.trace { "Start group: #{name.inspect} @ #{location}; metadata: #{metadata}" }
|
||||||
builder = ExampleGroupBuilder.new(name, location, metadata)
|
builder = ExampleGroupBuilder.new(name, location, metadata)
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ module Spectator
|
||||||
#
|
#
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
# For instance, adding a "pending" tag will mark tests as pending and skip execution.
|
# For instance, adding a "pending" tag will mark tests as pending and skip execution.
|
||||||
def start_iterative_group(collection, name, iterator = nil, location = nil, metadata = Metadata.new) : Nil
|
def start_iterative_group(collection, name, iterator = nil, location = nil, metadata = nil) : Nil
|
||||||
Log.trace { "Start iterative group: #{name} (#{typeof(collection)}) @ #{location}; metadata: #{metadata}" }
|
Log.trace { "Start iterative group: #{name} (#{typeof(collection)}) @ #{location}; metadata: #{metadata}" }
|
||||||
builder = IterativeExampleGroupBuilder.new(collection, name, iterator, location, metadata)
|
builder = IterativeExampleGroupBuilder.new(collection, name, iterator, location, metadata)
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ module Spectator
|
||||||
# It will be yielded two arguments - the example created by this method, and the *context* argument.
|
# It will be yielded two arguments - the example created by this method, and the *context* argument.
|
||||||
# The return value of the block is ignored.
|
# The return value of the block is ignored.
|
||||||
# It is expected that the test code runs when the block is called.
|
# It is expected that the test code runs when the block is called.
|
||||||
def add_example(name, location, context_builder, metadata = Metadata.new, &block : Example -> _) : Nil
|
def add_example(name, location, context_builder, metadata = nil, &block : Example -> _) : Nil
|
||||||
Log.trace { "Add example: #{name} @ #{location}; metadata: #{metadata}" }
|
Log.trace { "Add example: #{name} @ #{location}; metadata: #{metadata}" }
|
||||||
current << ExampleBuilder.new(context_builder, block, name, location, metadata)
|
current << ExampleBuilder.new(context_builder, block, name, location, metadata)
|
||||||
end
|
end
|
||||||
|
@ -144,7 +144,7 @@ module Spectator
|
||||||
# A set of *metadata* can be used for filtering and modifying example behavior.
|
# A set of *metadata* can be used for filtering and modifying example behavior.
|
||||||
# For instance, adding a "pending" tag will mark the test as pending and skip execution.
|
# For instance, adding a "pending" tag will mark the test as pending and skip execution.
|
||||||
# A default *reason* can be given in case the user didn't provide one.
|
# A default *reason* can be given in case the user didn't provide one.
|
||||||
def add_pending_example(name, location, metadata = Metadata.new, reason = nil) : Nil
|
def add_pending_example(name, location, metadata = nil, reason = nil) : Nil
|
||||||
Log.trace { "Add pending example: #{name} @ #{location}; metadata: #{metadata}" }
|
Log.trace { "Add pending example: #{name} @ #{location}; metadata: #{metadata}" }
|
||||||
current << PendingExampleBuilder.new(name, location, metadata, reason)
|
current << PendingExampleBuilder.new(name, location, metadata, reason)
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,9 @@ module Spectator
|
||||||
|
|
||||||
# Checks whether the node satisfies the filter.
|
# Checks whether the node satisfies the filter.
|
||||||
def includes?(node) : Bool
|
def includes?(node) : Bool
|
||||||
node.metadata.any? { |key, value| key.to_s == @tag && (!@value || value == @value) }
|
return false unless metadata = node.metadata
|
||||||
|
|
||||||
|
metadata.any? { |key, value| key.to_s == @tag && (!@value || value == @value) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ class SpectatorTestContext < SpectatorContext
|
||||||
|
|
||||||
# Initial metadata for tests.
|
# Initial metadata for tests.
|
||||||
# This method should be overridden by example groups and examples.
|
# This method should be overridden by example groups and examples.
|
||||||
private def self.metadata
|
private def self.metadata : ::Spectator::Metadata?
|
||||||
::Spectator::Metadata.new
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue