What is wrong with this test?
I'll write it using plain Ruby, but I took this from a Ruby on Rails project.
What if you have some test like this:
describe User do
it "should upcase its own name" do
user = User.new
user.name = "alice"
user.upcase_name!
expect(user.name).to eq "ALICE"
end
end
What do you thing is wrong with it?
What if I show you this:
describe User do
context "upcase_name!" do
subject { User.new }
before { subject.name = "alice" }
it do
expect { subject.upcase_name! }.to change { subject.name }.to("ALICE")
end
end
end
Is it better? Is it more difficult to read?
Feel free to comment below about all this, I will just add somethings:
Always have a subject
It is expected that all test case (aka, it
) have a subject
.
It is the main reason for this test. It is your target.
The first thing when I look to a test to understand it is looking for a target.
If your subject does not use the standard new
/initialize
create it using a subject { }
block. It will be a way easier to read.
Your subject
must be the same type of your top describe
Let's say that your describe
is describe User
, you are supposed to test a User
class or one instance. Don't mess with this thing.
Try to find the behavior of your code
Ok, ok, ok, let's not talk about TDD vs BDD, Test::Unit vs RSpec. Keep reading.
The behavior of your code is:
When you call
upcase_name!
some change happens to user's name
So, write it in your test. Keep reading.
If you have this code:
def name=(name)
@name = name.upcase
end
And (I don't know why) also you have upcase_name!
you need two tests.
With this code, the rewritten example will fail, because in my test I explicitly tell that it changes only when I call upcase_name!
.
With this name=
method it is expected to have something like this:
describe User do
it "should always store name as upcase" do
subject.name = "alice"
expect(subject.name).to eq "ALICE"
end
end
Bonus
Take a look at the output of rspec --format documentation
:
$ rspec spec/foo_spec.rb --format documentation
User
should upcase its own name
#upcase_name!
should change `subject.name` to "ALICE"
should always store name as upcase
Finished in 0.02947 seconds (files took 0.16243 seconds to load)
3 examples, 0 failures