Ruby on Rails 2.1 - Kiểm thử đơn vị

Giới thiệu

Trước khi tiếp tục, chúng ta hãy xem nhanh một vài định nghĩa -

  • Các Tests- Chúng là các ứng dụng thử nghiệm tạo ra kết quả nhất quán và chứng minh rằng ứng dụng Rails thực hiện những gì nó được mong đợi. Các thử nghiệm được phát triển đồng thời với ứng dụng thực tế.

  • Các Assertion- Đây là một dòng mã đánh giá một đối tượng (hoặc biểu thức) cho kết quả mong đợi. Ví dụ - Giá trị này = giá trị đó? Đối tượng này là nil?

  • Các Test Case- Đây là một lớp kế thừa từ Test :: Unit :: TestCase chứa một chiến lược kiểm thử bao gồm các bài kiểm tra liên quan đến ngữ cảnh.

  • Các Test Suite- Đây là một tập hợp các trường hợp thử nghiệm. Khi bạn chạy một bộ thử nghiệm, nó sẽ lần lượt thực hiện từng thử nghiệm thuộc về nó.

Kiểm tra đường ray

Khi bạn chạy tập lệnh script trợ giúp / tạo để tạo bộ điều khiểnmô hình , Rails sẽ tạo một khuôn khổ cho các bài kiểm tra đơn vị và chức năng. Bạn có thể nhận được phạm vi kiểm tra khá tốt bằng cách điền vào khung các bài kiểm tra cho chức năng bạn viết. Có hai điểm quan trọng cần kiểm tra trong một ứng dụng Rails:

  • Kiểm tra các mô hình

  • Kiểm tra bộ điều khiển

Hướng dẫn này sẽ trình bày ngắn gọn cả hai thử nghiệm. Vì vậy, hãy tạo một testapp để hiểu khái niệm.

C:\ruby> rails -d mysql testapp

Thiết lập cơ sở dữ liệu

Cho đến nay, chúng tôi chỉ sử dụng cơ sở dữ liệu phát triển của ứng dụng Rails, nhưng bây giờ bạn cần đảm bảo rằng cơ sở dữ liệu thử nghiệm cũng được tạo và các phần thích hợp của tệp config / database.yml của bạn được thiết lập chính xác.

Hãy tạo cơ sở dữ liệu phát triển và thử nghiệm như sau:

mysql> create database testapp_test;
Query OK, 1 row affected (0.01 sec)

mysql> create database testapp_development;
Query OK, 1 row affected (0.01 sec)

mysql> use testapp_test;
Database changed

mysql> grant all privileges on testapp_test.* 
   to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Định cấu hình database.yml

Định cấu hình config / database.yml của bạn như sau:

development:
   adapter: mysql
   encoding: utf8
   database: testapp_development
   username: root
   password: password
   host: localhost
test:
   adapter: mysql
   encoding: utf8
   database: testapp_test
   username: root
   password: password
   host: localhost
production:
   adapter: mysql
   encoding: utf8
   database: testapp_production
   username: root
   password: password
   host: localhost

Tạo di chuyển

Giả sử bạn có một bảng chứa sách, bao gồm tên sách, giá và một mô tả nhỏ. Quá trình di chuyển sau đây thiết lập bảng này:

testapp > ruby script/generate migration books

Bây giờ sửa đổi tệp testapp / db / migrate / 20080616170315_books.rb như sau:

class Books < ActiveRecord::Migration
   def self.up
      create_table :books do |t|
         t.string     :title, :limit => 32, :null => false
         t.float      :price
         t.text       :description
         t.timestamp  :created_at
      end
   end
  
   def self.down
      drop_table :books
   end
end

Bây giờ hãy chạy quá trình di chuyển như sau:

testapp > rake db:migrate

Điều này sẽ tạo ra booksbảng trong cơ sở dữ liệu testapp_development. Sau đó, chúng tôi cần thiết lập cơ sở dữ liệu thử nghiệm của bạn bằng lệnh rake như sau:

C:\ruby\testapp > rake db:test:clone_structure

Điều này sẽ sao chép các testapp_development cơ sở dữ liệu vào testapp_test cơ sở dữ liệu. Nó có nghĩa là bất cứ thứ gì bạn có trong cơ sở dữ liệu phát triển, bây giờ bạn cũng sẽ có cùng một dữ liệu trong cơ sở dữ liệu thử nghiệm.

Thử nghiệm Mô hình

Khi bạn tạo một mô hình bằng tập lệnh tạo, Rails cũng tạo một tập lệnh thử nghiệm đơn vị cho mô hình trong thư mục thử nghiệm. Nó cũng tạo ra một vật cố định , một tệp YAML chứa dữ liệu thử nghiệm để được tải vào cơ sở dữ liệu testapp_test. Đây là dữ liệu mà các bài kiểm tra đơn vị của bạn sẽ chạy -

testapp > ruby script/generate model Book
   exists  app/models/
   exists  test/unit/
   exists  test/fixtures/
   create  app/models/book.rb
   create  test/unit/book_test.rb
   create  test/fixtures/books.yml
   create  db/migrate
   create  db/migrate/20080616164236_create_books.rb

