From 13a0b9e2d36cc4be5605dbc3184e49eca86f59da Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Thu, 16 Jan 2020 18:36:40 -0700 Subject: [PATCH 1/7] Fix issue with implicit vs. explicit subject Addresses the issue pointed out in !25 There was a recent change that set a subject to the first argument of `describe` and `context`. This prevented an explicitly defined subject from being accessible in nested groups. --- src/spectator/dsl/groups.cr | 4 ++-- src/spectator_test.cr | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/spectator/dsl/groups.cr b/src/spectator/dsl/groups.cr index bce9215..227c224 100644 --- a/src/spectator/dsl/groups.cr +++ b/src/spectator/dsl/groups.cr @@ -24,11 +24,11 @@ module Spectator {{what}} end - def subject(*args) + def _spectator_implicit_subject(*args) described_class.new(*args) end {% else %} - def subject + def _spectator_implicit_subject(*args) {{what}} end {% end %} diff --git a/src/spectator_test.cr b/src/spectator_test.cr index 364d79e..ca0e2e0 100644 --- a/src/spectator_test.cr +++ b/src/spectator_test.cr @@ -6,6 +6,14 @@ require "./spectator/dsl" class SpectatorTest include ::Spectator::DSL + def _spectator_implicit_subject + nil + end + + def subject + _spectator_implicit_subject + end + def initialize(@spectator_test_values : ::Spectator::TestValues) end end From 2b2fb5af3afec922f64305e0bfe13bd10e226469 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Thu, 16 Jan 2020 18:37:04 -0700 Subject: [PATCH 2/7] Bump version to 0.9.3 --- shard.yml | 2 +- src/spectator.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shard.yml b/shard.yml index 661dd1b..63b83e8 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: spectator -version: 0.9.2 +version: 0.9.3 description: | A feature-rich spec testing framework for Crystal with similarities to RSpec. diff --git a/src/spectator.cr b/src/spectator.cr index 273ef10..9dad54d 100644 --- a/src/spectator.cr +++ b/src/spectator.cr @@ -6,7 +6,7 @@ module Spectator extend self # Current version of the Spectator library. - VERSION = "0.9.2" + VERSION = "0.9.3" # Top-level describe method. # All specs in a file must be wrapped in this call. From ed48b80d58085befb0491f960b72528322eb0c16 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Fri, 17 Jan 2020 21:58:29 -0700 Subject: [PATCH 3/7] Add RSpec `raise_error` matcher spec --- .../expectations/raise_error_matcher_spec.cr | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 spec/rspec/expectations/raise_error_matcher_spec.cr diff --git a/spec/rspec/expectations/raise_error_matcher_spec.cr b/spec/rspec/expectations/raise_error_matcher_spec.cr new file mode 100644 index 0000000..85678a7 --- /dev/null +++ b/spec/rspec/expectations/raise_error_matcher_spec.cr @@ -0,0 +1,94 @@ +require "../../spec_helper" + +# Examples taken from: +# https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/raise-error-matcher +# and modified to fit Spectator and Crystal. +Spectator.describe "`raise_error` matcher" do + context "expect any error" do + # This example originally calls a non-existent method. + # That isn't allowed in Crystal. + # The example has been changed to just raise a runtime error. + describe "dividing by zero" do + it "raises" do + expect { 42 // 0 }.to raise_error + end + end + end + + context "expect specific error" do + # Again, can't even compile if a method doesn't exist. + # So using a different exception here. + describe "dividing by zero" do + it "raises" do + expect { 42 // 0 }.to raise_error(DivisionByZeroError) + end + end + end + + # The following examples are changed slightly. + # `raise Type.new(message)` is the syntax in Crystal, + # whereas it is `raise Type, message` in Ruby. + # Additionally, `StandardError` doesn't exist in Crystal, + # so `Exception` is used instead. + context "match message with a string" do + describe "matching error message with string" do + it "matches the error message" do + expect { raise Exception.new("this message exactly") } + .to raise_error("this message exactly") + end + end + end + + context "match message with a regexp" do + describe "matching error message with regex" do + it "matches the error message" do + expect { raise Exception.new("my message") } + .to raise_error(/my mess/) + end + end + end + + context "matching message with `with_message`" do + describe "matching error message with regex" do + it "matches the error message" do + expect { raise Exception.new("my message") } + .to raise_error.with_message(/my mess/) + end + end + end + + context "match class + message with string" do + describe "matching error message with string" do + it "matches the error message" do + expect { raise Exception.new("this message exactly") } + .to raise_error(Exception, "this message exactly") + end + end + end + + context "match class + message with regexp" do + describe "matching error message with regex" do + it "matches the error message" do + expect { raise Exception.new("my message") } + .to raise_error(Exception, /my mess/) + end + end + end + + # TODO: Support passing a block to `raise_error` matcher. + # context "set expectations on error object passed to block" do + # it "raises DivisionByZeroError" do + # expect { 42 // 0 }.to raise_error do |error| + # expect(error).to be_a(DivisionByZeroError) + # end + # end + # end + + context "expect no error at all" do + describe "#to_s" do + it "does not raise" do + expect { 42.to_s }.not_to raise_error + end + end + end +end From a2508d5f6bda4574569f1048f21494a2b402cfff Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Fri, 17 Jan 2020 22:08:52 -0700 Subject: [PATCH 4/7] Fix negation case for respond_to matcher --- src/spectator/matchers/respond_matcher.cr | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/spectator/matchers/respond_matcher.cr b/src/spectator/matchers/respond_matcher.cr index 3f26041..59a955f 100644 --- a/src/spectator/matchers/respond_matcher.cr +++ b/src/spectator/matchers/respond_matcher.cr @@ -16,7 +16,7 @@ module Spectator::Matchers # Actually performs the test against the expression. def match(actual : TestExpression(T)) : MatchData forall T snapshot = snapshot_values(actual.value) - if match?(snapshot) + if snapshot.values.all? SuccessfulMatchData.new(description) else FailedMatchData.new(description, "#{actual.label} does not respond to #{label}", **values(snapshot)) @@ -27,7 +27,7 @@ module Spectator::Matchers # A successful match with `#match` should normally fail for this method, and vice-versa. def negated_match(actual : TestExpression(T)) : MatchData forall T snapshot = snapshot_values(actual.value) - if match?(snapshot) + if snapshot.values.any? FailedMatchData.new(description, "#{actual.label} responds to #{label}", **values(snapshot)) else SuccessfulMatchData.new(description) @@ -46,13 +46,6 @@ module Spectator::Matchers {% end %} end - # Checks if all results from the snapshot are satisified. - private def match?(snapshot) - # The snapshot did the hard work. - # Here just check if all values are true. - snapshot.values.all? - end - # Produces the tuple for the failed match data from a snapshot of the results. private def values(snapshot) {% begin %} From e3a4dedfc6b08cb19958e55b27ac1ce72bdb4f2e Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Fri, 17 Jan 2020 22:14:25 -0700 Subject: [PATCH 5/7] Add RSpec `respond_to` matcher spec --- .../expectations/respond_to_matcher_spec.cr | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spec/rspec/expectations/respond_to_matcher_spec.cr diff --git a/spec/rspec/expectations/respond_to_matcher_spec.cr b/spec/rspec/expectations/respond_to_matcher_spec.cr new file mode 100644 index 0000000..771f8f6 --- /dev/null +++ b/spec/rspec/expectations/respond_to_matcher_spec.cr @@ -0,0 +1,29 @@ +require "../../spec_helper" + +# Examples taken from: +# https://relishapp.com/rspec/rspec-expectations/v/3-8/docs/built-in-matchers/respond-to-matcher +# and modified to fit Spectator and Crystal. +Spectator.describe "`respond_to` matcher" do + context "basic usage" do + describe "a string" do + it { is_expected.to respond_to(:size) } # It's size in Crystal, not length. + it { is_expected.to respond_to(:hash, :class, :to_s) } + it { is_expected.not_to respond_to(:to_model) } + it { is_expected.not_to respond_to(:compact, :flatten) } + + # deliberate failures + # TODO: Add support for expected failures. + xit { is_expected.to respond_to(:to_model) } + xit { is_expected.to respond_to(:compact, :flatten) } + xit { is_expected.not_to respond_to(:size) } + xit { is_expected.not_to respond_to(:hash, :class, :to_s) } + + # mixed examples--String responds to :length but not :flatten + # both specs should fail + xit { is_expected.to respond_to(:size, :flatten) } + xit { is_expected.not_to respond_to(:size, :flatten) } + end + end + + # Spectator doesn't support argument matching with respond_to. +end From 15f211c4b6ee863a187ec8a73d80f2c0bdbaed5c Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Fri, 17 Jan 2020 22:41:38 -0700 Subject: [PATCH 6/7] Add `it_fails` to handle expected failures --- spec/rspec/expectations/all_matcher_spec.cr | 8 ++-- spec/rspec/expectations/be_matchers_spec.cr | 44 ++++++++--------- .../expectations/be_within_matcher_spec.cr | 9 ++-- .../rspec/expectations/change_matcher_spec.cr | 8 ++-- .../expectations/comparison_matchers_spec.cr | 19 ++++---- .../contain_exactly_matcher_spec.cr | 6 +-- .../expectations/contain_matcher_spec.cr | 47 +++++++++---------- spec/rspec/expectations/cover_matcher_spec.cr | 15 +++--- .../expectations/end_with_matcher_spec.cr | 10 ++-- .../have_attributes_matcher_spec.cr | 11 ++--- spec/rspec/expectations/match_matcher_spec.cr | 10 ++-- .../expectations/predicate_matchers_spec.cr | 17 +++---- .../expectations/respond_to_matcher_spec.cr | 13 +++-- .../expectations/start_with_matcher_spec.cr | 10 ++-- spec/rspec/expectations/type_matchers_spec.cr | 41 ++++++++-------- spec/spec_helper.cr | 12 +++++ 16 files changed, 130 insertions(+), 150 deletions(-) diff --git a/spec/rspec/expectations/all_matcher_spec.cr b/spec/rspec/expectations/all_matcher_spec.cr index 35ad484..1d910e9 100644 --- a/spec/rspec/expectations/all_matcher_spec.cr +++ b/spec/rspec/expectations/all_matcher_spec.cr @@ -11,10 +11,9 @@ Spectator.describe "`all` matcher" do it { is_expected.to all(be < 10) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to all(be_even) } - xit { is_expected.to all(be_a(String)) } - xit { is_expected.to all(be > 2) } + it_fails { is_expected.to all(be_even) } + it_fails { is_expected.to all(be_a(String)) } + it_fails { is_expected.to all(be > 2) } end end @@ -29,7 +28,6 @@ Spectator.describe "`all` matcher" do xit { is_expected.to all(start_with("s")) } # .or contain("y") ) } # deliberate failures - # TODO: Add support for expected failures. # TODO: Add support for compound matchers. xit { is_expected.to all(contain("foo")) } # .and contain("bar") ) } xit { is_expected.to all(be_a(String)) } # .and start_with("a") ) } diff --git a/spec/rspec/expectations/be_matchers_spec.cr b/spec/rspec/expectations/be_matchers_spec.cr index 79636f2..1e4ee63 100644 --- a/spec/rspec/expectations/be_matchers_spec.cr +++ b/spec/rspec/expectations/be_matchers_spec.cr @@ -12,12 +12,11 @@ Spectator.describe "`be` matchers" do specify { expect(false).not_to be_truthy } # deliberate failures - # TODO: Add support for expected failures. - pending { expect(true).not_to be_truthy } - pending { expect(7).not_to be_truthy } - pending { expect("foo").not_to be_truthy } - pending { expect(nil).to be_truthy } - pending { expect(false).to be_truthy } + specify_fails { expect(true).not_to be_truthy } + specify_fails { expect(7).not_to be_truthy } + specify_fails { expect("foo").not_to be_truthy } + specify_fails { expect(nil).to be_truthy } + specify_fails { expect(false).to be_truthy } end context "be_falsey matcher" do @@ -28,12 +27,11 @@ Spectator.describe "`be` matchers" do specify { expect("foo").not_to be_falsey } # deliberate failures - # TODO: Add support for expected failures. - pending { expect(nil).not_to be_falsey } - pending { expect(false).not_to be_falsey } - pending { expect(true).to be_falsey } - pending { expect(7).to be_falsey } - pending { expect("foo").to be_falsey } + specify_fails { expect(nil).not_to be_falsey } + specify_fails { expect(false).not_to be_falsey } + specify_fails { expect(true).to be_falsey } + specify_fails { expect(7).to be_falsey } + specify_fails { expect("foo").to be_falsey } end context "be_nil matcher" do @@ -44,12 +42,11 @@ Spectator.describe "`be` matchers" do specify { expect("foo").not_to be_nil } # deliberate failures - # TODO: Add support for expected failures. - pending { expect(nil).not_to be_nil } - pending { expect(false).to be_nil } - pending { expect(true).to be_nil } - pending { expect(7).to be_nil } - pending { expect("foo").to be_nil } + specify_fails { expect(nil).not_to be_nil } + specify_fails { expect(false).to be_nil } + specify_fails { expect(true).to be_nil } + specify_fails { expect(7).to be_nil } + specify_fails { expect("foo").to be_nil } end context "be matcher" do @@ -60,11 +57,10 @@ Spectator.describe "`be` matchers" do specify { expect(false).not_to be } # deliberate failures - # TODO: Add support for expected failures. - pending { expect(true).not_to be } - pending { expect(7).not_to be } - pending { expect("foo").not_to be } - pending { expect(nil).to be } - pending { expect(false).to be } + specify_fails { expect(true).not_to be } + specify_fails { expect(7).not_to be } + specify_fails { expect("foo").not_to be } + specify_fails { expect(nil).to be } + specify_fails { expect(false).to be } end end diff --git a/spec/rspec/expectations/be_within_matcher_spec.cr b/spec/rspec/expectations/be_within_matcher_spec.cr index 0307d1b..2a99b51 100644 --- a/spec/rspec/expectations/be_within_matcher_spec.cr +++ b/spec/rspec/expectations/be_within_matcher_spec.cr @@ -15,11 +15,10 @@ Spectator.describe "`be_within` matcher" do it { is_expected.not_to be_within(0.5).of(26.9) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to be_within(0.5).of(28) } - xit { is_expected.not_to be_within(0.5).of(27) } - xit { is_expected.to be_within(0.5).of(28.1) } - xit { is_expected.to be_within(0.5).of(26.9) } + it_fails { is_expected.not_to be_within(0.5).of(28) } + it_fails { is_expected.not_to be_within(0.5).of(27) } + it_fails { is_expected.to be_within(0.5).of(28.1) } + it_fails { is_expected.to be_within(0.5).of(26.9) } end end end diff --git a/spec/rspec/expectations/change_matcher_spec.cr b/spec/rspec/expectations/change_matcher_spec.cr index c59423e..9e712a7 100644 --- a/spec/rspec/expectations/change_matcher_spec.cr +++ b/spec/rspec/expectations/change_matcher_spec.cr @@ -26,8 +26,7 @@ Spectator.describe "`change` matcher" do end # deliberate failure - # TODO: Add support for expected failures. - xit "should increment the count by 2" do + it_fails "should increment the count by 2" do expect { Counter.increment }.to change { Counter.count }.by(2) end end @@ -36,12 +35,11 @@ Spectator.describe "`change` matcher" do context "expect no change" do describe "Counter#increment" do # TODO: Allow multiple arguments to context/describe. # deliberate failures - # TODO: Add support for expected failures. - xit "should not increment the count by 1 (using not_to)" do + it_fails "should not increment the count by 1 (using not_to)" do expect { Counter.increment }.not_to change { Counter.count } end - xit "should not increment the count by 1 (using to_not)" do + it_fails "should not increment the count by 1 (using to_not)" do expect { Counter.increment }.to_not change { Counter.count } end end diff --git a/spec/rspec/expectations/comparison_matchers_spec.cr b/spec/rspec/expectations/comparison_matchers_spec.cr index aef4194..bb201d7 100644 --- a/spec/rspec/expectations/comparison_matchers_spec.cr +++ b/spec/rspec/expectations/comparison_matchers_spec.cr @@ -12,11 +12,10 @@ Spectator.describe "Comparison matchers" do it { is_expected.to be >= 17 } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to be < 15 } - xit { is_expected.to be > 20 } - xit { is_expected.to be <= 17 } - xit { is_expected.to be >= 19 } + it_fails { is_expected.to be < 15 } + it_fails { is_expected.to be > 20 } + it_fails { is_expected.to be <= 17 } + it_fails { is_expected.to be >= 19 } # it { is_expected.to be < 'a' } # Removed because Crystal doesn't support Int32#<(Char) end @@ -24,7 +23,6 @@ Spectator.describe "Comparison matchers" do it { is_expected.to be < 'b' } # deliberate failures - # TODO: Add support for expected failures. # it { is_expected.to be < 18 } # Removed because Crystal doesn't support Char#<(Int32) end end @@ -37,11 +35,10 @@ Spectator.describe "Comparison matchers" do it { is_expected.to be >= "Banana" } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to be < "Cranberry" } - xit { is_expected.to be > "Zuchini" } - xit { is_expected.to be <= "Potato" } - xit { is_expected.to be >= "Tomato" } + it_fails { is_expected.to be < "Cranberry" } + it_fails { is_expected.to be > "Zuchini" } + it_fails { is_expected.to be <= "Potato" } + it_fails { is_expected.to be >= "Tomato" } end end end diff --git a/spec/rspec/expectations/contain_exactly_matcher_spec.cr b/spec/rspec/expectations/contain_exactly_matcher_spec.cr index 14d3c33..c4d7d3c 100644 --- a/spec/rspec/expectations/contain_exactly_matcher_spec.cr +++ b/spec/rspec/expectations/contain_exactly_matcher_spec.cr @@ -14,8 +14,7 @@ Spectator.describe "`contain_exactly` matcher" do it { is_expected.to contain_exactly(3, 2, 1) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to contain_exactly(1, 2, 1) } + it_fails { is_expected.to contain_exactly(1, 2, 1) } end end @@ -25,8 +24,7 @@ Spectator.describe "`contain_exactly` matcher" do it { is_expected.to_not contain_exactly(1, 2) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to_not contain_exactly(1, 3, 2) } + it_fails { is_expected.to_not contain_exactly(1, 3, 2) } end end end diff --git a/spec/rspec/expectations/contain_matcher_spec.cr b/spec/rspec/expectations/contain_matcher_spec.cr index a75897c..6c8e558 100644 --- a/spec/rspec/expectations/contain_matcher_spec.cr +++ b/spec/rspec/expectations/contain_matcher_spec.cr @@ -27,17 +27,16 @@ Spectator.describe "`contain` matcher" do it { is_expected.not_to contain(43, 100) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to contain(4) } - xit { is_expected.to contain(be_even) } - xit { is_expected.not_to contain(1) } - xit { is_expected.not_to contain(3) } - xit { is_expected.not_to contain(7) } - xit { is_expected.not_to contain(1, 3, 7) } + it_fails { is_expected.to contain(4) } + it_fails { is_expected.to contain(be_even) } + it_fails { is_expected.not_to contain(1) } + it_fails { is_expected.not_to contain(3) } + it_fails { is_expected.not_to contain(7) } + it_fails { is_expected.not_to contain(1, 3, 7) } # both of these should fail since it contains 1 but not 9 - xit { is_expected.to contain(1, 9) } - xit { is_expected.not_to contain(1, 9) } + it_fails { is_expected.to contain(1, 9) } + it_fails { is_expected.not_to contain(1, 9) } end end @@ -49,11 +48,10 @@ Spectator.describe "`contain` matcher" do it { is_expected.not_to contain("foo", "bar") } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to contain("foo") } - xit { is_expected.not_to contain("str") } - xit { is_expected.to contain("str", "foo") } - xit { is_expected.not_to contain("str", "foo") } + it_fails { is_expected.to contain("foo") } + it_fails { is_expected.not_to contain("str") } + it_fails { is_expected.to contain("str", "foo") } + it_fails { is_expected.not_to contain("str", "foo") } end end @@ -64,34 +62,33 @@ Spectator.describe "`contain` matcher" do subject { {:a => 7, :b => 5} } # Hash syntax is changed here from `:a => 7` to `a: 7`. - xit { is_expected.to contain(:a) } - xit { is_expected.to contain(:b, :a) } + # it { is_expected.to contain(:a) } + # it { is_expected.to contain(:b, :a) } # TODO: This hash-like syntax isn't supported. # it { is_expected.to contain(a: 7) } # it { is_expected.to contain(b: 5, a: 7) } - xit { is_expected.not_to contain(:c) } - xit { is_expected.not_to contain(:c, :d) } + # it { is_expected.not_to contain(:c) } + # it { is_expected.not_to contain(:c, :d) } # it { is_expected.not_to contain(d: 2) } # it { is_expected.not_to contain(a: 5) } # it { is_expected.not_to contain(b: 7, a: 5) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to contain(:a) } - xit { is_expected.not_to contain(:b, :a) } + # it { is_expected.not_to contain(:a) } + # it { is_expected.not_to contain(:b, :a) } # it { is_expected.not_to contain(a: 7) } # it { is_expected.not_to contain(a: 7, b: 5) } - xit { is_expected.to contain(:c) } - xit { is_expected.to contain(:c, :d) } + # it { is_expected.to contain(:c) } + # it { is_expected.to contain(:c, :d) } # it { is_expected.to contain(d: 2) } # it { is_expected.to contain(a: 5) } # it { is_expected.to contain(a: 5, b: 7) } # Mixed cases--the hash contains one but not the other. # All 4 of these cases should fail. - xit { is_expected.to contain(:a, :d) } - xit { is_expected.not_to contain(:a, :d) } + # it { is_expected.to contain(:a, :d) } + # it { is_expected.not_to contain(:a, :d) } # it { is_expected.to contain(a: 7, d: 3) } # it { is_expected.not_to contain(a: 7, d: 3) } end diff --git a/spec/rspec/expectations/cover_matcher_spec.cr b/spec/rspec/expectations/cover_matcher_spec.cr index fb1a74a..cf32929 100644 --- a/spec/rspec/expectations/cover_matcher_spec.cr +++ b/spec/rspec/expectations/cover_matcher_spec.cr @@ -15,16 +15,15 @@ Spectator.describe "`cover` matcher" do it { is_expected.not_to cover(11, 12) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to cover(11) } - xit { is_expected.not_to cover(4) } - xit { is_expected.not_to cover(6) } - xit { is_expected.not_to cover(8) } - xit { is_expected.not_to cover(4, 6, 8) } + it_fails { is_expected.to cover(11) } + it_fails { is_expected.not_to cover(4) } + it_fails { is_expected.not_to cover(6) } + it_fails { is_expected.not_to cover(8) } + it_fails { is_expected.not_to cover(4, 6, 8) } # both of these should fail since it covers 5 but not 11 - xit { is_expected.to cover(5, 11) } - xit { is_expected.not_to cover(5, 11) } + it_fails { is_expected.to cover(5, 11) } + it_fails { is_expected.not_to cover(5, 11) } end end end diff --git a/spec/rspec/expectations/end_with_matcher_spec.cr b/spec/rspec/expectations/end_with_matcher_spec.cr index c19720f..75e6fd1 100644 --- a/spec/rspec/expectations/end_with_matcher_spec.cr +++ b/spec/rspec/expectations/end_with_matcher_spec.cr @@ -10,9 +10,8 @@ Spectator.describe "`end_with` matcher" do it { is_expected.not_to end_with "stringy" } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to end_with "string" } - xit { is_expected.to end_with "stringy" } + it_fails { is_expected.not_to end_with "string" } + it_fails { is_expected.to end_with "stringy" } end end @@ -25,9 +24,8 @@ Spectator.describe "`end_with` matcher" do # it { is_expected.not_to end_with 0, 1, 2, 3, 4, 5 } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to end_with 4 } - xit { is_expected.to end_with 3 } + it_fails { is_expected.not_to end_with 4 } + it_fails { is_expected.to end_with 3 } end end end diff --git a/spec/rspec/expectations/have_attributes_matcher_spec.cr b/spec/rspec/expectations/have_attributes_matcher_spec.cr index dfa273b..81c11dc 100644 --- a/spec/rspec/expectations/have_attributes_matcher_spec.cr +++ b/spec/rspec/expectations/have_attributes_matcher_spec.cr @@ -24,14 +24,13 @@ Spectator.describe "`have_attributes` matcher" do # it { is_expected.not_to have_attributes(age: (a_value < 30) ) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to have_attributes(name: "Bob") } - xit { is_expected.to have_attributes(name: 10) } + it_fails { is_expected.to have_attributes(name: "Bob") } + it_fails { is_expected.to have_attributes(name: 10) } # fails if any of the attributes don't match - xit { is_expected.to have_attributes(name: "Bob", age: 32) } - xit { is_expected.to have_attributes(name: "Jim", age: 10) } - xit { is_expected.to have_attributes(name: "Bob", age: 10) } + it_fails { is_expected.to have_attributes(name: "Bob", age: 32) } + it_fails { is_expected.to have_attributes(name: "Jim", age: 10) } + it_fails { is_expected.to have_attributes(name: "Bob", age: 10) } end end end diff --git a/spec/rspec/expectations/match_matcher_spec.cr b/spec/rspec/expectations/match_matcher_spec.cr index 28b4f72..dac2a0c 100644 --- a/spec/rspec/expectations/match_matcher_spec.cr +++ b/spec/rspec/expectations/match_matcher_spec.cr @@ -10,9 +10,8 @@ Spectator.describe "`match` matcher" do it { is_expected.not_to match(/foo/) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to match(/str/) } - xit { is_expected.to match(/foo/) } + it_fails { is_expected.not_to match(/str/) } + it_fails { is_expected.to match(/foo/) } end end @@ -22,9 +21,8 @@ Spectator.describe "`match` matcher" do it { is_expected.not_to match("drinks") } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to match("food") } - xit { is_expected.to match("drinks") } + it_fails { is_expected.not_to match("food") } + it_fails { is_expected.to match("drinks") } end end end diff --git a/spec/rspec/expectations/predicate_matchers_spec.cr b/spec/rspec/expectations/predicate_matchers_spec.cr index f2dac5c..8a1cbda 100644 --- a/spec/rspec/expectations/predicate_matchers_spec.cr +++ b/spec/rspec/expectations/predicate_matchers_spec.cr @@ -11,8 +11,7 @@ Spectator.describe "Predicate matchers" do describe 7 do # deliberate failure - # TODO: Add support for expected failures. - xit { is_expected.to be_zero } + it_fails { is_expected.to be_zero } end end @@ -23,8 +22,7 @@ Spectator.describe "Predicate matchers" do describe [] of Int32 do # deliberate failure - # TODO: Add support for expected failures. - xit { is_expected.not_to be_empty } + it_fails { is_expected.not_to be_empty } end end @@ -35,8 +33,7 @@ Spectator.describe "Predicate matchers" do it { is_expected.to have_key(:foo) } # deliberate failure - # TODO: Add support for expected failures. - xit { is_expected.to have_key(:bar) } + it_fails { is_expected.to have_key(:bar) } end end @@ -58,8 +55,7 @@ Spectator.describe "Predicate matchers" do subject { {"foo" => 7, "bar" => 5} } # deliberate failure - # TODO: Add support for expected failures. - xit { is_expected.not_to have_all_string_keys } + it_fails { is_expected.not_to have_all_string_keys } end end end @@ -76,9 +72,8 @@ Spectator.describe "Predicate matchers" do it { is_expected.not_to be_multiple_of(7) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to be_multiple_of(4) } - xit { is_expected.to be_multiple_of(5) } + it_fails { is_expected.not_to be_multiple_of(4) } + it_fails { is_expected.to be_multiple_of(5) } end end diff --git a/spec/rspec/expectations/respond_to_matcher_spec.cr b/spec/rspec/expectations/respond_to_matcher_spec.cr index 771f8f6..ff52285 100644 --- a/spec/rspec/expectations/respond_to_matcher_spec.cr +++ b/spec/rspec/expectations/respond_to_matcher_spec.cr @@ -12,16 +12,15 @@ Spectator.describe "`respond_to` matcher" do it { is_expected.not_to respond_to(:compact, :flatten) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.to respond_to(:to_model) } - xit { is_expected.to respond_to(:compact, :flatten) } - xit { is_expected.not_to respond_to(:size) } - xit { is_expected.not_to respond_to(:hash, :class, :to_s) } + it_fails { is_expected.to respond_to(:to_model) } + it_fails { is_expected.to respond_to(:compact, :flatten) } + it_fails { is_expected.not_to respond_to(:size) } + it_fails { is_expected.not_to respond_to(:hash, :class, :to_s) } # mixed examples--String responds to :length but not :flatten # both specs should fail - xit { is_expected.to respond_to(:size, :flatten) } - xit { is_expected.not_to respond_to(:size, :flatten) } + it_fails { is_expected.to respond_to(:size, :flatten) } + it_fails { is_expected.not_to respond_to(:size, :flatten) } end end diff --git a/spec/rspec/expectations/start_with_matcher_spec.cr b/spec/rspec/expectations/start_with_matcher_spec.cr index c2942cc..471f1d6 100644 --- a/spec/rspec/expectations/start_with_matcher_spec.cr +++ b/spec/rspec/expectations/start_with_matcher_spec.cr @@ -10,9 +10,8 @@ Spectator.describe "`start_with` matcher" do it { is_expected.not_to start_with "that" } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to start_with "this" } - xit { is_expected.to start_with "that" } + it_fails { is_expected.not_to start_with "this" } + it_fails { is_expected.to start_with "that" } end end @@ -25,9 +24,8 @@ Spectator.describe "`start_with` matcher" do # it { is_expected.not_to start_with(0, 1, 2, 3, 4, 5) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to start_with 0 } - xit { is_expected.to start_with 3 } + it_fails { is_expected.not_to start_with 0 } + it_fails { is_expected.to start_with 3 } end end end diff --git a/spec/rspec/expectations/type_matchers_spec.cr b/spec/rspec/expectations/type_matchers_spec.cr index c2b1a2d..35bec18 100644 --- a/spec/rspec/expectations/type_matchers_spec.cr +++ b/spec/rspec/expectations/type_matchers_spec.cr @@ -40,19 +40,18 @@ Spectator.describe "Type matchers" do it { is_expected.not_to be_a(String) } # deliberate failures - # TODO: Add support for expected failures. - xit { is_expected.not_to be_kind_of(Derived) } - xit { is_expected.not_to be_a_kind_of(Derived) } - xit { is_expected.not_to be_a(Derived) } - xit { is_expected.not_to be_kind_of(Base) } - xit { is_expected.not_to be_a_kind_of(Base) } - xit { is_expected.not_to be_an(Base) } - xit { is_expected.not_to be_kind_of(MyModule) } - xit { is_expected.not_to be_a_kind_of(MyModule) } - xit { is_expected.not_to be_a(MyModule) } - xit { is_expected.to be_kind_of(String) } - xit { is_expected.to be_a_kind_of(String) } - xit { is_expected.to be_a(String) } + it_fails { is_expected.not_to be_kind_of(Derived) } + it_fails { is_expected.not_to be_a_kind_of(Derived) } + it_fails { is_expected.not_to be_a(Derived) } + it_fails { is_expected.not_to be_kind_of(Base) } + it_fails { is_expected.not_to be_a_kind_of(Base) } + it_fails { is_expected.not_to be_an(Base) } + it_fails { is_expected.not_to be_kind_of(MyModule) } + it_fails { is_expected.not_to be_a_kind_of(MyModule) } + it_fails { is_expected.not_to be_a(MyModule) } + it_fails { is_expected.to be_kind_of(String) } + it_fails { is_expected.to be_a_kind_of(String) } + it_fails { is_expected.to be_a(String) } end context "be_(an_)instance_of matcher" do @@ -87,14 +86,14 @@ Spectator.describe "Type matchers" do it { is_expected.not_to be_an_instance_of(String) } # deliberate failures - xit { is_expected.not_to be_instance_of(Derived) } - xit { is_expected.not_to be_an_instance_of(Derived) } - xit { is_expected.to be_instance_of(Base) } - xit { is_expected.to be_an_instance_of(Base) } - xit { is_expected.to be_instance_of(MyModule) } - xit { is_expected.to be_an_instance_of(MyModule) } - xit { is_expected.to be_instance_of(String) } - xit { is_expected.to be_an_instance_of(String) } + it_fails { is_expected.not_to be_instance_of(Derived) } + it_fails { is_expected.not_to be_an_instance_of(Derived) } + it_fails { is_expected.to be_instance_of(Base) } + it_fails { is_expected.to be_an_instance_of(Base) } + it_fails { is_expected.to be_instance_of(MyModule) } + it_fails { is_expected.to be_an_instance_of(MyModule) } + it_fails { is_expected.to be_instance_of(String) } + it_fails { is_expected.to be_an_instance_of(String) } end end end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index bca1453..f8047da 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -1 +1,13 @@ require "../src/spectator" + +macro it_fails(description = nil, &block) + it {{description}} do + expect do + {{block.body}} + end.to raise_error(Spectator::ExampleFailed) + end +end + +macro specify_fails(description = nil, &block) + it_fails {{description}} {{block}} +end From 272ebcd69320744fdccada554f5c7131a802d836 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sun, 19 Jan 2020 09:52:12 -0700 Subject: [PATCH 7/7] Fix subject with group describing a type An explicit subject should be used when describing a type. This mimics RSpec. --- src/spectator/dsl/groups.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spectator/dsl/groups.cr b/src/spectator/dsl/groups.cr index 227c224..33c12a1 100644 --- a/src/spectator/dsl/groups.cr +++ b/src/spectator/dsl/groups.cr @@ -24,7 +24,7 @@ module Spectator {{what}} end - def _spectator_implicit_subject(*args) + def subject(*args) described_class.new(*args) end {% else %}