diff --git a/lib/sus/base.rb b/lib/sus/base.rb index d752c85..fd0093f 100644 --- a/lib/sus/base.rb +++ b/lib/sus/base.rb @@ -16,10 +16,16 @@ def inspect "\#" end + # A hook which is called before the test is executed. + # + # If you override this method, you must call super. def before end - def after + # A hook which is called after the test is executed. + # + # If you override this method, you must call super. + def after(error = nil) end # Wrap logic around the test being executed. @@ -31,8 +37,10 @@ def around(&block) self.before return block.call + rescue => error + raise ensure - self.after + self.after(error) end def assert(...) diff --git a/lib/sus/context.rb b/lib/sus/context.rb index f79c177..fd081d2 100644 --- a/lib/sus/context.rb +++ b/lib/sus/context.rb @@ -78,17 +78,16 @@ def each(&block) # Include an around method to the context class, that invokes the given block before running the test. # - # Before hooks are called in the reverse order they are defined, in other words the last defined before hook is called first. + # Before hooks are usually invoked in the order they are defined, i.e. the first defined hook is invoked first. # # @parameter hook [Proc] The block to execute before each test. def before(&hook) wrapper = Module.new - wrapper.define_method(:around) do |&block| - super() do - instance_exec(&hook) - block.call - end + wrapper.define_method(:before) do + super() + + instance_exec(&hook) end self.include(wrapper) @@ -96,20 +95,18 @@ def before(&hook) # Include an around method to the context class, that invokes the given block after running the test. # - # After hooks are called in the order they are defined, in other words the last defined after hook is called last. + # After hooks are usually invoked in the reverse order they are defined, i.e. the last defined hook is invoked first. # # @parameter hook [Proc] The block to execute after each test. An `error` argument is passed if the test failed with an exception. def after(&hook) wrapper = Module.new - wrapper.define_method(:around) do |&block| - super() do - block.call - rescue => error - raise - ensure - instance_exec(error, &hook) - end + wrapper.define_method(:after) do |error| + instance_exec(error, &hook) + rescue => error + raise + ensure + super(error) end self.include(wrapper) diff --git a/lib/sus/mock.rb b/lib/sus/mock.rb index d6dba3f..7076744 100644 --- a/lib/sus/mock.rb +++ b/lib/sus/mock.rb @@ -82,7 +82,7 @@ def wrap(method, &hook) end module Mocks - def after + def after(error = nil) super @mocks&.each_value(&:clear) diff --git a/test/sus/context.rb b/test/sus/context.rb index 20269ee..278e404 100644 --- a/test/sus/context.rb +++ b/test/sus/context.rb @@ -27,6 +27,39 @@ it "has a full name" do expect(instance.full_name).to be == "describe test" end + + with "before hooks" do + let(:events) {Array.new} + + before do + events << :before1 + end + + before do + events << :before2 + end + + it "invokes before hooks" do + expect(events).to be == [:before1, :before2] + end + end + + with "after hooks" do + let(:events) {Array.new} + + after do + events << :after1 + expect(events).to be == [:example, :after2, :after1] + end + + after do + events << :after2 + end + + it "invokes after hooks" do + events << :example + end + end end describe Sus::With do diff --git a/test/sus/have.rb b/test/sus/have.rb index 7573f7b..8eb9d1a 100644 --- a/test/sus/have.rb +++ b/test/sus/have.rb @@ -43,7 +43,7 @@ def before @socket = Socket.new(:INET, :STREAM) end - def after + def after(error = nil) @socket.close super diff --git a/test/sus/include_context.rb b/test/sus/include_context.rb index 4887477..aa8e553 100644 --- a/test/sus/include_context.rb +++ b/test/sus/include_context.rb @@ -9,19 +9,23 @@ AContextWithHooks = Sus::Shared("a context with hooks") do before do - events << :shared_before + events << :context_before end after do - events << :shared_after + events << :context_after end around do |&block| + events << :context_around_before + super() do - events << :shared_around_before - + events << :context_around_super_before block.call + events << :context_around_super_after end + + events << :context_around_after end end @@ -35,7 +39,7 @@ end end - with "a shared context with arguments" do + with "a shared context with hooks" do let(:events) {Array.new} include AContextWithHooks @@ -44,8 +48,51 @@ events << :example_before end + after do + events << :example_after + end + + around do |&block| + events << :example_around_before + + super() do + events << :example_around_super_before + block.call + events << :example_around_super_after + end + + events << :example_around_after + + # This is the full sequence of events: + expect(events).to be == [ + :example_around_before, + :context_around_before, + :context_before, + :example_before, + :context_around_super_before, + :example_around_super_before, + :example, + :example_around_super_after, + :context_around_super_after, + :example_after, + :context_after, + :context_around_after, + :example_around_after, + ] + end + it "can include a shared context" do - expect(events).to be == [:example_before, :shared_around_before, :shared_before] + events << :example + + expect(events).to be == [ + :example_around_before, + :context_around_before, + :context_before, + :example_before, + :context_around_super_before, + :example_around_super_before, + :example, + ] end end end diff --git a/test/sus/it.rb b/test/sus/it.rb index ee0a165..ec78583 100644 --- a/test/sus/it.rb +++ b/test/sus/it.rb @@ -14,7 +14,7 @@ def before self.before_hook_invoked = true end - def after + def after(error = nil) self.after_hook_invoked = true end