11 Stimmen

Muster für den Zugriff auf die Themenhierarchie in RSpec

Wenn ich RSpec verwende, um tief verschachtelte Datenstrukturen zu testen, sehe ich die Notwendigkeit, Subjekte in verschachtelten Kontexten in Bezug auf die Subjekte in den enthaltenen Kontexten zu definieren. Ich habe ausgiebig gesucht, aber keine Beispiele dafür gefunden, wie man dies tun kann, ohne viele Variablen zu definieren. Das verkompliziert die Spezifikationen und schränkt die Möglichkeit der Wiederverwendung von Spezifikationen ein. Ich bin neugierig, ob es eine Möglichkeit gibt, dies in RSpec so zu tun, wie es ist, und wenn nicht, was wäre ein guter Weg, um das Problem anzugehen.

Im Moment sieht mein Code etwa so aus:

context 'with a result which is a Hash' do
  before do
    @result = get_result()
  end
  subject { @result }
  it { should be_a Hash }
  context 'with an Array' do
    before do
      @array_elem = @result[special_key]
    end
    subject { @array_elem }
    it { should be_an Array }
    context 'that contains a Hash' do
      before do
        @nested_hash = ...
      end
      subject { @nested_hash }
      ...
    end
  end
end

Stattdessen würde ich lieber etwas schreiben, das in etwa so lautet:

context 'with a result which is a Hash' do
  subject { get_result }
  it { should be_a Hash }
  context 'with an Array' do
    subject { parent_subject[special_key] }
    it { should be_an Array }
    context 'that contains a Hash' do
      subject { do_something_with(parent_subject) }
      ...
    end
  end
end

Wie lässt sich RSpec um diese Art der automatischen Verwaltung der Themenhierarchie erweitern?

11voto

Shevaun Punkte 1208

Ich war auf der Suche nach der gleichen Sache und wollte die subject so dass ich die its also habe ich es so implementiert:

describe "#results" do
  let(:results) { Class.results }

  context "at the top level" do
    subject { results }

    it { should be_a Hash }
    its(['featuredDate']) { should == expected_date }
    its(['childItems']) { should be_a Array }
  end

  context "the first child item" do
    subject { results['childItems'][0] }

    it { should be_a Hash }
    its(['title']) { should == 'Title' }
    its(['body']) { should == 'Body' }
  end

  context "the programme info for the first child item" do
    subject { results['childItems'][0]['programme'] }

    it { should be_a Hash }
    its(['title']) { should == 'title' }
    its(['description']) { should == 'description' }
  end
end

6voto

Andreas Finne Punkte 168

Ich habe diese Frage gefunden, als ich versuchte, etwas Ähnliches zu tun. Meine Lösung ist zu finden unter https://gist.github.com/asmand/d1ccbcd01789353c01c3

Es geht darum, die Gleitzeitberechnung einer Woche über Weihnachten zu testen, d. h. von der gegebenen Woche sind nur Montag und Freitag Arbeitstage, der Rest sind Feiertage.

Die Lösung basiert auf benannten Themen. D.h.

describe WeeklyFlexCalculator, "during Christmas week" do

  subject(:calculation) { WeeklyFlexCalculator.new(params).calculate }

  context "with no work performed" do
    it { should have(1).item }

    context "the week calculated" do
      subject(:workweek) {calculation[0]}

      its([:weekTarget]) { should eq 15.0 }
      its([:weekEffort]) { should eq 0.0 }

      context "the work efforts" do
        subject(:efforts) {workweek[:efforts]}

        it { should have(2).items }

        context "the first work effort" do
          subject(:effort) {efforts[0]}

          its([:target]) {should eq 7.5}
          its([:diff]) {should eq -7.5}
          its([:effort]) {should eq 0.0}
        end
      end
    end
  end
end

Der Kürze halber wurde eine Menge Code weggelassen, aber das vollständige Beispiel ist im verlinkten Gist zu finden.

2voto

nathanvda Punkte 48972

Bei dieser Art von hierarchischer Struktur würde ich auf die Verwendung von subject und machen das Thema explizit. Dies könnte zwar zu etwas mehr Tipparbeit führen (wenn Sie viele Tests haben), ist aber auch übersichtlicher. Die verschachtelte subject -Aussagen können auch verwirrend sein, wenn man sich drei Ebenen tiefer befindet, was eigentlich geprüft wird.

  context 'with a result which is a Hash' do
    before do
      @result = get_result()
    end
    it { @result.should be_a Hash }
    context 'special_key' do
      before do
        @array_elem = @result[special_key]
      end
      it { @array_elem.should be_an Array }
      context 'that contains a Hash' do
        before do
          @nested_hash = ...
        end
        it { @nested_hash.should be_a Hash }
        ...
      end
    end
  end

Aber das könnte Geschmackssache sein. Ich hoffe, das hilft.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X