How to write better rspec

  • How to describe your methods

Hãy rõ ràng về phương pháp bạn viết describe. Ví dụ, sử dụng documentation convention Ruby của "." (Hoặc: 😃 khi đề cập đến tên của một phương thức của lớp và # khi đề cập đến tên của một instance method's name. Bad example:

describe 'the authenticate method for User' do
describe 'if the user is an admin' do

Good example:

describe '.authenticate' do
describe '#admin?' do
  • Use contexts

Contexts là một phương pháp mạnh mẽ để làm cho test của bạn rõ ràng và được tổ chức tốt. Về lâu dài việc sử dụng context sẽ giúp cho test của bạn dễ đọc hơn. Bad example:

it 'has 200 status code if logged in' do
  expect(response).to respond_with 200
end
it 'has 401 status code if not logged in' do
  expect(response).to respond_with 401
end

Good example:

context 'when logged in' do
  it { is_expected.to respond_with 200 }
end
context 'when logged out' do
  it { is_expected.to respond_with 401 }
end
  • Single expectation test

Sử dụng 'one expectation'" được thể hiện rộng rãi hơn là "mỗi test chỉ nên thực hiện một assertion". Điều này giúp bạn tìm ra lỗi có thể xảy ra, đi trực tiếp vào test fail và để làm cho code của bạn dễ đọc hơn. Trong specs đơn vị cô lập, bạn muốn mỗi ví dụ để chỉ định một (và chỉ một) hành vi. Nhiều expectations trong cùng một ví dụ là một tín hiệu mà bạn có thể chỉ định nhiều hành vi. Dù sao, trong những test không bị cô lập (ví dụ những bài tích hợp với một DB, một webservice bên ngoài, hay những test cuối cùng), bạn sẽ đạt được hiệu suất lớn để thực hiện cùng một thiết lập lặp đi lặp lại, Một kỳ vọng khác nhau trong mỗi test. Trong những loại thử nghiệm chậm hơn, tôi nghĩ rằng nó tốt để chỉ định nhiều hơn một hành vi bị cô lập. Good example(ISOLATED):

it { is_expected.to respond_with_content_type(:json) }
it { is_expected.to assign_to(:resource) }

Good example(NOT ISOLATED):

it 'creates a resource' do
  expect(response).to respond_with_content_type(:json)
  expect(response).to assign_to(:resource)
end
  • Test all possible cases

Thử nghiệm là một thực hành tốt, nhưng nếu bạn không kiểm tra các trường hợp phụ, nó sẽ không hữu ích. Kiểm tra trường hợp hợp lệ, phụ và không hợp lệ. Ví dụ, hãy xem xét hành động sau đây.

DESTROY ACTION

before_filter :find_owned_resources
before_filter :find_resource

def destroy
  render 'show'
  @consumption.destroy
end

Lỗi tôi thường thấy nằm trong test chỉ cho dù tài nguyên đã được xoá. Nhưng có ít nhất hai trường hợp phụ: khi tài nguyên không được tìm thấy và khi nó không thuộc sở hữu của user thực hiện hành động xoá. Vậy nên bạn nên suy nghĩ đến tất cả các trường hợp đầu vào và test chúng. Good example:

describe '#destroy' do

  context 'when resource is found' do
    it 'responds with 200'
    it 'shows the resource'
  end

  context 'when resource is not found' do
    it 'responds with 404'
  end

  context 'when resource is not owned' do
    it 'responds with 404'
  end
end
  • Expect vs Should syntax

On new projects always use the expect syntax. Bad example:

it 'creates a resource' do
  response.should respond_with_content_type(:json)
end

Good example:

it 'creates a resource' do
  expect(response).to respond_with_content_type(:json)
end

Configure the Rspec to only accept the new syntax on new projects, to avoid having the 2 syntax all over the place. Good example:

# spec_helper.rb
RSpec.configure do |config|
  # ...
  config.expect_with :rspec do |c|
    c.syntax = :expect
  end
end

On one line expectations or with implicit subject we should use is_expected.to. Bad example:

context 'when not valid' do
  it { should respond_with 422 }
end

Good example

context 'when not valid' do
  it { is_expected.to respond_with 422 }
end

reference:
https://github.com/reachlocal/rspec-style-guide http://www.betterspecs.org/ ,