📅  最后修改于: 2020-10-20 05:22:25             🧑  作者: Mango
在继续之前,让我们快速看一下一些定义-
测试-它们是产生一致结果并证明Rails应用程序完成了预期工作的测试应用程序。测试是与实际应用程序同时开发的。
断言-这是一行代码,用于评估对象(或表达式)的预期结果。例如–此值=该值吗?这个对象是零吗?
测试用例-这是一个从Test :: Unit :: TestCase继承的类,其中包含由上下文相关测试组成的测试策略。
测试套件-这是测试用例的集合。运行测试套件时,它将依次执行属于它的每个测试。
当您运行辅助脚本script / generate创建控制器和模型时,Rails会为单元和功能测试生成框架。通过用您编写的功能的测试填充框架,可以很好地覆盖测试范围。在Rails应用程序中有两个要测试的要点-
测试模型
测试控制器
本教程将简要介绍这两个测试。因此,让我们创建一个testapp来了解这一概念。
C:\ruby> rails -d mysql testapp
到目前为止,我们仅使用了Rails应用程序的开发数据库,但是现在您需要确保也创建了测试数据库,并且正确设置了config / database.yml文件的相应部分。
让我们如下创建开发和测试数据库:
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)
如下配置您的config / database.yml-
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
假设您有一个包含书籍的表格,包括书籍的标题,价格和简短说明。以下迁移设置此表-
testapp > ruby script/generate migration books
现在按如下所示修改testapp / db / migrate / 20080616170315_books.rb文件-
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
现在运行迁移,如下所示:
testapp > rake db:migrate
这将在testapp_development数据库中创建books表。之后,我们需要使用rake命令来设置您的测试数据库,如下所示:
C:\ruby\testapp > rake db:test:clone_structure
这会将testapp_development数据库克隆到testapp_test数据库中。这意味着您在开发数据库中拥有的一切,现在您在测试数据库中也将拥有相同的数据。
当使用generate脚本生成模型时,Rails还会在测试目录中为该模型生成一个单元测试脚本。它还创建了一个夹具,一个YAML文件,其中包含要加载到testapp_test数据库中的测试数据。这是您的单元测试将要运行的数据-
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
在模型类中编写代码时,将在这些文件中编写相应的测试。因此,让我们在test / fixtures / books.yml中使用YAML创建两个测试书记录,如下所示-
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'
现在,让我们用以下代码替换书籍单元测试文件test / unit / book_test.rb中的现有代码-
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
最后,运行测试方法如下-
testapp > ruby test/unit/book_test.rb
这是运行成功的测试用例的输出-
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
让我们分析一下这里发生的事情-
BookTest方法通过使用文本夹具/books.yml中第一条记录的标题和其他字段创建一个新的Book对象开始。结果对象存储在perl_book实例变量中。
第一个断言测试保存Book对象是否成功。
接下来,使用find方法检索book对象,并将其存储在另一个名为perl_book_copy的实例变量中。在下一个断言中测试该检索是否成功,该断言将两个书本对象的标题进行比较。至此,我们已经测试了创建和读取数据库记录的能力。
该解决方案通过为存储在perl_book中的对象分配新标题来测试更新,然后断言保存更改成功。
最后,测试了销毁Book对象的能力。
这就是我们可以测试Rails模型的方式。
控制器测试也称为功能测试。功能测试测试以下类型的控制器功能-
Rails框架支持五种类型的请求-
要编写功能测试,您需要模拟控制器将处理的五种HTTP请求类型中的任何一种。
请求类型“ get”和“ post”是控制器测试中最常用的。所有这些方法都有四个参数-
在本教程中,我们将看到如何使用get方法来测试我们的控制器。您可以类似的方式测试其余方法。
当使用generate生成控制器时,Rails为控制器创建功能测试脚本,如下所示:
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
在控制器类中编写代码时,将在这些文件中编写相应的测试。在此之前,让我们在app / controllers / book_controller.rb内部定义控制器功能列表,显示和搜索,如下所示:
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
注–您需要两个视图模板用于show和list方法。您可以定义这些视图并对其进行测试,但是现在,我们将继续进行操作,而无需定义这些视图。
现在,让我们重新使用test / fixtures / books.yml文件中的测试治具,如下所示:
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'
将以下test_search_book和test_search_not_found方法添加到test / functional / book_controller_test.rb,以测试书本控制器的搜索操作的功能。
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
现在运行您的测试用例,如下所示:
testapp > ruby test/functional/book_controller_test.rb
它给出以下输出-
Loaded suite test/functional/book_controller_test
Started
..
Finished in 0.422 seconds.
2 tests, 7 assertions, 0 failures, 0 errors
让我们分析一下这里发生了什么-
setup方法是创建控制器,请求和响应对象的默认方法。 Rails将在内部使用它们。
第一个测试方法test_search_book生成一个对搜索操作的get请求,并传递一个title参数。
接下来的两个断言验证Book对象是否保存在名为@book的实例变量中,并且该对象通过了可能存在的所有Active Record验证。
第一种方法中的最终断言测试该请求已重定向到控制器的show动作。
第二种测试方法test_search_not_found ,执行另一个get请求,但传入了无效的标题
第一个断言测试是否已发出对列表操作的重定向。
如果继续进行了断言,则闪存哈希中应该有一条消息,您可以使用assert_equal进行测试。
要获取有关断言的更多信息,请参考Rails Standard Documentation 。
您可以使用rake实用程序来测试您的应用程序。以下是一些重要命令的列表。
$ rake测试-测试所有单元测试和功能测试(以及集成测试,如果存在)。
$ rake test:functionals-运行所有功能测试。
$ rake test:units-运行所有单元测试。
$ rake test:integration-运行所有集成测试。
$ rake test: plugins-在./vendor/plugins/**/test中运行所有测试。
$ rake test:recent-对最近10分钟内已修改的模型和控制器运行测试-
$ rake test:未提交-对于Subversion中的项目,运行测试以测试自上次提交以来在模型和控制器中发生的更改-