RSpec is a very powerful tool for testing applications. It's been around for a while and provides a rich feature set.

One thing that RSpec provides is the ability to stub a method on an object or class so that, instead of executing and behaving as it normally would, it instead returns a hard-coded value and never actually executes.

Here is a simple example [1]:

```
student = load_student_from_database(id: 77)
allow(student).to receive(:grades).and_return(['A', 'A+', 'C'])
puts(student.grades)
```

The second line in that snippet of code causes any calls to `student.grades`

to *always* return the array `['A', 'A+', 'C']`

. The actual definition of the `#grades`

method will never be invoked.

Let's build on this example.

We can imagine that if there exists a `Student`

class in our system, then there probably exists a `GpaCalculator`

class. Let's go ahead and TDD such a class into existence.

As a reference point, let's use the GPA scale of my Alma Mater, DePaul University, where an A translates to 4.0 grade points and a B translates to 3.0 grade points.

Here is what the first few tests might look like:

```
describe GpaCalculator do
it 'calculates one A to be 4.0' do
student = Student.new
allow(student).to receive(:grades).and_return(['A'])
expect(GpaCalculator.new(student).calculate).to eq(4.0)
end
it 'calculates one B to be 3.0' do
student = Student.new
allow(student).to receive(:grades).and_return(['B'])
expect(GpaCalculator.new(student).calculate).to eq(3.0)
end
it 'calculates one A and one B to be 3.5' do
student = Student.new
allow(student).to receive(:grades).and_return(['A', 'B'])
expect(GpaCalculator.new(student).calculate).to eq(3.5)
end
end
```

This is already getting a little clunky. Someone who sees an opportunity for refactoring this may clean it up to look a little bit like this:

```
describe GpaCalculator do
let(:student) { Student.new }
subject { GpaCalculator.new(student) }
it 'calculates one A to be 4.0' do
allow(student).to receive(:grades).and_return(['A'])
expect(subject.calculate).to eq(4.0)
end
it 'calculates one B to be 3.0' do
allow(student).to receive(:grades).and_return(['B'])
expect(subject.calculate).to eq(3.0)
end
it 'calculates one A and one B to be 3.5' do
allow(student).to receive(:grades).and_return(['A', 'B'])
expect(subject.calculate).to eq(3.5)
end
end
```

That's certainly better. Unfortunately, many people will stop here and move on to other things. Now, for an example this small, it's not a grave sin to leave it as is. But on a large test suite, cleaning as much as you can is a big deal and really helps increase maintainability in the long term.

In a situation such as this, where you repeatedly stub the same method to return a different array (or hash) in every test, there exist a few techniques that remove noise and improve readability.

One approach that I've recently begun suggesting is this:

```
describe GpaCalculator do
let(:grades) { [] }
let(:student) { Student.new }
subject { GpaCalculator.new(student) }
before :each do
allow(student).to receive(:grades).and_return(grades)
end
it 'calculates one A to be 4.0' do
grades << 'A'
expect(subject.calculate).to eq(4.0)
end
it 'calculates one B to be 3.0' do
grades << 'B'
expect(subject.calculate).to eq(3.0)
end
it 'calculates one A and one B to be 3.5' do
grades << 'A'
grades << 'B'
expect(subject.calculate).to eq(3.5)
end
end
```

A little cleaner, isn't it? We move the noisy syntax for "stub this to return that" out of each individual test and into a before block. What remains is the meat of every single test case–the expected GPA and the grades that directly affect it.

Some folks may not like the `before :each`

block. An alternative is to throw the stub directly into the corresponding let block:

```
let(:student) {
student = Student.new
allow(student).to receive(:grades).and_return(grades)
student
}
```

Which, in my opinion, isn't really any better, but it is an option.

A completely different approach would be use doubles[3] and avoid the `allow`

altogether:

```
let(:student) { instance_double('Student', grades: grades) }
```

Once you go through all this, your final version will probably look something like:

```
describe GpaCalculator do
let(:grades) { [] }
let(:student) { instance_double('Student', grades: grades) }
subject { GpaCalculator.new(student) }
it 'calculates one A to be 4.0' do
grades << 'A'
expect(subject.calculate).to eq(4.0)
end
it 'calculates one B to be 3.0' do
grades << 'B'
expect(subject.calculate).to eq(3.0)
end
it 'calculates one A and one B to be 3.5' do
grades << 'A'
grades << 'B'
expect(subject.calculate).to eq(3.5)
end
end
```

Voilà!

Remember, although your tests aren't production code and don't run your business, they're still a critical part of your business. If they're hard to read, modify, or add to, then development will suffer. Be on the lookout for ways to refactor them and make them more maintainable.

[1] Although this article uses RSpec and Ruby as an example, the idea presented here should be applicable to other languages and their respective test frameworks.

[2] For the sake of the example, we inject `Student`

into the `GpaCalculator`

here. A better approach would be to simply pass the student's grades into the `GpaCalculator`

, and completely eliminate the dependency of `GpaCalculator`

on `Student`

. With this design your `GpaCalculator`

stands alone and is usable in other places of your code where you don't necessarily have a `Student`

object in your hands.

[3] instance_doubles, a.k.a verifying doubles, were introduced in RSpec 3 and provide some safety against stubbing methods that don't actually exist.