10

我已经看到了一些虚拟 Rails 应用程序的示例(用于测试,因此它们通常处于测试或规范目录下)与 Appraisals gem 一起使用,据称这些 gem 可以与 Rails 3.x 和 Rails 4 一起使用,但它们看起来很老套,而且功能不全。有点意料之中,因为它是一个精简的科学怪人怪物,试图与 Rails 3 和 Rails 4 的各种版本兼容。

我提到了尝试进行此类测试的项目(截至 2013 年 3 月下旬),例如 less-rails 和 ember-rails,但是这种使用各种版本的 Rails 进行测试的方法似乎不是很干净,而且它是尝试调试非标准 Rails 应用程序是非常重要的,尤其是在 Rails 的 beta 版本中。

最好有一种更简洁的测试方法,它允许您为每个版本的 Rails 拥有一个完整的 Rails 应用程序,通过一些魔法进行测试并不难设置或维护,并且不需要非标准的路径黑客在地方等

使用各种版本的 Rails(至少包括最新的 Rails 3.1.x、3.2.x 和 4.0.0.beta1)测试 gem 的可用策略是什么,每种策略的优缺点是什么?

4

2 回答 2

4

rails-core 列表中相关线程的一些选项:

选项 1:评估 gem 和单个 Rails 虚拟应用程序

Ken Collins 提到使用评估和 Rails “虚拟”应用程序:

我使用评估和 dummy_app 的组合针对 3.0、3.1、3,2 和 4.0 测试 minitest-spec-rails,根据它所测试的 rails 版本对自身进行最低限度的配置。一些链接:

https://github.com/metaskills/minitest-spec-rails https://github.com/metaskills/minitest-spec-rails/blob/master/test/dummy_app/init.rb

类似的技术用于less-railsember-railshigh_voltage等。

我在restful_json (v3.3.0) 中使用了与high_voltage类似的设置,但使用了一个使用 4.0.0-beta1 创建的完整 Rails 应用程序,我对其进行了最低限度的修改,以便也可以与 Rails 3.1.x/3.2.x 一起使用。

更新:可能希望查看许可者以获取最新示例。

优点:相当简单。可以从命令行等针对各种 Rails 版本进行测试。可以是非常小的 Rails 应用程序配置,或者可以使用具有细微差别的完整 Rails 应用程序。

缺点:仍然为多个 Rails 版本重用相同的 Rails 应用程序,因此需要一些条件和不需要的配置。(某些文件可能存在不适用于其他版本的 Rails 等的问题,但似乎不是大问题。)

选项 2:Rails 版本作为环境变量,单个 Gemfile,单个 Rails 虚拟应用程序,依赖 travis-ci 在多个版本中进行测试

Steve Klabnik 提到了一个解决方案,它可以与单个 Gemfile、单个完整的 Rails 应用程序一起使用(即使在“虚拟”目录下,并且不使用评估 gem,依靠 travis-ci 进行测试:

我一直想更多地讨论这个话题,因为我最近一直在为我的一堆宝石做这件事。我有两个这样做:

德雷珀:https ://github.com/drapergem/draper

LocaleSetter:https ://github.com/jcasimir/locale_setter/

基本上,我将整个 Rails 应用程序嵌入到 gem 中,然后通过 env vars 在 travis 上针对多个版本的 Rails 运行它。

优点:简单。不依赖于评估宝石(不是说这是一个问题,但可能更容易维护)。

缺点:据我所知,仍然为多个 Rails 版本重用相同的 Rails 应用程序。除非使用 travis-ci 或以干净的 gemset 开头的东西(即,如果在命令行下运行),当前不区分 gemset,因此较新的 gem 可能与较旧的 Rails 一起使用,等等,但史蒂夫说如果这会导致问题,你可以把锁吹走并重新捆绑。

于 2013-04-02T19:28:01.267 回答
2

还有第三种选择:使用多个 gemfile 和多个虚拟应用程序。

宝石文件

Bundler 有一个有用的选项,名为--gemfile. 有了它,你可以指定用什么文件代替Gemfile,它会在同名后生成一个锁文件:

bundle install --gemfile Gemfile.rails3
bundle install --gemfile Gemfile.rails4

这将生成 Gemfile.rails3.lock 和 Gemfile.rails4.lock。因此,这些 Gemfile 可以是您的主要 Gemfile 强制 rails 版本的副本:

source "http://rubygems.org"
gemspec
gem "jquery-rails"
gem "rails", '~>4' 

使用虚拟应用程序中的 gemfile

然后你有两个虚拟应用程序,一个用于 rails-3,一个用于 rails-4。要在运行(例如)迁移时使用它们正确的 gemfile:

cd test/dummy_rails3
BUNDLE_GEMFILE=../../Gemfile.rails3 bundle exec rake db:migrate
cd ../dummy_rails4
BUNDLE_GEMFILE=../../Gemfile.rails4 bundle exec rake db:migrate

是的,这可能是最糟糕的部分。但这主要是一次性设置。

使用 rake 中的 gemfile

要在运行测试时指示使用哪个版本,请在 Rakefile 中设置环境变量 BUNDLE_GEMFILE :

#!/usr/bin/env rake

rails_version = ENV[ 'RAILS_VERSION' ] || '4'

if rails_version == '3'
  ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails3'
else
  ENV[ 'BUNDLE_GEMFILE' ] = 'Gemfile.rails4'
end

begin
  require 'bundler/setup'
rescue LoadError
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

我更喜欢让用户传递 RAILS_VERSION 而不是直接传递 BUNDLE_GEMFILE,因为它更容易记住,我们可以只传递“3”或“4”。

从测试中使用正确的虚拟应用程序

最后,在 test_helper 中,根据请求的 rails 版本切换虚拟应用程序:

# Configure Rails Environment
ENV["RAILS_ENV"] = "test"

dummy_app = ENV[ 'RAILS_VERSION' ] == '3' ? 'dummy_rails3' : 'dummy_rails4'

require File.expand_path("../#{dummy_app}/config/environment.rb",  __FILE__)
require "rails/test_help"

从您的用户角度

为了让您的用户运行测试,他必须通过使用 BUNDLE_GEMFILE 运行迁移任务来进行一次性设置,这并不那么性感。

但是一旦完成,用户就可以针对 rails-3 和 rails-4 运行测试,而无需在每次想要切换版本时生成 Gemfile,并且您可以在测试应用程序中拥有特定于版本的代码和配置,而无需在if Rails.version >= '4'任何地方放置语句.

运行规格:

RAILS_VERSION=3 bundle exec rake test
bundle exec rake test # rails-4 is the default in code I wrote

您可以在我的activerecord_any_of gem中看到此方法的示例。

于 2013-09-01T10:45:16.777 回答