`

使用Rack进行Rails测试

阅读更多
Testing Rails with Rack::Test

The biggest news in Rails 2.3 is its support for Rack, the WSGI inspired Ruby web server interface. Of all the Rack goodness that has come along lately, the one that has me the most excited is Bryan Helmkamp’s Rack::Test library, of which Bryan said “Basically, I extracted Merb’s request helper code into a small, reusable, framework agnostic library.”

I loved Merb’s request specs. I suspect that I’m going to like Rack::Test too.
如何安装 Rack::Test

We’ll start by installing Rack::Test and loading it into our Rails app. Append this line to config/environments/test.rb:

引用
config.gem "rack-test", :lib => "rack/test"


You can now use rake to install it:

$ sudo rake gems:install RAILS_ENV=test


使用Rake运行Rack“rake test:rack”


We want to be able to run these tests easily with rake, just like our unit or functional tests. Create a new file called lib/tasks/rack-test.task and paste this code (courtesy of recipe 53 from the Advanced Rails Recipes book) into it:
namespace :test do
  Rake::TestTask.new(:rack => "db:test:prepare") do |t|
    t.libs << "test"
    t.pattern = "test/rack/**/*_test.rb"
    t.verbose = true
  end
  Rake::Task["test:rack"].comment = "Run the Rack::Test tests in test/rack"
end

task :test do
  Rake::Task["test:rack"].invoke
end


Note that we have also extended the :test task so that our Rack tests will get run after our unit and functional tests.

You should now be able to run rake test:rack, but it won’t do anything yet. Let’s test it by dropping this code into a file called test/rack/dummy_test.rb:

require File.join(File.dirname(__FILE__), *%w[.. test_helper])

class DummyTest < ActiveSupport::TestCase
  include Rack::Test::Methods

  def app
    lambda { |env| [200, {}, "Coolness"] }
  end

  test "should be hooked up properly" do
    get "/"
    assert last_response.body.include?("Cool")
  end
end

When you run rake test:rack you should get something like this:

$ rake test:rack
(in /Users/graham/data/effectif/projects/canvas)
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -I"lib:test" "/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/rack/login_test.rb" 
Loaded suite /Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started

.
Finished in 0.008904 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

测试Rails应用

You’ll have noticed that the app method (which is supposed to return an instance of the Rack application under test) doesn’t actually have anything to do with Rails. It returns a callable object that needs to be compliant with the Rack API (apps are invoked via their call method, which is also how you invoke a lambda).

Let’s fix that by making the app method return an instance of our Rails application.

For an example of how Rails instantiates a rack app have a look inside commands/server.rb. Scroll down until you find the call to Rack::Builder.new. From there we can see that Rails is using ActionController::Dispatcher.new. That should be enough for most purposes (if not you can see what else you may need to add by poking around in server.rb).

That gives us a template test file that looks something like this:

require File.join(File.dirname(__FILE__), *%w[.. test_helper])

class MyTest < ActiveSupport::TestCase
  include Rack::Test::Methods

  def app
    ActionController::Dispatcher.new
  end

  test "home page" do
    get "/"
    assert last_response.ok?
  end
end


If you want to get a bit more fancy and test things that aren’t handled by ActionController::Dispatcher you can put your app together with Rack::Builder. As a contrived example, if you wanted to test for the presence of static files (I said it was contrived) you could create your app like this:
def app
  Rack::Builder.new {
    map "/" do
      use Rails::Rack::Static 
      run ActionController::Dispatcher.new
    end
  }.to_app
end


This article was written using Rails 2.3.2, Rack 1.0.0 and Rack::Test 0.3.0.
Why Bother?

Shortly after I first posted this article, crispee commented on reddit asking why you’d bother to use Rack::Test instead of the functional tests that come with Rails. It’s a good question, and I completely failed to cover it. Ooops.

Firstly, Rack::Test is more similar to the Rails integration tests than to the functional tests. Functional tests only allow you test the actions and views of a single controller. Rack::Test allows you to write tests that visit pages anywhere on your site – you can simulate the behaviour of a real browser to ensure that your entire app hangs together properly.

Secondly, both the Rails functional and integration tests are closely coupled to Rails. Imagine for a moment that you’ve been running a Rails app for a while now. You’ve invested a lot of effort in your application; users can log in and do all sorts of clever stuff. In the meantime you’ve been hand crafting the sales pages (e.g. home page, tour, FAQ, etc.) and adding them to your app. All these static pages are served by one big controller and your routes file is getting to be a bit of a mess. It’s high time that you introduced a CMS.

You’ve also recently stumbled across a hot new rack compatible web framework (for the sake of argument, let’s call it Sinatra). You quite fancy using a Sinatra CMS (sorry, shameless plug) while continuing to develop the main part of your application in Rails. Rack makes this very easy to do in the same Ruby process (see Rails meets Sinatra for details).

Obviously, you wrote a test to demonstrate that a new user can click on the “Buy Now” link on your home page, navigate their way through your signup forms, and end up on the home page. If you were also astute enough to write that test using Rack::Test, that test will still work after you move some of those pages into the Sinatra CMS.

If you refer to Pratik’s “Rails meets Sinatra” post that I linked to above, you’ll see that you’d only have to change the way the rack app is instantiated in your test:

def app
  Rack::Builder.new {
    # URLs starting with /account (logged in users) go to Rails
    map "/account" do
      run ActionController::Dispatcher.new
    end

    # Everything else goes to your CMS
    map "/" do
      run Sinatra.application
    end
  }.to_app
end


How awesome is that?
分享到:
评论

相关推荐

    rack-back_door:将用户 ID 注入会话以进行集成和控制器测试

    将用户注入会话以进行集成和控制器测试。 灵感来自宝石 安装 将此行添加到应用程序的 Gemfile 中: gem 'rack-back_door' 然后执行: $ bundle 或者自己安装: $ gem install rack-back_door 用法 默认情况...

    akita-rails-har-logger:秋田的Rails中间件

    有两种方法可以检测您的Rack / Rails应用程序。 第一种是将HAR记录器用作Rack中间件。 第二种是将其用作Rails ActionController过滤器。 根据您使用的框架,一个或两个选项可能可供您使用。 如果您对记录RSpec测试...

    大卫:具有Rack界面的CoAP服务器

    使用MRI&gt; = 2.3和JRuby&gt; = 9.1进行了测试。 David版本〜&gt; 0.5.0适用于Rack 2(和Rails 5)。 〜&gt; 0.4.5版本提供与Rails 4的兼容性。 快速开始 只要在您的Gemfile中包含David! gem 'david' 它将挂接到Rack并使其...

    rest-api-authentication-jwt-ruby:使用Ruby,Rails,PostgreSQL,JWT等开发的软件(REST-API)

    REST API身份验证Rails-JWT...软件Ruby版本管理器RVM 1.29.10-next数据库使用PostgreSQL应用客户休息:邮递员,失眠,Talend API测试仪等外挂程式您可以使用宝石JWT,Carrierwave,Bcrypt,Rack-Cors等用法$ git clone ...

    rack-timeout:中止要求时间太长的请求

    机架::超时 中止要求时间太长的请求; 引发异常。 默认值为15秒。 建议将超时设置为对应用程序实际可行的低。 您可以通过设置RACK_... 这将加载机架超时,并使用默认超时15s将其设置为Rails中间件。 没有为测试环境

    dredd-rack:用于您的Rack应用程序的Dredd API蓝图测试工具

    除了方便之外,这还允许将API蓝图用作验收测试套件,例如,在客户端开发人员将用作模拟服务器的同时,使用Dredd和RSpec进行 。 安装 将gem添加到您的Gemfile : # Gemfile gem 'dredd-rack' , '~&gt; 1.0' # see ...

    redis-store:命名空间的Rack :: Session,Rack :: Cache,I18n和缓存Redis存储(用于Ruby Web框架)

    Redis Store为现代Ruby框架提供了全套存储( Cache , I18n , Session , HTTP Cache ),例如: Ruby on Rails , Sinatra , Rack , Rack :: Cache和I18n 。 它支持对象编组,超时,单个或多个节点以及名称空间...

    tips-on-rails:Rails 开发人员的专业网络

    Rails 技巧入门Tips on Rails 使用环境变量在瘦 web 服务器上运行。 您需要完成以下步骤才能使其运行。 创建.env文件,包含以下信息: PORT=5300 (this specific port is needed to work with GitHub oauth)RACK_ENV...

    ToDo-app-rack-React

    ToDo应用-React and Rack 转到front-end文件夹并运行: npm i json-server --watch db.json npm start ... 仅使用机架服务器,您的后端响应可能会有点慢,但是一旦我们开始使用rails,它将更快。

    rack-legacy:在任何机架服务器下运行 CGI 和 PHP 等遗留环境

    简介 Rack Legacy 尝试提供与 PHP 和 CGI​​ 等遗留...用法 安装 gem install rack - legacy通用机架集成 将以下内容放入您的机架堆栈中: require 'rack-legacy'use Rack :: Legacy :: Php , 'public'Rails使用¶

    rack-no_animations:机架无动画

    安装将此行添加到应用程序的Gemfile中: gem 'rack-no_animations' 然后执行: $ bundle或将其自己安装为: $ gem install rack-no_animations用法在config/environments/test.rb将中间件添加到rails中,例如: ...

    standalone-cucumber:一个用于测试非Ruby Web应用程序的示例Cucumber测试套件

    独立Cucumber测试套件 简介 有时您会继承非基于Rails或非Rack的Web应用程序,例如PHP,Perl,Java / J2EE等。我喜欢使用Cucumber进行功能测试,因此我将这个项目结构汇总起来用作测试非Ruby Web的起点基于应用程序。...

    Ruby on Rails基础之新建项目

    - config.ru #Rack服务器的程序设置、用于启动程序 - Gemfile,Gemfile.lock #指定Gem依赖,用于bundler gem - Rakefile #保存并加载可在命令行中执行的任务,可添加任务在lib/tasks中 新建项目 rai

    split:基于机架的AB测试框架

    Split是基于机架的A / B测试框架,旨在与Rails,Sinatra或任何其他基于机架的应用程序一起使用。 Split受和 Rails A / B测试插件以及使用Redis的启发很大。 Split旨在对黑客友好,允许最大程度的自定义和可扩展性...

    capybara:Web应用程序的验收测试框架

    水豚 Capybara通过模拟真实用户将...无需为Rails和Rack应用程序进行设置。 开箱即用。 直观的API ,模仿实际用户会使用的语言。 将测试运行的后端从快速无头模式切换到实际的浏览器,而无需更改测试。 强大的同步功

    Larrys-Lawncare-API-后端

    自述文件该存储库用于使用React前端的全栈Web应用程序的RAILS api后端。 使用此存储库之前,请运行捆绑安装以安装最新...用于密码加密Rack-cors-跨源资源共享-允许api与前端一起使用敲门-用户身份验证Rspec-rails-测试

    机架攻击:用于阻止和限制的机架中间件

    使用Rack :: Attack,您可以根据请求的属性轻松决定何时允许,阻止和限制。 请参阅介绍Rack :: Attack的。 目录 入门 正在安装 将此行添加到您的应用程序的Gemfile中: # In your Gemfile gem 'rack-attack' ...

    基于云的持续集成项目TravisCI.zip

    比如Ruby语言的:Rails, Rack, Sinatra, RSpec, Cumber, Node.js, PHP的:Symfony2, Doctrine2, Zend Framework 2。 使用Travis-CI的项目可以在说明文件中增加目前版本的构建状态。如:,。 Travis-CI 使用 ...

    static:GOV.UK 静态文件和资源

    它与结合使用,后者是 Rack 中间件,它接受来自 Rails 应用程序的 HTML 响应,并将其与来自静态的模板相结合。现场示例有关静态提供的页面家具示例,请参阅此。技术文档这是一个 Ruby on Rails 应用程序,应该遵循...

    snoopier:提供基于 Rack 的可配置基础认证

    史努比提供基于 Rack::Auth 的可配置基本身份验证。配置将其添加到您的 gemfile: gem "snoopier"...并定义以下 ENV 变量 BASIC_...去做使用 Rails.secrets? 测试这个项目震撼并使用 MIT-LICENSE。 自豪地用来自爱建造

Global site tag (gtag.js) - Google Analytics