Khi bạn viết mã trong các lớp mô hình, bạn sẽ viết các bài kiểm tra tương ứng trong các tệp này. Vì vậy, hãy tạo hai bản ghi sổ kiểm tra bằng YAML trong test / fixtures / books.yml như sau:

perl_cb:
   id: 1
   title: 'Ruby Tutorial'
   price: 102.00
   description : 'This is a nice Ruby tutorial'
java_cb:
   id: 2
   title: 'Java Programming'
   price: 62.00
   description : 'Java Programming for the beginners'

Bây giờ hãy thay thế mã hiện có trong tệp kiểm tra đơn vị sách / unit / book_test.rb bằng mã sau:

require File.dirname(__FILE__) + '/../test_helper'

class BookTest < ActiveSupport::TestCase
   fixtures :books

   def test_book

      perl_book = Book.new :title => books(:perl_cb).title, 
         :price => books(:perl_cb).price,
         :description => books(:perl_cb).description,
         :created_at => books(:perl_cb).created_at

      assert perl_book.save

      perl_book_copy = Book.find(perl_book.id)

      assert_equal perl_book.title, perl_book_copy.title

      perl_book.title = "Ruby Tutorial"

      assert perl_book.save
      assert perl_book.destroy
   end
end

Cuối cùng, chạy phương pháp kiểm tra như sau:

testapp > ruby test/unit/book_test.rb

Đây là kết quả của việc chạy trường hợp thử nghiệm thành công -

testapp > ruby test/unit/book_test_crud.rb 
Loaded suite ./test/unit/book_test
Started
.
Finished in 0.0625 seconds.

1 tests, 4 assertions, 0 failures, 0 errors

Hãy phân tích những gì đã xảy ra ở đây -

  • Phương thức BookTest bắt đầu bằng cách tạo một đối tượng Sách mới bằng cách sử dụng tiêu đề và các trường khác từ bản ghi đầu tiên trong text fixture / books.yml. Đối tượng kết quả được lưu trữ trong biến cá thể perl_book.

  • Kiểm tra xác nhận đầu tiên rằng việc lưu đối tượng Sách đã thành công.

  • Tiếp theo, đối tượng book được truy xuất bằng phương thức find và được lưu trữ trong một biến thể hiện khác có tên là perl_book_copy. Sự thành công của việc truy xuất này được kiểm tra trong khẳng định tiếp theo, so sánh tên sách của cả hai đối tượng sách. Tại thời điểm này, chúng tôi đã kiểm tra khả năng tạo và đọc bản ghi cơ sở dữ liệu.

  • Giải pháp kiểm tra việc cập nhật bằng cách gán một tiêu đề mới cho đối tượng được lưu trữ trong perl_book và sau đó xác nhận rằng việc lưu thay đổi thành công.

  • Cuối cùng, khả năng phá hủy một đối tượng Sách được thử nghiệm.

Đây là cách chúng tôi có thể kiểm tra các Mô hình Rails của mình.

Kiểm tra bộ điều khiển

Kiểm tra bộ điều khiển còn được gọi là functional testing. Kiểm tra chức năng kiểm tra các loại chức năng sau của bộ điều khiển:

  • Phản hồi có được chuyển hướng như mong đợi không?
  • Mẫu mong đợi có được hiển thị không?
  • Định tuyến có như mong đợi không?
  • Phản hồi có chứa các thẻ mong đợi không?

Khung công tác Rails hỗ trợ năm loại yêu cầu -

  • get
  • post
  • put
  • head
  • delete

Để viết một bài kiểm tra chức năng, bạn cần phải mô phỏng bất kỳ loại yêu cầu HTTP nào trong năm loại yêu cầu HTTP mà bộ điều khiển của bạn sẽ xử lý.

Loại yêu cầu "get" và "post" được sử dụng phổ biến nhất trong thử nghiệm bộ điều khiển. Tất cả các phương thức này có bốn đối số -

  • Hành động của bộ điều khiển
  • Một băm tùy chọn của các tham số yêu cầu
  • Hàm băm phiên tùy chọn
  • Một băm flash tùy chọn

Trong hướng dẫn này, chúng ta sẽ xem cách sử dụng getphương pháp để kiểm tra bộ điều khiển của chúng tôi. Bạn có thể kiểm tra phần còn lại của các phương pháp theo cách tương tự.

Khi bạn tạo một bộ điều khiển bằng tạo, Rails sẽ tạo một tập lệnh kiểm tra chức năng cho bộ điều khiển như sau:

testapp > ruby script/generate controller Book
   exists  app/controllers/
   exists  app/helpers/
   create  app/views/book
   exists  test/functional/
   create  app/controllers/book_controller.rb
   create  test/functional/book_controller_test.rb
   create  app/helpers/book_helper.rb

Khi bạn viết mã trong các lớp bộ điều khiển, bạn sẽ viết các bài kiểm tra tương ứng trong các tệp này. Trước đó, hãy xác định danh sách chức năng bộ điều khiển , hiển thịtìm kiếm bên trongapp/controllers/book_controller.rb như sau -

