mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add docs for #describe and #context
This commit is contained in:
parent
0efaf9fa85
commit
bf03cf03ce
1 changed files with 105 additions and 0 deletions
|
@ -142,28 +142,133 @@ module Spectator::DSL
|
||||||
# This way, examples, hooks, nested groups, and other items can be added to it.
|
# This way, examples, hooks, nested groups, and other items can be added to it.
|
||||||
# Groups and examples are nested in a parent group.
|
# Groups and examples are nested in a parent group.
|
||||||
# The only group that isn't nested is the root group - `RootExampleGroup`.
|
# The only group that isn't nested is the root group - `RootExampleGroup`.
|
||||||
|
#
|
||||||
|
# Some example groups make use of sample values.
|
||||||
|
# Sample values are a collection of test values that can be used in examples.
|
||||||
|
# For more information, see `Internals::SampleValues`.
|
||||||
module StructureDSL
|
module StructureDSL
|
||||||
|
# Placeholder initializer.
|
||||||
|
# This is needed because examples and groups call `super` in their initializer.
|
||||||
|
# Those initializers pass the sample values upward through their hierarchy.
|
||||||
def initialize(sample_values : Internals::SampleValues)
|
def initialize(sample_values : Internals::SampleValues)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a new example group to describe a component.
|
||||||
|
# The `what` argument describes "what" is being tested.
|
||||||
|
# Additional example groups and DSL may be nested in the block.
|
||||||
|
#
|
||||||
|
# Typically when testing a method,
|
||||||
|
# the spec is written like so:
|
||||||
|
# ```
|
||||||
|
# describe "#foo" do
|
||||||
|
# it "does something" do
|
||||||
|
# # ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# When describing a class (or any other type),
|
||||||
|
# the `what` parameter doesn't need to be quoted.
|
||||||
|
# ```
|
||||||
|
# describe String do
|
||||||
|
# it "does something" do
|
||||||
|
# # ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# And when combining the two together:
|
||||||
|
# ```
|
||||||
|
# describe String do
|
||||||
|
# describe "#size" do
|
||||||
|
# it "returns the length" do
|
||||||
|
# # ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# The `#describe` and `#context` are identical in terms of functionality.
|
||||||
|
# However, `#describe` is typically used on classes and methods,
|
||||||
|
# while `#context` is used for use cases and scenarios.
|
||||||
macro describe(what, &block)
|
macro describe(what, &block)
|
||||||
context({{what}}) {{block}}
|
context({{what}}) {{block}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a new example group to describe a situation.
|
||||||
|
# The `what` argument describes the scenario or case being tested.
|
||||||
|
# Additional example groups and DSL may be nested in the block.
|
||||||
|
#
|
||||||
|
# The `#describe` and `#context` are identical in terms of functionality.
|
||||||
|
# However, `#describe` is typically used on classes and methods,
|
||||||
|
# while `#context` is used for use cases and scenarios.
|
||||||
|
#
|
||||||
|
# Using context blocks in conjunction with hooks, `#let`, and other methods
|
||||||
|
# provide an easy way to define the scenario in code.
|
||||||
|
# This also gives each example in the context an identical situation to run in.
|
||||||
|
#
|
||||||
|
# For instance:
|
||||||
|
# ```
|
||||||
|
# describe String do
|
||||||
|
# context "when empty" do
|
||||||
|
# subject { "" }
|
||||||
|
#
|
||||||
|
# it "has a size of zero" do
|
||||||
|
# expect(subject.size).to eq(0)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# it "is blank" do
|
||||||
|
# expect(subject.blank?).to be_true
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# context "when not empty" do
|
||||||
|
# subject { "foobar" }
|
||||||
|
#
|
||||||
|
# it "has a non-zero size" do
|
||||||
|
# expect(subject.size).to_not eq(0)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# it "is not blank" do
|
||||||
|
# expect(subject.blank?).to be_false
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# While this is a somewhat contrived example,
|
||||||
|
# it demonstrates how contexts can reuse code.
|
||||||
|
# Contexts also make it clearer how a scenario is setup.
|
||||||
macro context(what, &block)
|
macro context(what, &block)
|
||||||
|
# Module for the context.
|
||||||
|
# The module uses a generated unique name.
|
||||||
module Group%group
|
module Group%group
|
||||||
|
# Include the parent module.
|
||||||
|
# Since `@type` resolves immediately,
|
||||||
|
# this will reference the parent type.
|
||||||
include {{@type.id}}
|
include {{@type.id}}
|
||||||
|
|
||||||
|
# Check if `what` looks like a type.
|
||||||
|
# If it is, add the `#described_class` method.
|
||||||
|
# At the time of writing this code,
|
||||||
|
# this is the way (at least that I know of)
|
||||||
|
# to check if an AST node is a type name.
|
||||||
|
#
|
||||||
|
# NOTE: In Crystal 0.27, it looks like `#resolve` can be used.
|
||||||
|
# Need to investigate, but would also increase minimum version.
|
||||||
{% if what.is_a?(Path) || what.is_a?(Generic) %}
|
{% if what.is_a?(Path) || what.is_a?(Generic) %}
|
||||||
_spectator_described_class {{what}}
|
_spectator_described_class {{what}}
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
|
# Start a new group.
|
||||||
::Spectator::DSL::Builder.start_group(
|
::Spectator::DSL::Builder.start_group(
|
||||||
{{what.is_a?(StringLiteral) ? what : what.stringify}}
|
{{what.is_a?(StringLiteral) ? what : what.stringify}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Nest the block's content in the module.
|
||||||
{{block.body}}
|
{{block.body}}
|
||||||
|
|
||||||
|
# End the current group.
|
||||||
::Spectator::DSL::Builder.end_group
|
::Spectator::DSL::Builder.end_group
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue