gem测试的策略,以确保gem与Rails 3.x和4.0一起使用?

我已经看到了一些虚拟Rails应用程序的例子(用于测试,因此它们通常在测试或规范下),与Appraisalsgem一起使用,据说可以与Rails 3.x和Rails 4一起使用,但它们看起来很像hackishfunction不全。 这是有点预期的,因为它是一个被剥离的弗兰肯斯坦怪物,试图兼容各种版本的Rails 3以及Rails 4。

我已经提到了试图进行这种测试的项目(截至2013年3月下旬),比如less-rails和ember-rails,但这种用各种版本的Rails测试的方式看起来并不是很干净,而且它是尝试调试非标准的Rails应用程序是非常重要的,特别是在测试版的Rails中。

如果有一个更干净的测试方法,那么你可以通过一些魔法来测试每个Rails应用程序的完整Rails应用程序,通过一些魔法来设置或维护并不困难并且不需要非标准的路径攻击在某些地方等

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

rails-core列表中相关线程的几个选项:

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

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

我使用appraisal和dummy_app的混合测试minitest-spec-rails对3.0,3.1,3,2和4.0,根据它测试的哪个rails版本最低限度地配置自己。 一些链接:

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

类似的技术用于较少轨道 , 余烬轨道和高压电路等。

我在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在多个版本中进行测试

史蒂夫Klabnik提到了一个解决方案,可以使用单个Gemfile,一个完整的Rails应用程序(即使在“虚拟”目录下,并且没有使用评估gem,依靠travis-ci来测试:

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

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

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

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

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

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

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

Gemfiles

Bundler有一个名为--gemfile的有用选项。 有了它,您可以指定要使用的文件而不是Gemfile ,它将生成一个相同名称后的锁定文件:

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

这将生成Gemfile.rails3.lock和Gemfile.rails4.lock。 所以,那些Gemfiles可以是你的主要Gemfile强制rails版本的副本:

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

使用虚拟应用程序中的gemfiles

然后你有两个虚拟应用程序,一个用于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的gemfiles

要指示在运行测试时使用哪个版本,请在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”。

从测试中使用正确的虚拟app

最后,在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'各地的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中看到此方法的示例。