Skip to content

Instantly share code, notes, and snippets.

@chaomao
Last active July 25, 2016 08:32
Show Gist options
  • Save chaomao/29a67c5fa9f78a4e61a5 to your computer and use it in GitHub Desktop.
Save chaomao/29a67c5fa9f78a4e61a5 to your computer and use it in GitHub Desktop.

RSpec Style Guideline

Please follow this guideline to refine your rspec, make sure code is better after you modify anything

use :type and Rspec in declaration

RSpec.describe Api::UsersController, type: :controller do
	...
end

there are also some other types

  • Model: type: :model
  • Controller: type: :controller
  • Request: type: :request
  • Feature: type: :feature
  • View: type: :view
  • Helper: type: :helper
  • Mailer: type: :mailer
  • Routing: type: :routing

add render_views to render data

if you want to verify render results, like json or HTML returned by controller, you need call render_views methods at very beginning of your test.

RSpec.describe Api::UsersController, type: :controller do
	render_views
end

use url to describe action test

It will be more clear if you can use HTTP method and URL to describe action test instead of action name

# recommend
describe 'get /api/users/:user_id' do
	...
end

# not recommand
describe '#get' do
	...
end

use let instead of instance variable

let is a method to help us prepare test data, it will create data unless you call it.

# recommend
it 'create user' do
	user
end
let(:user) {...}

# not recommend
it 'create user' do
	@user
end

before { @user = User.create }

prepare current_user in test

In controller test, it is important to know who is current_user. Please make sure current_user is the right people with right permission for a specific test.

it 'get users' do
	allow(controller).to receive(:current_user).and_return(student)
end

let(:student)

prase json to symbol key hash

It's easier to parse json to symbol key hash when you verify json in test.

 # {name: 'Harry Potter'}, recommend
JSON.parse(response.body, symbolize_names: true)

# or call json_resonse method in model_helper.rb, recommend
let(:json) { json_response(response) }

# {'name' => 'Harry Potter'}, not recommend
JSON.parse(response.body) 

verify response code and response keys

HTTP code and response keys are very important for a response, we should always make sure they are verified. If there are more test in same action test, you don't need verify http code and json keys every time, however you need to make sure http code and json keys are verified once.

describe 'get /api/users' do
	it 'get all admin' do
		...
		expect(response).to have_http_status(:ok)
		expect(json).to match(name: 'harry', gender: 'female')
	end
	
	it 'get all students' do
		
	end
end
let(json) {...}

split test into three parts

It will make test code more readable if split test into: prepare data, do some action, and verify.

# add new line to split
it 'reset password' do
	user = User.create
	
	user.reset_password
	
	expect(user.password).to eq('old_password')
end

#or you can follow this way
it 'reset password' do
	user.reset_password
	
	expect(user.password).to eq('old_password')
end

let(:user) { User.create }

put before and let after test code

before and let is some step to prepare data, we should always focus test code at first glance.

Rspec.describe 'UsersController' do
	describe 'get /api/users' do
		...
	end
	
	describe 'put /api/users/:id' do
		...
	end
	
	before { ... }
	let(:user) { ... }
end

use match to verify

match is much powerful and flexible for verify, it can return more accurate error message when something went wrong. You can read this for detail

# recommend
it 'user list' do
	...
	expect(json).to match([
		a_hash_including(name: 'Harry'),
		a_hash_including(name: 'Snape'),
	])
end

#not recommend
it 'user list' do
	...
	expect(json.length).to eq(2)
	expect(json[0]).to include(name: 'Harry')
	expect(json[1]).to include(name: 'Snape')
end

#other

use found?, valid?, truthy?

We can use these helper method to make our code more readable.

# will return 404 if not found
found?(@user = User.find(params[:id])) do
	render :index, status: :ok
end

# verify model object only, return 400 and error message if invalid
valid?(@user) { render :index, status: :ok }

# verify value is truthy, return 400 with customized error message if false
truthy?(@user.update(params), 'error message') do
	render :index, status: :ok
end

do not copy and paste code without your brain

Personally I don't recommend copy-paste code, if you really want to do that, please pay attention to following things.

  • try to refactor the code you want to copy, maybe you don't need copy after refactor
  • read paste code line by line to make sure that is exactly what you want.
  • slap your face if you create bug because you just copy and paste but didn't read it

better and cleaner after modify code

Please make sure you clean the house before you leave, make code better and cleaner after you modify it.

add more validation on important active model

Models like Rubric and Template are very important in our system, please do add more validation if you modify atrribute of that model

prepare the more meaningful fake data in system

If you may need look all specs in our system

  • Modify model attribute
  • Modify model validator

Remember, if you think prepare meaningful fake data is hard, our qa have to test harder after you finish development, do not leave your shit to other team members!!!

test enough in your spec

  • controller test, verify http status code, response result and model created/deleted/changed
  • model test, verify atributed changed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment