12/08/2018, 13:19

[Rails] [TDD] Hướng dẫn viết feature testing

Bài viết này hướng dẫn cách viết feature testing cho 1 rails app Vậy feature testing là gì? Định nghĩa chi tiết thì các bạn đọc ở đây nhưng hiểu nôm na thì feature testing nghĩa là thực hiện 1 công việc test cho 1 chức năng (feature) như 1 người test. Để minh họa cho các bạn dễ hiểu, thì ...

Bài viết này hướng dẫn cách viết feature testing cho 1 rails app

  • Vậy feature testing là gì?

Định nghĩa chi tiết thì các bạn đọc ở đây nhưng hiểu nôm na thì feature testing nghĩa là thực hiện 1 công việc test cho 1 chức năng (feature) như 1 người test.

Để minh họa cho các bạn dễ hiểu, thì khi chạy feature testing các bạn sẽ có kết quả như video sau

https://www.youtube.com/watch?v=GdIgVqJHbak&feature=youtu.be

Như vậy nghĩa 1 test case feature test đã bao gồm khá nhiều test case unit test (mặc dù k phải là tất cả).

Ví dụ bạn test việc fill vào form sau

Screen Shot 2016-05-09 at 9.45.42 PM.png

thì các việc cần làm là

  • Visit page http://localhost/books
  • Fill fields
  • Click button submit
  • Expect result

Phân tích 1 chút.

  • Ở bước 1, visit page thì k có gì, bỏ qua nhe

  • Ở bước 2. Fill fields. Đơn giản là điền các giá trị cho các fields

  • Ở bước 3. Ở đây có thể xảy ra các trường hợp (tùy theo fill ở bước 2):

    • blank title, author hay price
    • title, author invalid (quá dài, ngắn, hoặc k đúng format... tùy theo validations của các bạn) hay price không đúng (ví dụ bạn nhập vào text hay ký tự đặc biệt...)
    • và cuối cùng là all fields is valid.
  • Bước 4. Kết quả kỳ vọng, sẽ phụ thuộc vào từng trường hợp ở bước 2

    • Ví dụ blank title thì màn hình thông báo phải có đoạn text "title can't blank" và current_path thay đổi
    • Còn trong trường hợp valid thì mà hình có thông báo "Create book successfully" và current_path sẽ chuyển về book_path(:id)
  • Tao project demo (mình dùng scaffold)
    rails new sample_app
  • Tạo 1 scaffold book gồm có title:string, author: string, price: float
    rails g scaffold book title:string author:string price:float
  • OK, lúc này view http://localhost:3000/books/new thì các bạn có form như hình trên

  • Trong Gemfile

    group :development, :test do
      gem 'byebug'
      gem 'rspec-rails'
      gem 'capybara'
      gem "selenium-webdriver"
    end

Việc setup cho từng gem, các bạn xem trên github dùm mình.

  • Trong model book.rb, giả sử mình có validation cho title
    class Book < ActiveRecord::Base
      validates :title, presence: true, length: { maximum: 50 }
    end
  • Việc setup tới đây coi như hoàn tất.

Sau đó các bạn cần list ra các test cases có thể xảy ra. Ở ví dụ trên thì có thể

    scenario "valid input" do
    end

    scenario "missing title" do
    end

    scenario "title too long" do
    end
    ...

Trên đây mình chỉ đưa ra 1 số test case. Tùy theo validation và theo chương trình của các bạn mà lượng test case sẽ khác đi.

Các bạn tạo 1 folder features trong sample_app/spec

Trong folder features tạo 1 file create_book_spec.rb (sample_app/spec/features/create_book_spec.rb) với nội dung

    require "rails_helper"

    RSpec.feature "Create new book", type: :feature do
      before do
        visit new_book_path
      end
    end

Tiếp theo, ta cùng implement với từng test case cụ thể.

Trường hợp 1.

    scenario "valid input" do
      fill_in "book[title]", with: "god father"
      click_button "Create Book"
      expect(page).to have_text("Book was successfully created.")
    end

Ở đây book[title] là name của 2 trường title trong form. Các bạn có thể set name theo ý mình trong code. Tuy nhiên, mình khuyên nên để name mặc định rails sinh ra cho mình.

Screen Shot 2016-05-09 at 10.03.47 PM.png

Với các trường hợp còn lại, các bạn làm tương tự, và file create_book_spec.rb cuối cùng sẽ như sau

    require "rails_helper"

    RSpec.feature "Create new book", type: :feature do
      before do
        visit new_book_path
      end

      scenario "valid input" do
        fill_in "book[title]", with: "god father"
        click_button "Create Book"
        expect(page).to have_text("Book was successfully created.")
      end

      scenario "mising title" do
        click_button "Create Book"
        expect(page).to have_text("Title can't be blank")
      end

      scenario "title too long", js: true do
        fill_in "book[title]", with: "a" * 51
        click_button "Create Book"
        expect(page).to have_text("Title is too long (maximum is 50 characters)")
      end
    end

Tuy nhiên khi test thế này, ví dụ khi các bạn có 1 field, có value được update bằng jQuery, phụ thuộc theo giá trị các fields khác thì giá trị của field đó sẽ không được cập nhật, do chương trình test hiện tại không chạy js.

Các bạn fix bằng cách thêm js: true vào trước test case nào có dùng tới jQuery

    scenario "valid input", js: true do
    end

và lúc này, khi chạy test, các bạn sẽ thấy 1 điều khá thú vị là rspec sẽ tự động mở trình duyệt, fill vào các field, click button Submit và cho các bạn view page result.

Qua ví dụ trên, các bạn có thể viết feature test cho chương trình của mình. Việc viết feature test giúp các bạn có thể test chương trình như 1 tester, tuy nhiên nó chỉ giúp bạn hiểu rõ logic dự án và phần nào tránh được bugs chứ không thể thay thế hoàn toàn tester được.

Trên đây mình chỉ demo 1 ví dụ đơn giản, còn các controls như checkboxs, dropdowns... việc select hay fill những fields đó, các bạn tự tìm hiểu thêm.

Việc viết feature test không khó, khó là bạn phải cover được nhiều nhất case có thể xảy ra. Điều này thì phải nhờ đến tester rồi             </div>
            
            <div class=

0