advishnuprasad
advishnuprasad

Reputation: 341

Rspec guidance on repetitive expect

I have a test case like this.

subject(:report) { @report.data }
it { expect(report[0][:id]).to eq(@c1.id) }
it { expect(report[1][:id]).to eq(@c2.id) }
it { expect(report[2][:id]).to eq(@c3.id) }
it { expect(report[0][:title]).to eq("Announcement3") }
it { expect(report[1][:title]).to eq("Announcement2") }
it { expect(report[2][:title]).to eq("Announcement1") }

I feel this is not really an efficient way.

Is there any other way to make it efficient ? So that it looks like one line condition.

Upvotes: 0

Views: 126

Answers (3)

Caleb Hearth
Caleb Hearth

Reputation: 3365

You could map reports to the keys you care about and make expectations on that:

expect(report.map { |h| h[:title] }).to eq [array, of, values]

You could use include to check each report member's keys:

expect(report[0]).to include id: @c1.id, title: "Announcement3"

You could build an "expected" object and test equality:

expected = [{ id: @c1.id, title: "Announcement3" }, ...]
expect(report).to eq expected

Upvotes: 0

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84443

Test Behavior, Not Composition

Always test behavior, not composition. What you ought to be testing here is the behavior that given some set of fixed inputs, a report will generate the same fixed output every single time. You aren't doing that; you're introspecting individual report elements, which is about composition.

Instead, consider using fixtures or FactoryGirl (or even just a setup block) to define fixed inputs, and then check that:

it 'creates valid report data' do
  expect(@report.data).to eq @sample.data
end

More on Behavior

If each element of your report is coming from a different method, you ought to be testing the behavior of each of those methods separately, rather than decomposing the final report. That is another way to make your test clearer and more meaningful, and addresses the "unit" in unit testing.

Upvotes: 3

Tumas
Tumas

Reputation: 1727

I'd rather write something like this:

it { expect(report[0]).to include(id: @c1.id, title: "Announcement3") }
it { expect(report[1]).to include(id: @c2.id, title: "Announcement2") }
it { expect(report[2]).to include(id: @c3.id, title: "Announcement1") }

It does not get that deep into report structure and for me looks more readable.

Upvotes: 1

Related Questions