diff --git a/src/spectator/dsl.cr b/src/spectator/dsl.cr index 5689a6f..0d13112 100644 --- a/src/spectator/dsl.cr +++ b/src/spectator/dsl.cr @@ -2,7 +2,6 @@ require "./dsl/*" module Spectator # Namespace containing methods representing the spec domain specific language. - # Also contains builders to generate classes and instances to later run the spec. module DSL end end diff --git a/src/spectator/dsl/example_dsl.cr b/src/spectator/dsl/example_dsl.cr index 95f4a1c..f315a63 100644 --- a/src/spectator/dsl/example_dsl.cr +++ b/src/spectator/dsl/example_dsl.cr @@ -2,14 +2,9 @@ require "../expectations/expectation_partial" require "../source" require "../test_block" require "../test_value" -require "./matcher_dsl" - -module Spectator::DSL - # Methods that are available inside test code. - # Basically, inside an `StructureDSL#it` block. - module ExampleDSL - include MatcherDSL +module Spectator + module DSL # Starts an expectation. # This should be followed up with `Spectator::Expectations::ExpectationPartial#to` # or `Spectator::Expectations::ExpectationPartial#to_not`. diff --git a/src/spectator/dsl/matcher_dsl.cr b/src/spectator/dsl/matcher_dsl.cr index bcfbec1..5c55a06 100644 --- a/src/spectator/dsl/matcher_dsl.cr +++ b/src/spectator/dsl/matcher_dsl.cr @@ -2,9 +2,8 @@ require "../matchers" require "../test_block" require "../test_value" -module Spectator::DSL - # Methods for defining matchers for expectations. - module MatcherDSL +module Spectator + module DSL # Indicates that some value should equal another. # The == operator is used for this check. # The value passed to this method is the expected value. diff --git a/src/spectator/dsl/structure_dsl.cr b/src/spectator/dsl/structure_dsl.cr index a2799e1..87f1fb3 100644 --- a/src/spectator/dsl/structure_dsl.cr +++ b/src/spectator/dsl/structure_dsl.cr @@ -1,156 +1,7 @@ require "../example_group" -module Spectator::DSL - # Domain specific language for the main structure of a spec. - # The primary components of this are `#describe`, `#context`, and `#it`. - # - # These macros define modules and classes. - # Those modules and classes are used to create the test cases. - # - # A class is created for every block of code that contains test code. - # An `#it` block creates a class derived from `RunnableExample`. - # A `#pending` block creates a class derived from `PendingExample`. - # The classes are built so that they run the example's code when invoked. - # However, the actual example code is placed into a separate "wrapper" class. - # This is done to avoid overlap with the Spectator namespace. - # The example code ends up having visibility only into itself and the DSL. - # - # Here's some skeleton code to demonstrate this: - # ``` - # it "does something" do - # # Test code goes here... - # end - # ``` - # - # becomes... - # - # ``` - # # Class describing the example - # # and provides a means of running the test. - # # Typically every class, module, and method - # # that the user might see or be able to reference is obscured. - # # Fresh variables from Crystal's macros are used to achive this. - # # It makes debugging Spectator more difficult, - # # but prevents name collision with user code. - # class Example123 < RunnableExample - # def initialize(group, sample_values) - # # group and sample_values are covered later. - # super - # @instance = Test123.new(sample_values) - # end - # - # # Returns the text provided by the user. - # # This isn't stored as a member - # # so that it can be referenced directly in compiled code. - # def what - # "does something" - # end - # - # # This method is called by `RunnableExample` - # # when the example code should be ran. - # def run_instance - # @instance._run123 - # end - # end - # - # # Wrapper class for the example code. - # # This isolates it from Spectator's internals. - # class Test123 - # include Context123 # More on this in a bit. - # include ExampleDSL # Include DSL for the example code. - # - # # Generated method name to avoid conflicts. - # def _run123 - # # Test code goes here... - # end - # end - # ``` - # - # Modules are used to provide context and share methods across examples. - # They are used as mix-ins for the example code. - # The example code wrapper class includes its parent module. - # This allows the example to access anything that was defined in the same context. - # Contexts can be nested, and this is achieved by including the parent module. - # Whenever a module or class is defined, - # it includes its parent so that functionality can be inherited. - # - # For example: - # ``` - # describe "#foo" do - # subject { described_class.foo(value) } - # - # context "when given :bar" do - # let(value) { :bar } - # - # it "does something" do - # # ... - # end - # end - # end - # ``` - # - # becomes... - # - # ``` - # # describe "#foo" - # module Context123 - # # Start a new group. - # # More on this in a bit. - # Builder.start_group("#foo") - # - # def subject - # described_class.foo(value) - # end - # - # # context "when given :bar" - # module Context456 - # include Context123 # Inherit parent module. - # - # # Start a nested group. - # Builder.start_group("when given :bar") - # - # def value - # :bar - # end - # - # # Wrapper class for the test case. - # class Test456 - # include Context456 # Include context. - # - # # Rest of test code... - # end - # - # # Example class for the test case. - # class Example456 < RunnableExample - # # Rest of example code... - # end - # - # # Add example to group. - # Builder.add_example(Example456) - # - # # End "when given :bar" group. - # Builder.end_group - # end - # - # # End "#foo" group. - # Builder.end_group - # end - # ``` - # - # In addition to providing modules as mix-ins, - # example groups are defined with `#describe` and `#context`. - # The DSL makes use of `Builder` to construct the run-time portion of the spec. - # As groups are defined, they are pushed on a stack - # and popped off after everything nested in them is defined. - # `Builder` tracks the current group (top of the stack). - # This way, examples, hooks, nested groups, and other items can be added to it. - # Groups and examples are nested in a parent group. - # 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 Spectator + module DSL # 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. diff --git a/src/spectator_test.cr b/src/spectator_test.cr index 439ceb9..8f14454 100644 --- a/src/spectator_test.cr +++ b/src/spectator_test.cr @@ -1,10 +1,8 @@ -require "./spectator/dsl/example_dsl" -require "./spectator/dsl/structure_dsl" +require "./spectator/dsl" # Root-level class that all tests inherit from and are contained in. # This class is intentionally outside of the scope of Spectator, # so that the namespace isn't leaked into tests unexpectedly. class SpectatorTest - include ::Spectator::DSL::StructureDSL # Include the DSL for creating groups, example, and more. - include ::Spectator::DSL::ExampleDSL # Mix in methods and macros specifically for example DSL. + include ::Spectator::DSL end