Testing your Rails APIs with Airborne

Nếu bạn sử dụng Rails để xây dựng REST API, và bạn không muốn số lần Developer phàn nàn rằng một endpoint không hoạt động tăng lên thì chính xác bài viết này dành cho bạn.

Airborne là một API testing Framework cho phép bạn viết test cho các API được xây dựng bằng Ruby theo một cách rất trực quan.

Vì vậy, trong bài đăng này, tôi sẽ xuyên suốt trên tất cả các khía cạnh khác nhau của việc sử dụng Airborne với Rails mà nó còn mơ hồ với tôi trước tiên. Ngoài những điều tôi giải thích ở đây, mọi thứ khác về cách sử dụng Airborne cũng được mô tả trong Document của nó .

Cài đặt

Rất đơn giản, add gem vào gem file

group :development, :test do
  gem 'rspec-rails', '~> 3.5'
end
group :test do
  gem 'airborne'
end

Chạy bundle install để cài đặt gem.

Cách sử dụng

Giới thiệu

Nhìn chung, trong ứng dụng Rails REST API( không sử dụng các công cụ như Grape), các endpoint của bạn sẽ trỏ tương ứng tới các action trong Controller. Ví dụ, nếu bạn có một controller tickets_controller.rb sử dụng để trả lại list tất cả các ticket, tạo ticket và edit ticket. API test của bạn sẽ nằm trong thư mục /spec/controllers/tickets_controller_spec.rb. Có lẽ quy tắc này quá quen thuộc với Developer mà đã từng viết qua test Rails rồi.

Tạo request

require 'rails_helper'

RSpec.describe TicketsController, :type => :controller do
  describe 'GET index' do
    it 'returns correct types' do
      get :index
      expect_json_types(foo: :string)
    end
  end
end

Đoạn test trên tạo 1 request GET trỏ tới hàm index trong TicketsController và kiểm tra xem respone đó có chứa giá trị foo dạng string hay không. Ví dụ trên quá đơn giản và dễ hiểu phải không.

Tham số truy vấn, requestion body và request header

Nếu các bạn đã đọc Airborne documentation sẽ nhận ra rằng tài liệu không chỉ rõ cách truyền tham số truy vấn(query parameters) hoặc request body khi test một Controller. Tất cả những gì chúng ta cần phải làm là truyền tất cả mọi thứ như là tham số thứ 2 request.

describe 'POST create' do
  it 'returns correct types' do
    body = {'subject' => 'Hey', 'body' => 'Testbody'}
    post :create, body
    expect_status(201)
  end
end

Hoặc trong trường hợp tham số truy vấn/url:

it 'returns correctly status filtered tickets' do
  status_filter = Ticket.statuses.keys.sample
  query = {'status' => status_filter}
  get :index, query
  expect_status(200)
  expect_json('*', status: status_filter)
end

Nếu bạn phải gửi các tham số Header cùng với các tham số truy vấn, tất cả những gì bạn cần làm là merge chúng vào một hàm băm và truyền chúng như là đối số thứ hai.

it 'returns correctly user filtered tickets' do
  user_id_filter = User.includes(:tickets).where.not(tickets: {id: nil}).sample.id
  query = {'user_id' => user_id_filter}
  query.merge! auth_headers
  get :index, query
  expect_status(200)
  expect_json('*.user', id: user_id_filter)
end

Làm việc với devise_token_auth

Chắc hẳn với mỗi Rails developer thì việc sử dụng devise là không còn lạ lẫm nữa. Devise_token_auth là gem để xác thực API với Rails và nó cung cấp một method đơn giản để tạo auth Header cho User của bạn. .create_new_auth_token. Bạn hầu như phải authenticate rất nhiều request vì vậy tốt hơn là không phải viết code authenticate trong mỗi Controller. Chúng ta có thể làm sạch (DRY) bằng cách add config này vào trước mỗi action spec/rails_helper.rb:

config.before(:all, type: :controller) do
  @user = create(:user)
  @user_auth_headers = @user.create_new_auth_token
end

Đoạn code trên nhìn có vẻ không đơn giản, trước khi tất cả các test trong một Controller sẽ tạo các Header xác thực mới cho người dùng của bạn và bạn có thể truyền nó như là đối số thứ hai trong request của bạn để authenticate nó.

it 'returns only tickets that belong to logged in user' do
  get :index, @user_auth_headers
  expect_status(200)
  expect_json('*.user', id: @user.id)
end

Airborne API

Airborne cung cấp những phương thức sau đây để cho phép bạn kiểm tra cấu trúc, giá trị và kiểu dữ liệu của các phần tử trong phản ứng JSON API của bạn.

  • expect_json_types: Kiểm tra các loại giá trị thuộc tính JSON được trả về. Bạn có thể xem thêm các loại dữ liệu ở đây .
  • expect_json: Kiểm tra giá trị của các giá trị thuộc tính JSON được trả về.
  • expect_json_keys: Kiểm tra sự tồn tại của các key được chỉ định trong đối tượng JSON.
  • expect_json_sizes: Kiểm tra size của các giá trị thuộc tính JSON trả về, đúng cả trong trường hợp response là array.
  • expect_status: Kiểm tra mã trạng thái HTTP được trả về.
  • expect_header: Kiểm tra Header trong response.
  • expect_header_contains: Kiểm tra xem Header có chưá 1 element hay không.

Những điều trên đây chỉ là Basic, nếu các bạn muốn tìm hiểu thêm hãy xem trên Document