From e9aa71e67a7255a484d12961fdccf3d0ff462f4a Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Sun, 2 Mar 2014 00:31:06 -0800 Subject: [PATCH 1/3] Always use color. --- spec/spec_helper.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a7b197a2b8..842d71d97f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -89,10 +89,6 @@ def run(reporter=nil) end end - def in_editor? - ENV.has_key?('TM_MODE') || ENV.has_key?('EMACS') || ENV.has_key?('VIM') - end - module EnvHelpers def with_env_vars(vars) original = ENV.to_hash @@ -135,7 +131,7 @@ def without_env_vars(*vars) end # runtime options - c.color = !in_editor? + c.color = true c.include EnvHelpers c.filter_run_excluding :ruby => lambda {|version| case version.to_s From b39385e6624d2f42f588eda7b82a68cf6d867eb7 Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Sat, 1 Mar 2014 22:29:34 -0800 Subject: [PATCH 2/3] Make `described_class` to return innermost described class. It used to return the outermost described class. It doesn't happen very often that there is more than one class being described in the set of nested example groups (and we generally recommend against it), but this was surprising behavior to me. Fixes #1114. --- Changelog.md | 6 +++++ features/subject/implicit_subject.feature | 12 +++------- lib/rspec/core/metadata.rb | 2 +- spec/rspec/core/example_group_spec.rb | 18 ++++++++++++--- spec/rspec/core/metadata_spec.rb | 28 +++++++++++------------ 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/Changelog.md b/Changelog.md index 7248dedf2d..8edf40304a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,12 @@ ### 3.0.0.rc1 Development [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.0.0.beta2...master) +Breaking Changes for 3.0.0: + +* Change `described_class` so that in a nested group like `describe + MyClass`, it returns `MyClass` rather than the outer group's described + class. (Myron Marston) + Enhancements: * Add `config.default_formatter` attribute, which can be used to set a diff --git a/features/subject/implicit_subject.feature b/features/subject/implicit_subject.feature index 3197a77d97..8f19d4581b 100644 --- a/features/subject/implicit_subject.feature +++ b/features/subject/implicit_subject.feature @@ -33,7 +33,7 @@ Feature: implicitly defined subject When I run `rspec nested_subject_spec.rb` Then the examples should all pass - Scenario: subject in a nested group with a different class (outermost wins) + Scenario: subject in a nested group with a different class (innermost wins) Given a file named "nested_subject_spec.rb" with: """ruby class ArrayWithOneElement < Array @@ -46,14 +46,8 @@ Feature: implicitly defined subject describe Array do describe ArrayWithOneElement do context "referenced as subject" do - it "should be empty (because it is the Array declared at the top)" do - expect(subject).to be_empty - end - end - - context "created in the example" do - it "should not be empty" do - expect(ArrayWithOneElement.new).not_to be_empty + it "contains one element" do + expect(subject).to include("first element") end end end diff --git a/lib/rspec/core/metadata.rb b/lib/rspec/core/metadata.rb index 081b378273..bae544b471 100644 --- a/lib/rspec/core/metadata.rb +++ b/lib/rspec/core/metadata.rb @@ -150,7 +150,7 @@ def described_class end end - container_stack.reverse.each do |g| + container_stack.each do |g| candidate = g[:description_args].first return candidate unless String === candidate || Symbol === candidate end diff --git a/spec/rspec/core/example_group_spec.rb b/spec/rspec/core/example_group_spec.rb index aee464a791..f8e6e316e0 100644 --- a/spec/rspec/core/example_group_spec.rb +++ b/spec/rspec/core/example_group_spec.rb @@ -472,7 +472,7 @@ def ascending_numbers context "in a nested group" do it "inherits the described class/module from the outer group" do group = ExampleGroup.describe(String) do - describe Array do + describe "nested" do example "describes is String" do expect(described_class).to eq(String) end @@ -481,6 +481,18 @@ def ascending_numbers expect(group.run).to be_truthy, "expected examples in group to pass" end + + it "overrides the described class when a class is passed" do + value = nil + + ExampleGroup.describe(String) do + describe Array do + example { value = described_class } + end + end.run + + expect(value).to eq(Array) + end end context "for `describe(SomeClass)` within a `describe 'some string' group" do @@ -1111,8 +1123,8 @@ def extract_execution_results(group) describe Object, "describing nested example_groups", :little_less_nested => 'yep' do describe "A sample nested group", :nested_describe => "yep" do - it "sets the described class to the described class of the outer most group" do |ex| - expect(ex.example_group.described_class).to eq(ExampleGroup) + it "sets the described class to the nearest described class" do |ex| + expect(ex.example_group.described_class).to eq(Object) end it "sets the description to 'A sample nested describe'" do |ex| diff --git a/spec/rspec/core/metadata_spec.rb b/spec/rspec/core/metadata_spec.rb index 781fe11d35..2c6b86656b 100644 --- a/spec/rspec/core/metadata_spec.rb +++ b/spec/rspec/core/metadata_spec.rb @@ -290,32 +290,32 @@ module Core end context "in a nested group" do - it "returns the parent group's described class" do - sm = Metadata.new - sm.process(String) + it "inherits the parent group's described class" do + parent = Metadata.new + parent.process(Hash) - m = Metadata.new(sm) - m.process(Array) + child = Metadata.new(parent) + child.process("sub context") - expect(m[:example_group][key]).to be(String) + expect(child[:example_group][key]).to be(Hash) end - it "returns own described class if parent doesn't have one" do - sm = Metadata.new - sm.process("foo") + it "sets the described class when passing a class" do + parent = Metadata.new + parent.process(String) - m = Metadata.new(sm) - m.process(Array) + child = Metadata.new(parent) + child.process(Array) - expect(m[:example_group][key]).to be(Array) + expect(child[:example_group][key]).to be(Array) end - it "can override a parent group's described class" do + it "can override a parent group's described class using metdata" do parent = Metadata.new parent.process(String) child = Metadata.new(parent) - child.process(Fixnum) + child.process("sub context") child[:example_group][key] = Hash grandchild = Metadata.new(child) From 83f99365e833788bd36074e5f53091319723a5df Mon Sep 17 00:00:00 2001 From: Myron Marston Date: Sun, 2 Mar 2014 14:14:11 -0800 Subject: [PATCH 3/3] Refine `described_class` inference further. In the last commit, I made inner `describe SomeClass` example groups get `SomeClass` as the described_class. The logic confusingly allowed a `:described_class` metadata key in an outer group take precedence, which meant that the behavior depended on whether or not `described_class` was referenced from the outer group. This fixes that, making it work consistently: - Use `:described_class` is present. - Otherwise, use the group's `describe` arg (unless it's something like a string). - If neither of those, look in the parent and recurse. --- lib/rspec/core/metadata.rb | 2 -- spec/rspec/core/example_group_spec.rb | 27 +++++++++++++++++++-------- spec/rspec/core/metadata_spec.rb | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/rspec/core/metadata.rb b/lib/rspec/core/metadata.rb index bae544b471..2539549fad 100644 --- a/lib/rspec/core/metadata.rb +++ b/lib/rspec/core/metadata.rb @@ -148,9 +148,7 @@ def described_class return value unless value.nil? end end - end - container_stack.each do |g| candidate = g[:description_args].first return candidate unless String === candidate || Symbol === candidate end diff --git a/spec/rspec/core/example_group_spec.rb b/spec/rspec/core/example_group_spec.rb index f8e6e316e0..49638ec6aa 100644 --- a/spec/rspec/core/example_group_spec.rb +++ b/spec/rspec/core/example_group_spec.rb @@ -482,16 +482,27 @@ def ascending_numbers expect(group.run).to be_truthy, "expected examples in group to pass" end - it "overrides the described class when a class is passed" do - value = nil + context "when a class is passed" do + def described_class_value + value = nil + + ExampleGroup.describe(String) do + yield if block_given? + describe Array do + example { value = described_class } + end + end.run - ExampleGroup.describe(String) do - describe Array do - example { value = described_class } - end - end.run + value + end + + it "overrides the described class" do + expect(described_class_value).to eq(Array) + end - expect(value).to eq(Array) + it "overrides the described class even when described_class is referenced in the outer group" do + expect(described_class_value { described_class }).to eq(Array) + end end end diff --git a/spec/rspec/core/metadata_spec.rb b/spec/rspec/core/metadata_spec.rb index 2c6b86656b..a978b3477b 100644 --- a/spec/rspec/core/metadata_spec.rb +++ b/spec/rspec/core/metadata_spec.rb @@ -319,7 +319,7 @@ module Core child[:example_group][key] = Hash grandchild = Metadata.new(child) - grandchild.process(Array) + grandchild.process("sub context") expect(grandchild[:example_group][key]).to be(Hash) expect(child[:example_group][key]).to be(Hash)