class BookController < ApplicationController
   def list
      @book_pages, @books = paginate :books, :per_page => 10
   end

   def show
      @book = Book.find(params[:id])
   end

   def search
      @book = Book.find_by_title(params[:title])
      if @book
         redirect_to :action => 'show', :id => @book.id
      else    
         flash[:error] = 'No such book available'
         redirect_to :action => 'list'
      end
   end
end

NOTE - Bạn sẽ cần hai mẫu chế độ xem cho showvà phương pháp danh sách . Bạn có thể xác định các chế độ xem đó và kiểm tra chúng, nhưng ngay bây giờ, chúng tôi sẽ tiến hành mà không xác định các chế độ xem đó.

Bây giờ chúng ta hãy sử dụng lại vật cố định thử nghiệm của chúng tôi trong test/fixtures/books.yml tập tin như sau -

perl_cb:
   id: 1
   title: 'Ruby Tutorial'
   price: 102.00
   description : 'This is a nice Ruby tutorial'
java_cb:
  id: 2
  title: 'Java Programming'
  price: 62.00
  description : 'Java Programming for the beginners'

Thêm dòng sau test_search_booktest_search_not_found phương pháp để test / functional / book_controller_test.rb để kiểm tra các chức năng của hành động tìm kiếm Kiểm Soát Tài Chính Sách.

require File.dirname(__FILE__) + '/../test_helper'
require 'book_controller'

# Re-raise errors caught by the controller.
class BookController
   def rescue_action(e) 
      raise e 
   end
end

class BookControllerTest < Test::Unit::TestCase
   fixtures :books
   def setup
      @controller = BookController.new
      @request    = ActionController::TestRequest.new
      @response   = ActionController::TestResponse.new
   end

   def test_search_book
      get :search, :title => 'Ruby Tutorial'
      assert_not_nil assigns(:book)
      assert_equal books(:perl_cb).title, assigns(:book).title
      assert_valid assigns(:book)
      assert_redirected_to :action => 'show'
   end

   def test_search_not_found
      get :search, :title => 'HTML Tutorial'
      assert_redirected_to :action => 'list'
      assert_equal 'No such book available', flash[:error]
   end
end

Bây giờ chạy các trường hợp thử nghiệm của bạn như sau:

testapp > ruby test/functional/book_controller_test.rb

Nó cho kết quả sau:

Loaded suite test/functional/book_controller_test
Started
..
Finished in 0.422 seconds.

2 tests, 7 assertions, 0 failures, 0 errors

Hãy phân tích điều gì đã xảy ra ở đây -

  • Các thiết lập phương pháp là một phương pháp mặc định để tạo các đối tượng điều khiển, yêu cầu, và phản ứng. Chúng sẽ được sử dụng bởi Rails trong nội bộ.

  • Phương pháp thử nghiệm đầu tiên test_search_book tạo ragetyêu cầu hành động tìm kiếm, chuyển vào một tham số tiêu đề .

  • Hai xác nhận tiếp theo xác minh rằng đối tượng Sách đã được lưu trong một biến thể hiện có tên là @book và đối tượng đó vượt qua bất kỳ xác thực Bản ghi Hoạt động nào có thể tồn tại.

  • Xác nhận cuối cùng bên trong phương pháp đầu tiên kiểm tra rằng yêu cầu đã được chuyển hướng đến hành động hiển thị của bộ điều khiển.

  • Phương pháp kiểm tra thứ hai, test_search_not_found , thực hiện một yêu cầu nhận khác nhưng chuyển sang tiêu đề không hợp lệ

  • Kiểm tra xác nhận đầu tiên rằng chuyển hướng đến hành động danh sách đã được đưa ra.

  • Nếu các xác nhận tiếp tục được thông qua, sẽ có một thông báo trong mã băm flash mà bạn có thể kiểm tra bằng khẳng định_equal ..

Để có thêm thông tin về Assertions, vui lòng tham khảo Tài liệu Tiêu chuẩn của Rails .

Sử dụng Rake để kiểm tra

Bạn có thể dùng raketiện ích để kiểm tra các ứng dụng của bạn. Dưới đây là danh sách một số lệnh quan trọng.

  • $rake test - Kiểm tra tất cả các kiểm thử đơn vị và kiểm thử chức năng (và kiểm thử tích hợp, nếu chúng tồn tại).

  • $rake test:functionals- Chạy tất cả các bài kiểm tra chức năng.

  • $rake test:units - Chạy tất cả các bài kiểm tra đơn vị.

  • $rake test:integration - Chạy tất cả các bài kiểm tra tích hợp.

  • $rake test:plugins - Chạy tất cả kiểm tra trong ./vendor/plugins/**/test.

  • $rake test:recent - Chạy kiểm tra các mô hình và bộ điều khiển đã được sửa đổi trong 10 phút qua -

  • $rake test:uncommitted - Đối với các dự án trong Subversion, hãy chạy kiểm tra những thay đổi đã diễn ra trong các mô hình và bộ điều khiển kể từ lần cam kết cuối cùng -