设置RSpec来测试gem(不是Rails)


154

使用添加的rspec-rails生成器可以很容易地设置RSpec来测试Rails应用程序。但是如何添加RSpec来测试开发中的gem?我没有使用珠宝商或类似工具。我只是使用Bundler(bundle gem my_gem)来设置新gem的结构,并手动编辑* .gemspec。我还添加s.add_development_dependency "rspec", ">= 2.0.0"了gemspec并做了一个bundle install

是否有一些不错的教程,接下来如何使RSpec工作?


我想我必须写一个:-) ...至少已经有两个宝石很好地集成了它:acts-as-taggable-on和acts_as_geocodable。
Zardoz 2010年

Answers:


255

我已更新此答案以匹配当前的最佳实践:

Bundler完美支持宝石开发。如果要创建宝石,则Gemfile中唯一需要的是以下内容:

source "https://rubygems.org"
gemspec

这告诉Bundler在运行时在gemspec文件中查找依赖项bundle install

接下来,确保RSpec是您gem的开发依赖项。编辑gemspec,使其显示为:

spec.add_development_dependency "rspec"

接下来,创建spec/spec_helper.rb并添加如下内容:

require 'bundler/setup'
Bundler.setup

require 'your_gem_name' # and any other gems you need

RSpec.configure do |config|
  # some (optional) config here
end

前两行告诉Bundler仅在gemspec内加载宝石。当您在自己的机器上安装自己的gem时,这将迫使您的规范使用当前的代码,而不是您单独安装的版本。

创建一个规范,例如spec/foobar_spec.rb

require 'spec_helper'
describe Foobar do
  pending "write it"
end

可选:添加一个.rspec文件作为默认选项,并将其放在gem的根路径中:

--color
--format documentation

最后:运行规格:

$ rspec spec/foobar_spec.rb

75
公平地说,您应该改为调用RSpec的init命令来生成规范框架文件,而不必手动键入它们。这将确保与您使用的RSpec版本兼容: rspec --init
AttilaGyörffy

12
rspec --init当我写这篇文章时还没有,但是很好!
iain 2012年

实际上,我发现在规范助手中执行需求的最佳方法是:require'rubygems'require'bundler / setup'Bundler.require(:default,:development)
mkon

@mkon的三行代码与iain的三行代码有何不同?
Nakilon

1
@mkon中的行将需要开发和测试组中的所有宝石,而我的方法是手动要求每个宝石。由于制作宝石时需要自己准备所有宝石,因此我认为这是一种更好/更清晰的方法,即使可能需要更多工作。
iain

53

Iain的上述解决方案效果很好!

如果您还想要一个Rakefile,那么您所需要做的就是:

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)

# If you want to make this the default task
task default: :spec

RDocTask的RDoc中检查各种选项,您可以选择将其传递到任务定义中。


26

您可以通过运行rspec来生成新的gem bundler gem --test=rspec my_gem。无需其他设置!

我总是忘记这一点。它在这里实现:https : //github.com/bundler/bundler/blob/33d2f67d56fe8bf00b0189c26125d27527ef1516/lib/bundler/cli/gem.rb#L36


1
整齐!但是,我认为您的宝石名称应使用下划线而不是驼峰大小写。否则,Bundler会创建带有大写字母的文件(Bundler 1.7.4)
Malte 2015年

Bundler抱怨了--test=rspec,但是它仍然问我在运行时是否要使用Rspec bundler gem my_gem
Nicolas Mattia

7

这是一种便宜且容易(尽管未正式推荐)的方式:

在您的宝石的根目录中创建一个目录spec,将您的规格放在此处。您可能已经安装了rspec,但是如果没有安装,请执行a gem install rspec并忘记Gemfiles和bundler。

接下来,您将制定一个规范,并且需要告诉它您的应用程序在哪里,文件在哪里,并包括要测试的文件(以及它具有的所有依赖项):

# spec/awesome_gem/awesome.rb
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
$: << File.join(APP_ROOT, 'lib/awesome_gem') # so rspec knows where your file could be
require 'some_file_in_the_above_dir' # this loads the class you want to test

describe AwesomeGem::Awesome do
  before do
    @dog = AwesomeGem::Awesome.new(name: 'woofer!')
  end
  it 'should have a name' do
    @dog.name.should eq 'woofer!'
  end
  context '#lick_things' do
    it 'should return the dog\'s name in a string' do
      @dog.lick_things.should include 'woofer!:'
    end
  end
end

打开终端并运行rspec:

~/awesome_gem $ rspec
..

Finished in 0.56 seconds
2 examples, 0 failures

如果您想要某些.rspec选择,请创建一个.rspec文件并将其放在gem的根路径中。我的看起来像这样:

# .rspec
--format documentation --color --debug --fail-fast

简单,快速,整洁!

我之所以这样,是因为您根本不必在项目中添加任何依赖项,整个过程仍然非常快。 bundle exec放慢速度,这是您必须做的,以确保始终使用同一版本的rspec。我的计算机加载rspec所花的时间为运行两次测试所花的0.56秒已占99%。运行数百个规格应该非常快。我知道的唯一可能遇到的问题是,如果您更改了rspec的版本,而新版本与您在测试中使用的某些功能不向后兼容,则可能必须重新编写一些测试。

如果您要执行一次性规格,或者有充分的理由不将rspec包含在gemspec中,那么这很好,但是对于启用共享或强制兼容而言,这不是很好。


有没有办法在您每次引用测试对象时都不将AwesomeGem ::放在类名之前?或在您的示例中创建新测试时。
Misha Slyusarev '16

1
当然,您可以将您的类名设置为较​​短的名称(例如)Thing = AwesomeGem::Awesome,也可以在模块内进行测试,例如module AwesomeGem; it 'stuff' do; Awesome.new ... end; end
wulftone
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.