diff --git a/spec/std/socket/udp_socket_spec.cr b/spec/std/socket/udp_socket_spec.cr index 087acca25aa5..b99e4d286b81 100644 --- a/spec/std/socket/udp_socket_spec.cr +++ b/spec/std/socket/udp_socket_spec.cr @@ -78,14 +78,32 @@ describe UDPSocket do expect_raises(Socket::Error, "Unsupported IP address family: INET. For use with IPv6 only") do udp.multicast_interface 0 end - udp.multicast_interface Socket::IPAddress.new(unspecified_address, 0) + + begin + udp.multicast_interface Socket::IPAddress.new(unspecified_address, 0) + rescue e : Socket::Error + if e.os_error == Errno::ENOPROTOOPT + pending!("Multicast device selection not available on this host") + else + raise e + end + end Socket::IPAddress.new("224.0.0.254", port) when Socket::Family::INET6 expect_raises(Socket::Error, "Unsupported IP address family: INET6. For use with IPv4 only") do udp.multicast_interface(Socket::IPAddress.new(unspecified_address, 0)) end - udp.multicast_interface(0) + + begin + udp.multicast_interface(0) + rescue e : Socket::Error + if e.os_error == Errno::ENOPROTOOPT + pending!("Multicast device selection not available on this host") + else + raise e + end + end Socket::IPAddress.new("ff02::102", port) else diff --git a/src/spec/dsl.cr b/src/spec/dsl.cr index c6524e4edf93..bc199149a01c 100644 --- a/src/spec/dsl.cr +++ b/src/spec/dsl.cr @@ -53,6 +53,10 @@ module Spec class AssertionFailed < SpecError end + # :nodoc: + class ExamplePending < SpecError + end + # :nodoc: class NestingSpecError < SpecError end diff --git a/src/spec/example.cr b/src/spec/example.cr index efd639604679..01f46a6fae62 100644 --- a/src/spec/example.cr +++ b/src/spec/example.cr @@ -47,6 +47,8 @@ module Spec rescue ex : Spec::AssertionFailed @parent.report(:fail, description, file, line, Time.monotonic - start, ex) Spec.abort! if Spec.fail_fast? + rescue ex : Spec::ExamplePending + @parent.report(:pending, description, file, line, Time.monotonic - start) rescue ex @parent.report(:error, description, file, line, Time.monotonic - start, ex) Spec.abort! if Spec.fail_fast? diff --git a/src/spec/methods.cr b/src/spec/methods.cr index 019c90f34c41..ebde51f7023a 100644 --- a/src/spec/methods.cr +++ b/src/spec/methods.cr @@ -6,6 +6,8 @@ module Spec::Methods # # Example: # ``` + # require "spec" + # # describe "Int32" do # describe "+" do # it "adds" { (1 + 1).should eq 2 } @@ -35,6 +37,8 @@ module Spec::Methods # # Example: # ``` + # require "spec" + # # it "adds" { (1 + 1).should eq 2 } # ``` # @@ -52,6 +56,8 @@ module Spec::Methods # # Example: # ``` + # require "spec" + # # pending "check cat" { cat.alive? } # ``` # @@ -76,6 +82,24 @@ module Spec::Methods raise Spec::AssertionFailed.new(msg, file, line) end + # Marks the current example pending + # + # In case an example needs to be pending on some condition that requires executing it, + # this allows to mark it as such rather than letting it fail or never run. + # + # ``` + # require "spec" + # + # it "test git" do + # cmd = Process.find_executable("git") + # pending!("git is not available") unless cmd + # cmd.ends_with?("git").should be_true + # end + # ``` + def pending!(msg = "Cannot run example", file = __FILE__, line = __LINE__) + raise Spec::ExamplePending.new(msg, file, line) + end + # Executes the given block before each spec in the current context runs. # # A context is defined by `describe` or `context` blocks, or outside of them @@ -87,16 +111,16 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # before_each do # puts "runs before sample_b" # end # - # it "sample_b" {} + # it "sample_b" { } # end # ``` def before_each(&block) @@ -117,16 +141,16 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # after_each do # puts "runs after sample_b" # end # - # it "sample_b" {} + # it "sample_b" { } # end # ``` def after_each(&block) @@ -147,16 +171,16 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # before_all do # puts "runs at start of nested_context" # end # - # it "sample_b" {} + # it "sample_b" { } # end # ``` def before_all(&block) @@ -177,16 +201,16 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # after_all do # puts "runs at end of nested_context" # end # - # it "sample_b" {} + # it "sample_b" { } # end # ``` def after_all(&block) @@ -213,9 +237,9 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # around_each do |example| @@ -224,7 +248,7 @@ module Spec::Methods # puts "runs after sample_b" # end # - # it "sample_b" {} + # it "sample_b" { } # end # ``` def around_each(&block : Example::Procsy ->) @@ -250,7 +274,7 @@ module Spec::Methods # order of definition. # # ``` - # require "spec + # require "spec" # # describe "main_context" do # around_each do |example| @@ -259,7 +283,7 @@ module Spec::Methods # puts "runs at end of main_context" # end # - # it "sample_a" {} + # it "sample_a" { } # # describe "nested_context" do # around_each do |example| @@ -268,7 +292,7 @@ module Spec::Methods # puts "runs at end of nested_context" # end # - # it "sample_b" {} + # it "sample_b" { } # end # end # ```