如何测试依赖Rails并使用Rails命令的gem [英] How to test a gem that depends on Rails and uses Rails commands

查看:81
本文介绍了如何测试依赖Rails并使用Rails命令的gem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个执行Rails命令的宝石(例如,rails g model Item).当我在Rails项目中使用它时,一切正常.问题是在Rails项目之外的开发中对其进行测试.

我正在将cucumberaruba结合使用,以测试CLI命令是否执行了正确的rails命令并生成了预期的文件.不幸的是,当我尝试测试行为时,它会失败,因为没有Rails文件,并且命令必须在Rails项目中运行才能正常工作.

我在gemspec中添加了Rails依赖项:

Gem::Specification.new do |spec|
  spec.add_development_dependency 'rails', '~> 5.2.4'
end

我曾考虑过在测试开始时创建一个新的Rails项目,然后在测试运行后将其删除,但这似乎非常不便.有更好的方法吗?

解决方案

我们用于 WickedPDF 是默认的rake任务,在我们运行测试之前,是删除&在gem的gitignored子目录中生成完整的Rails应用程序.

作为此Rakefile的高级简化示例 ,它看起来像这样的东西:

Rakefile

require 'rake'
require 'rake/testtask'

# This gets run when you run `bin/rake` or `bundle exec rake` without specifying a task.
task :default => [:generate_dummy_rails_app, :test]

desc 'generate a rails app inside the test directory to get access to it'
task :generate_dummy_rails_app do
  if File.exist?('test/dummy/config/environment.rb')
    FileUtils.rm_r Dir.glob('test/dummy/')
  end
  system('rails new test/dummy --database=sqlite3')
  system('touch test/dummy/db/schema.rb')
  FileUtils.cp 'test/fixtures/database.yml', 'test/dummy/config/'
  FileUtils.rm_r Dir.glob('test/dummy/test/*') # clobber existing tests
end

desc 'run tests in the test directory, which includes the generated rails app'
Rake::TestTask.new(:test) do |t|
  t.libs << 'lib'
  t.libs << 'test'
  t.pattern = 'test/**/*_test.rb'
  t.verbose = true
end

然后在 test/test_helper.rb 中,我们需要生成的Rails应用,该应用本身会加载Rails及其环境:

test/test_helper.rb

ENV['RAILS_ENV'] = 'test'

require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'test/unit' # or possibly rspec/minispec

# Tests can go here, or other test files can require this file to have the Rails environment available to them.
# Some tests may need to copy assets/fixtures/controllers into the dummy app before being run. That can happen here, or in your test setup.

您可以通过自定义生成应用程序的命令来跳过Rails不需要的部分.例如,默认情况下,您的gem可能根本不需要数据库,也不需要很多东西,因此您可以针对更简单的应用自定义命令.可能是这样的:

system("rails new test/dummy --skip-active-record \
  --skip-active-storage --skip-action-cable --skip-webpack-install \
  --skip-git --skip-sprockets --skip-javascript --skip-turbolinks")

在WickedPDF项目中,我们想在各种默认" Rails安装中进行测试,因此我们无需对命令进行太多自定义,但是所生成的内容远远超出了测试某些生成器任务所需的内容. /p>

WickedPDF还可以针对使用TravisCI的多个版本的Rails进行测试和多个Gemfile,但也可以通过Luke在此主题中建议的评估gem 来实现. /p>

I'm making a gem that executes Rails commands (rails g model Item for example). When I use it in a Rails project, everything works. The problem is testing it in development outside of a Rails project.

I'm using cucumber with aruba to test if CLI commands execute the proper rails commands and generate the expected files. Unfortunately, when I try to test the behaviour it fails because there are no rails files and the commands require to be run inside of a Rails project in order to work.

I have added a rails dependency to the gemspec:

Gem::Specification.new do |spec|
  spec.add_development_dependency 'rails', '~> 5.2.4'
end

I've thought about creating a new rails project on test start and then deleting it after the tests run, but that seems highly inconvenient. Is there a better way to do this?

解决方案

A technique we use for WickedPDF is in the default rake task, before we run the tests, is to delete & generate a full Rails application in a gitignored subdirectory of the gem.

As a high-level simplified example of this Rakefile, it looks something like this:

Rakefile

require 'rake'
require 'rake/testtask'

# This gets run when you run `bin/rake` or `bundle exec rake` without specifying a task.
task :default => [:generate_dummy_rails_app, :test]

desc 'generate a rails app inside the test directory to get access to it'
task :generate_dummy_rails_app do
  if File.exist?('test/dummy/config/environment.rb')
    FileUtils.rm_r Dir.glob('test/dummy/')
  end
  system('rails new test/dummy --database=sqlite3')
  system('touch test/dummy/db/schema.rb')
  FileUtils.cp 'test/fixtures/database.yml', 'test/dummy/config/'
  FileUtils.rm_r Dir.glob('test/dummy/test/*') # clobber existing tests
end

desc 'run tests in the test directory, which includes the generated rails app'
Rake::TestTask.new(:test) do |t|
  t.libs << 'lib'
  t.libs << 'test'
  t.pattern = 'test/**/*_test.rb'
  t.verbose = true
end

Then, in test/test_helper.rb, we require the generated Rails app, which loads Rails itself and it's environment:

test/test_helper.rb

ENV['RAILS_ENV'] = 'test'

require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'test/unit' # or possibly rspec/minispec

# Tests can go here, or other test files can require this file to have the Rails environment available to them.
# Some tests may need to copy assets/fixtures/controllers into the dummy app before being run. That can happen here, or in your test setup.

You could skip parts of Rails that aren't needed by customizing the command that generates the app. For example, your gem may not need a database at all or a lot of things by default, so you command could be customized for a simpler app. Something like this maybe:

system("rails new test/dummy --skip-active-record \
  --skip-active-storage --skip-action-cable --skip-webpack-install \
  --skip-git --skip-sprockets --skip-javascript --skip-turbolinks")

In the WickedPDF project, we wanted to test across a wide range of "default" Rails installs, so we don't customize the command much, but that may generate much more than what you need to test some generator tasks.

WickedPDF also tests against multiple versions of Rails with TravisCI and multiple Gemfiles, but this could also be accomplished with the Appraisal gem that Luke suggested in this thread.

这篇关于如何测试依赖Rails并使用Rails命令的gem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