- vừa được xem lúc

Một số lưu ý khi viết test cho Rails

0 0 31

Người đăng: Bùi Văn Thượng

Theo Viblo Asia

1. Giới thiệu

Khi mình đọc lại test case của dự án, có khá nhiều đoạn code dài và rối mắt khi đọc dẫn đến việc bạn phải tốn nhiều thời gian cho việc đọc hiểu code. Hơn thế nữa, việc viết test không theo một quy chuẩn sẽ kiến bạn trở nên lúng túng, không biết sẽ triển khai thêm code test mới ở đâu. Vì thế, mình viết bài này nhắm mục đích giúp các bạn có thêm những lựa chọn hữu ích khi viết code, giúp code trở nên trong sáng, sạch đẹp hơn.

2. Code style

A. Controller

Với controller, việc sắp xếp theo thứ tự method như dưới đây sẽ giúp bạn dễ dàng tìm kiếm, đọc hiểu code hơn.

index
create
show
update
destroy
other actions
private methods

B. Models

Với model

  • Sắp xếp theo bảng chữ cái.
  • Sắp xếp theo thứ tự, ví dụ
class MyModel < ApplicationRecord include DateTime CONSTANT = ... attr_accessor :name belongs_to :animal has_one :dog has_many :feature accepts_nested_attributes_for :foods delegate validates :name enum category: { pug: 0, hasky: 1 } after_destroy :destroy_feature scope :first_scope class << self def method1; end def method2; end end def instance_method1; end private def do_something; end
end

3. Spec, test case

Sau đây là một số lưu ý khi viết test :

1. Viết test case method theo thứ tự như trong models, controller sẽ giúp bạn dễ dàng tìm kiếm và viết thêm mã

RSpec.describe MyModel, type: :model do describe 'associations' do; end describe 'validations' do; end describe 'enums' do; end describe 'callbacks' do describe 'method1' do; end describe 'method2' do; end end ...
end

2. Đưa subject lên đầu method sẽ giúp bạn clear về nội dung viết test

describe 'delete_extended_object' do subject { parent.destroy } ..
end

3. Chỉ khai báo dữ liệu dùng đến trong blocks

BAD let!(:animal) { create :animal, type: 'dog'} let!(:dog1) { create :dog, name: 'abc', age: 2, type: :husky, parent_object: animal } let!(:user_login) { create :user, name: 'user1', is_login: false } let(:return_object1) do animal: { id: 1, type: 'dog' } end let(:return_object2) do user: { id: 1, name: 'user1' }, pet: { id: 1, name: 'abc' } end context 'action 1' do it { expect(response.body).to eq return_object1 } end context 'action 2' do it { expect(response.body).to eq return_object2 } end

Ví dụ, khối context1 chỉ sử dụng dữ liệu animal, nhưng lại tạo dữ liệu cho cả dog1user_login. Tất nhiên, việc viết mã như trên không có gì sai. Tuy nhiên khối mã trên sẽ tốn thêm thời gian để tạo dữ liệu dư thừa mà không sử dụng đến.

GOOD let!(:animal) { create :animal, type: 'dog'} context 'action 1' do let(:return_object1) do animal: { id: 1, type: 'dog' } end it { expect(response.body).to eq return_object1 } end context 'action 2' do let!(:dog1) { create :dog, name: 'abc', age: 2, type: :husky, parent_object: animal } let!(:user_login) { create :user, name: 'user1', is_login: false } let(:return_object2) do user: { id: 1, name: 'user1' }, pet: { id: 1, name: 'abc' } end it { expect(response.body).to eq return_object2 } end

4. Tránh việc gọi method, truy vấn trong response trả về

Không nên

BAD
describe 'PATCH /api/v1/objects' do let!(:animal) { create :animal, type: 'dog'} context 'action 1' do let(:return_object1) do animal: { id: 1, type: animal.type, feature: animal.method_feature } end it { expect(response.body).to eq return_object1 } end
end

Khi gọi đến thuộc tính, method sẽ làm tăng thời gian chạy test case. Không những thế, việc xem lại test case sẽ tốn nhiều thời gian hơn, như phải tìm thuộc tính method sẽ trả ra giá trị nào.

GOOD
describe 'PATCH /api/v1/objects' do let!(:animal) { create :animal, type: 'dog'} context 'action 1' do let(:return_object1) do animal: { id: 1, type: 'dog', feature: 'rescue' } end it { expect(response.body).to eq return_object1 } end
end

5. Định hình cấu trúc trả về để viết test hiệu quả, tránh việc bỏ sót

Khi viết test chúng ta nên định hình các cấu trúc sẽ được trả về, phân chia chúng thành các case . Ví dụ các test case thường sẽ bắt đầu bằng expect nil, sau đó sẽ đến cách case khác.

 context 'if return value is blank' do it 'return nil' do; end it 'return empty array' do; end end context 'if return value is present ' do it 'return integer' do; end it 'return array' do; end end

Tham khảo thêm

Bình luận

Bài viết tương tự

- vừa được xem lúc

Docker: Chưa biết gì đến biết dùng (Phần 3: Docker-compose)

1. Mở đầu. . .

0 0 121

- vừa được xem lúc

Tích hợp VNPAY vào Rails

Xin chào 500 ae năm mới nhé. Tiếp nối câu chuyện về Thanh toán online mà mình có chia sẽ ở 2 bài trước, mọi người chưa đọc thì có thể vào xem ở đây nhé.

1 1 95

- vừa được xem lúc

Tìm hiểu Adapter Pattern trong Rails

. Nếu là một web developer chắc hẳn chúng ta đã không ít lần đọc qua về các Design patterns hay cách áp dụng chúng để làm cho code trở nên hướng đối tượng hơn, dễ đọc, dễ hiểu, dễ maintain, dễ mở rộng, … Các design patterns được áp dụng khá nhiều trong các Rails projects như Service Object, Decorato

0 0 48

- vừa được xem lúc

Sử dụng Searchkick để tìm kiếm thông minh trên Rails và Elasticsearch

Bạn đã bao giờ tự hỏi, ứng dụng web của mình có thể mở rộng quy mô bằng cách học được các từ khóa mà người dùng tìm kiếm? Có giải pháp nào cung cấp công cụ tìm kiếm tự động nhanh chóng với chỉ 1 từ khóa bất kì? Thật may khi có Searchkick và Elasticsearch là các công cụ hỗ trợ công việc tìm kiếm trở

0 0 103

- vừa được xem lúc

Những sai lầm bạn có thể mắc phải khi code Rails

. Chào các bạn, chào các bạn. Đừng vội đóng tab nha.

0 0 47

- vừa được xem lúc

Một số lưu ý cải thiện performance khi làm việc với Rails

Khi làm việc với ruby on rails chắc hẳn chúng ta sẽ làm việc với active record rất nhiều. Tuy nhiên có nhiều điều có thể ta vẫn chưa thực sự hiểu, ví dụ như ActiveRecord execute SQL query như thế nào? Và cũng còn khá nhiều lập trình viên khác cũng không để ý tới điều này.

0 0 111