I talked at Omotesando.rb(Ruby meetup in Japan) on the other day.
Surprisingly, Matz attended on that meetup.
At there, Matz give a comment to RSpecZ, a gem for RSpec.
"You should make a Pull Request in RSpec repository."
I didn't make Pull Request yet.
But I noticed that a lot of people are interesting to RSpecZ.
So, I introduce RSpecZ here first.
What is RSpecZ?
RSpec has a big problem.
RSpec codes are Long (means Hard to review).
RSpecZ is trying to solve this problem.
It has methods of extending let
, context
and subject
now.
I want RSpecZ to be a Guide of RSpec in the future so I will make generators
, code analyzer and formatter
and something like that.
I show you RSpecZ effectiveness with Image.
This image is created by applying RSpecZ to a rspec code from a project I participated.
I will tell you how this can be happened.
Basic Features
Extend context
RSpec's context
method is flexible and versatilie.
In the other words, it tends to be redundant and hard to understand.
For example,
context 'When phone_number is 090-1234-5678' do
let(:phone_number) { '090-1234-5678' }
it { expect(phone.save).to be_truthy }
end
( 090-1234-5678
is valid phone number in Japan.)
This context
is redundant. Because context
and let
show same thing.
But this will be happened very often when we use RSpec.
And one more problem.
RSpec's context
has no meaning by itself. context
first argument show state of the context.
Without first argument, we cannot know what kind of context it make.
The above code means that set valid phone number to phone_number
variable(let).
RSpecZ make this code simple.
set_valid(:phone_number, '090-1234-5678') do
it { expect(phone.save).to be_truthy }
end
set_valid
method combine context
and let
.
And method name can say valid
value will be put to phone_number
.
Reviewer can know valid
specs will be written in the block when he read the method name.
And lines of code become short.
With RSpecZ you can write multiple valid cases Very Easily.
set_valids(:phone_number, '090-1234-5678', '080-9566-8466', '070-4567-8901', '09045678945' ) do
it { expect(phone.save).to be_truthy }
end
Same code with RSpec will be
%w[090-1234-5678 080-9566-8466 070-4567-8901 09045678945].each do |phone_number|
context "When phone_number is #{phone_number}" do
let(:phone_number) { phone_number }
it { expect(phone.save).to be_truthy }
end
end
You can know how easy to review RSpecZ codes with comparing these codes.
RSpecZ has not only set_valid
but also set_invalid
for case of invalid
value set.
Choose correct method to help reviewer review codes.
Extend let
When you write RSpec, you may write this kind of codes,
let(:name) { 'test-name' }
let(:phone_number) { '090-1234-5678' }
let(:address) { 'test-address' }
let(:params) { {
name: name,
phone_number: phone_number,
address: address
} }
subject { get '/api/test', params: params }
This let
s can help you to change a part of context from default value.
You can write flexible specs.
However, this codes are also redundant.
RSpecZ has create_params
method.
let(:name) { 'test-name' }
let(:phone_number) { '090-1234-5678' }
let(:address) { 'test-address' }
create_params :name, :phone_number, :address
subject { get '/api/test', params: params }
This code has same meaning.
create_params
define params
let
with using defined let
s.
Actually, create_params
define let
with test-xxx
characters if the param is not defined yet.
So, below code also has same meaning.
let(:phone_number) { '090-1234-5678' }
create_params :name, :phone_number, :address
subject { get '/api/test', params: params }
I will implement more useful let
methods in the future.
Other features
RSpecZ has some other useful methods.
Please check github repository if you are interested.
https://github.com/RSpecZ/RSpecZ
Mesurement effectiveness of RSpecZ
I check the effectiveness of RSpecZ with compare projects.
One is a rails project without RSpecZ (I participate before) and the other one is a rails project with RSpecZ (I currently participate).
Premises
- These projects are completely different. They has different business logics.
- I developed code base of both of projects. ( Basic code styles are same)
- Project with RSpecZ is just started(3 months) so codes are less.
- We use other features in project with RSpecZ which RSpecZ not yet have. So, not only RSpecZ feature make codes shorter.
Results
Lines of RSpec | Num of tests | |
---|---|---|
Project with RSpecZ | 2183 | 1223 |
Project without RSpecZ | 20023 | 5143 |
Lines of RSpec: Total lines of request_spec
and support
files.
Num of tests: Number of examples.
Conclusion
RSpecZ can make RSpec codes HALF.
(CANNOT compare just RSpecZ features because of Premises)
This is may not accurate but we can know the power of RSpecZ from result.
At last
This article introduce RSpecZ features.
RSpecZ is just started a few months before.
We have very few commiters.
Please give comments if you are interested.
Top comments (1)
In contrast, a guy from thoughtbot team with 'telling a story' mindset encourages developer should not afraid to write redundant code as long as it is to make clearer documentation.
But actually it seems interesting and promising. It will be nice and handy be to seeing
set_valid
,set_invalid
, orcreate_params
as part of the default Rspec feature. Hope Rspec or RspecZ future will make test practice easier to understand.