How to get the minitest capture_io method found in my specs? - rspec2

This is my spec/helper.rb file:
require 'minitest/autorun'
require 'minitest/spec'
require_relative '../lib/launcher'
class MiniTest::Spec
include MiniTest::Assertions
end
And this is the spec file:
require 'helper'
describe Launcher do
it "should get the stdout" do
out, err = capture_io do
warn "You did a bad thing"
end
err.should =~ /bad/
end
end
But when I run the spec:
± rake spec
/Users/millisami/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/launcher_spec.rb -Ispec:lib
F
Failures:
1) Launcher should be a launcher for cloud
Failure/Error: out, err = capture_io do
NoMethodError:
undefined method `capture_io' for #<RSpec::Core::ExampleGroup::Nested_1:0x000001012a4840>
# ./spec/launcher_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.00044 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/launcher_spec.rb:4 # launcher should be a launcher for cloud
rake aborted!
/Users/millisami/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/launcher_spec.rb -Ispec:lib failed
Tasks: TOP => spec
But when I do this with the default MiniTest::Unit way, it works?
And why not the spec way?

Your spec_helper.rb should look more like this:
require 'minitest/unit'
RSpec.configure do |c|
c.include MiniTest::Assertions
end

Related

Minitest: rake test:all fails while explicit testing does not

I have a weird problem which is bugging me for days now... and I don't have a single clue.
I have a rails 4 app which i test using Minitest and guard. So far everything went fine until at some point (which unfortunately I'm not able to reconstruct although I was using guard, maybe my collaborators introduced the issues...) some of our tests fail. The weird thing is: bundle exec rake test:all fails:
DEPRECATION WARNING: rake test:all is deprecated and will be removed in Rails 5. Use rake test to run all tests in test directory. (called from mon_synchronize at /usr/lib/ruby/2.3.0/monitor.rb:214)
# Running tests with run options --seed 53809:
WARNING: The next major version of capybara-webkit will require at least version 5.0 of Qt. You're using version 4.8.7.
............EE....EE.............F..
Finished tests in 26.018707s, 1.3836 tests/s, 1.6142 assertions/s.
Error:
PlaceTest#test_return_''_if_too_many_characters_to_translate:
NoMethodError: undefined method `failsafe_translate' for nil:NilClass
test/models/place_auto_translation_test.rb:29:in `block in <class:PlaceTest>'
Error:
PlaceTest#test_test_places_are_valid:
NoMethodError: undefined method `geocode' for nil:NilClass
test/models/place_geocode_test.rb:21:in `block in <class:PlaceTest>'
Error:
PlaceTest#test_should_translate_text_below_character_limit:
NoMethodError: undefined method `failsafe_translate' for nil:NilClass
test/models/place_auto_translation_test.rb:34:in `block in <class:PlaceTest>'
Error:
PlaceTest#test_can_translate_if_valid_credentials_given:
NoMethodError: undefined method `bing_translator' for nil:NilClass
test/models/place_auto_translation_test.rb:16:in `block in <class:PlaceTest>'
Failure:
Index page Feature Test#test_0002_language is switched to german [/home/blubber/software_projects/rails/workspace/lberg-map/test/features/index_page_test.rb:16]
Minitest::Assertion: Expected to include "Neuer Ort".
36 tests, 42 assertions, 1 failures, 4 errors, 0 skips
Now, while trying to understand the issues raised I was testing the problematic files individually (within my editor and guard or on the command-line, same thing of course) it turns out, that there is actually no problem at all, all tests pass oO. Hence bundle exec rake test test/models/place_auto_translation_test.rb returns
# Running tests with run options --seed 55164:
.....
Finished tests in 25.472545s, 0.1963 tests/s, 0.2355 assertions/s.
5 tests, 6 assertions, 0 failures, 0 errors, 0 skips
Same goes for place_geocode_test.rb as well as the "failing" feature test. Any idea on what's happening here? The test file test/models/place_auto_translation_test.rb looks like this:
require_relative '../test_helper'
class PlaceTest < ActiveSupport::TestCase
def setup
#valid_translator = BingTranslatorWrapper.new(ENV['bing_id'], ENV['bing_secret'], ENV['microsoft_account_key'])
#place = Place.new(name: 'Kiezspinne',
street: 'Schulze-Boysen-Straße',
house_number: '13',
postal_code: '10365',
city: 'Berlin',
description_en: 'This is a test')
end
# AUTO TRANSLATION WRAPPER TESTS
test 'can translate if valid credentials given' do
assert_not_nil #valid_translator.bing_translator
end
test 'cannot translate if API id and key invalid or no microsoft account key' do
invalid_translator = BingTranslatorWrapper.new(ENV['wrong_id'], ENV['wrong_secret'], ENV['microsoft_account_key'])
assert_nil invalid_translator.bing_translator
invalid_translator = BingTranslatorWrapper.new(ENV['bing_id'], ENV['bing_secret'], ENV['wrong_microsoft_account_key'])
assert_equal '', invalid_translator.failsafe_translate('Dies ist ein Test', 'en', 'de')
end
test "return '' if too many characters to translate" do
text = '13 characters' * 1000
assert_equal '', #valid_translator.failsafe_translate(text, 'en', 'de')
end
test 'should translate text below character limit' do
text = 'This is a test'
assert_equal 'Automatische Übersetzung: Dies ist ein Test', #valid_translator.failsafe_translate(text, 'en', 'de')
end
test 'should autotranslate after_create' do
#place.save
#place.reload
assert_equal "Automatische Übersetzung: Dies ist ein Test", #place.description_de
end
end
and test_helper.rb looks like this
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/rails'
require 'minitest/reporters'
require 'minitest/rails/capybara'
reporter_options = { color: true }
Minitest::Reporters.use!(
Minitest::Reporters::DefaultReporter.new(reporter_options),
ENV,
Minitest.backtrace_filter
)
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
end
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.set_default_stub(
[
{
'latitude' => 52,
'longitude' => 12,
'address' => {
'road' => 'Magdalenenstr.',
'house_number' => '19',
'postcode' => '10365',
'town' => 'Berlin',
},
'type' => 'house',
}
]
)
# allow tile loading from foreign server
Capybara::Webkit.configure do |config|
%w[a b c].each { |x| config.allow_url("tile-#{x}.openstreetmap.fr") }
end
# While testing with Javascript flag, test runs in another thread,
# thus created fixtures are not available without the following setup
class Capybara::Rails::TestCase
self.use_transactional_fixtures = false
before do
if metadata[:js]
Capybara.javascript_driver = :webkit
Capybara.current_driver = Capybara.javascript_driver
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.start
end
end
after do
if metadata[:js]
DatabaseCleaner.clean
end
Capybara.reset_sessions!
Capybara.current_driver = Capybara.default_driver
end
end
Thanks a thousand, best
Andi

Factory_girl and RSpec: undefined method `new' for Test:Module

I generated the following scaffold (using Ruby 2.2.0, rails 4.1.8, postgres):
rails g scaffold Test user:references text:references data:hstore
In my test_spec.rb:
require 'rails_helper'
RSpec.describe Test, :type => :model do
describe 'User generates a test' do
before do
#text = create(:text, content: "Cats eat mice")
#user = create(:user)
#test = create(:test)
end
...
When I run rspec the test fails with the following message:
Failure/Error: #test = create(:test)
NoMethodError:
undefined method `new' for Test:Module
# ./spec/models/test_spec.rb:8:in `block (3 levels) in <top (required)>'
When I test other models (user, text) everything works well, only the Test model fails. Calling Test.create(...) in rspec file also fails. Creating new test in rails console works. Any ideas how to fix this?
With the default configuration, Rails defines the module constant Test, so Ruby doesn't autoload your test.rb file when FactoryGirl does a Test.new as part of your :test factory.
You can install Rails without the Test infrastructure by using the -T switch, in which case it won't define the Test module and you should be fine.
If Rails is already configured, you can put the following in your rails_helper.rb file to remove the Test constant and you should be ok as well:
Object.send(:remove_const, :Test)

Minitest - NoMethodError: undefined method `get'

I was stuck with error when i run very simple test with minitest-rails gem.
I have rails 4.1.5 and minitest 5.4.0
rake test:controllers
1) Error:
DashboardController::index action#test_0001_anonymous:
NoMethodError: undefined method get' for #<#<Class:0x00000008e28170>:0x00000008eeb9b8>
test/controllers/dashboard_controller_test.rb:6:inblock (3 levels) in '
Test:
require "test_helper"
describe DashboardController do
context "index action" do
before do
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
My test_helper:
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/rails/capybara"
class MiniTest::Spec
class << self
alias :context :describe
end
end
class RequestTest < MiniTest::Spec
include Rails.application.routes.url_helpers
register_spec_type(/request$/, self)
end
class ActionDispatch::IntegrationTest
# Register "request" tests to be handled by IntegrationTest
register_spec_type(/Request( ?Test)?\z/i, self)
end
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
# Add more helper methods to be used by all tests here...
extend MiniTest::Spec::DSL
end
There are many things wrong with what you are doing. As I understand it you want to use Minitest's spec DSL in your Rails tests, correct? It looks like you are doing things to accomplish this that you don't need to do. I don't understand why half that code in your test_helper.rb file is there. I also suspect that you have other code doing things that are not being shown.
Here is what I did to reproduce your setup:
$ echo "Creating a new Rails app"
☣ [rails41:rails41] $ rails new undefined_get
☣ [rails41:rails41] $ cd undefined_get/
$ echo "Generate a Dashboard controller"
$ rails g controller dashboard index
$ echo "Add minitest-rails dependencies"
$ echo 'gem "minitest-rails"' >> Gemfile
$ echo 'gem "minitest-rails-capybara"' >> Gemfile
$ bundle install
$ echo "The test runs fine now:"
$ rake test
Run options: --seed 47210
# Running:
.
Finished in 0.457972s, 2.1835 runs/s, 2.1835 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
$ echo "Update to your test code and test_helper code"
$ echo "Use whatever editor you want. Not shown here."
$ echo "Now rerun the tests:"
$ rake test
rake aborted!
NoMethodError: undefined method `context' for #<Class:0x007f860258ae50>
The error I get is different than yours. You aliased the method context to describe in your test_helper.rb file, but unfortunately the object you aliased is not in the inheritance chain for the rails test objects. The rails test objects extend Minitest::Spec::DSL, but they do not inherit from Minitest::Spec. So, I am strongly suspicious that the code you provided is indeed producing the results you have presented. That said, here is the code in my test_helper.rb that will run your test:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/rails"
require "minitest/rails/capybara"
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Allow context to be used like describe
class << self
alias :context :describe
end
# Add more helper methods to be used by all tests here...
end
This is the standard test_helper.rb with two changes. First, it has the requires for minitest-rails and minitest-rails-capybara. That is all you need to do in order to enable the Minitest spec DSL in your rails tests. Second, it adds the alias for context to describe on ActiveSupport::TestCase, which is the basis for all the rails tests. If you want to add tests that do not inherit from ActiveSupport::TestCase then you can also alias it on Minitest::Spec, but that will not help you use context within your controller tests.
Still here? Okay. So why did your code give you a different error than mine? Likely the test object used for your controller tests isn't ActionController::TestCase. I say that because your error was undefined method get. The get method is something that ActionController::TestCase defines, and is not on Minitest::Spec. So, you somehow messed up your Minitest configuration. A simple way to make sure that your tests are using the correct test objects is to add an additional assertion to your test. Like this:
require "test_helper"
describe DashboardController do
context "index action" do
before do
# Make sure we are using the correct test class
self.class.ancestors.must_include ActionController::TestCase
# Continue with setup
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
If that first assertion fails then you know you have done something wrong in your configuration.

How to test a rake task with RSpec?

I have an Ruby 2.1/Rails 3.2 application which uses the asset pipeline. We are also using a fragile (alpha) gem which causes "rake assets:precompile" to fail at times. I would like to write an rspec test which ensures that this rake task always passes before we commit our code.
I wrote a test in spec/asset_precompile_spec.rb which looks like this:
require 'spec_helper'
require 'rake'
describe 'assets:precompile' do
before { MyApp::Application.load_tasks }
it { expect { Rake::Task['assets:precompile'].invoke }.not_to raise_exception }
end
I then ran it on the command line using
rspec spec/lib/assets_precompile_spec.rb
The output I got looked like this:
1) assets:precompile
Failure/Error: it { expect { Rake::Task['assets:precompile'].invoke }.not_to raise_exception }
expected no Exception, got #<RuntimeError: Command failed with status (1): [/home/railsdev/.rvm/rubies/ruby-2.1.2/bin/...]> with backtrace:
# ./spec/lib/assets_precompile_spec.rb:7:in `block (3 levels) in <top (required)>'
# ./spec/lib/assets_precompile_spec.rb:7:in `block (2 levels) in <top (required)>'
# ./spec/lib/assets_precompile_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.71247 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/lib/assets_precompile_spec.rb:7 # assets:precompile
I have looked far & wide, and I can't find any example to run "rake assets:precompile" which actually works in my RSpec environment. I have tried explicitly loading the spec_helper.rb file, I have tried explicitly requiring "factory_girl", but I cannot find anything which works.
Is there a way to make a test run this rake task run in a RSpec test?
Try Rake::Task['assets:precompile:all'].invoke
instead of Rake::Task['assets:precompile'].invoke
In my case it helped.

NameError: uninitialized constant Minitest::VERSION

I'm using Rails 4.1 and Ruby 2.0.0. I'm trying to set up testing with minitest-rails and I'm running into this strange error. When I include:
require 'minitest/spec'
In my 'spec_helper' file it give me a NameError: uninitialized constant Minitest::VERSION error. When I comment out this line, everything seems to work fine. The odd thing is that 'minitest/autorun' is also in there and not causing any problems. Maybe you guys can shed some light on what's going on here.
spec_helper.rb:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'minitest/spec'
require 'minitest/autorun'
require 'minitest-rails'
require 'minitest-rails-capybara'
Rakefile:
require File.expand_path('../config/application', __FILE__)
Pinteresting::Application.load_tasks
namespace :test do
task :run do
ENV["RACK_ENV"] = "test"
$LOAD_PATH.unshift("lib", "spec")
if ARGV[1]
require_relative ARGV[1]
else
Dir.glob("./spec/**/*_spec.rb").each { |file| require file }
end
end
end
.spec:
require "spec_helper"
describe "Test" do
describe "When two is equal to two" do
it "asserts true" do
assert_equal(2, 2)
end
end
end
Stack trace:
nbp-93-202:pinteresting Frank$ rake test:run
rake aborted!
NameError: uninitialized constant Minitest::VERSION
/usr/local/rvm/gems/ruby-2.0.0-p481/gems/minitest-5.3.4/lib/minitest/unit.rb:22:in `<class:Unit>'
/usr/local/rvm/gems/ruby-2.0.0-p481/gems/minitest-5.3.4/lib/minitest/unit.rb:21:in `<module:Minitest>'
/usr/local/rvm/gems/ruby-2.0.0-p481/gems/minitest-5.3.4/lib/minitest/unit.rb:20:in `<top (required)>'
/usr/local/rvm/gems/ruby-2.0.0-p481/gems/minitest-5.3.4/lib/minitest/spec.rb:1:in `<top (required)>'
/Users/Frank/Desktop/pinteresting/spec/spec_helper.rb:4:in `<top (required)>'
/Users/Frank/Desktop/pinteresting/spec/diagnostic_spec.rb:1:in `<top (required)>'
/Users/Frank/Desktop/pinteresting/Rakefile:12:in `block (3 levels) in <top (required)>'
/Users/Frank/Desktop/pinteresting/Rakefile:12:in `each'
/Users/Frank/Desktop/pinteresting/Rakefile:12:in `block (2 levels) in <top (required)>'
Tasks: TOP => test:run
Interestingly, if try to run or require a file with just the two requires minitest/spec and minitest/autorun the interpreter raises a warning saying that you should require 'minitest/autorun' instead or add "gem 'minitest'" before require 'minitest/autorun', although it doesn't rise the NameErrorto me.
So switching the require statements around (in order to first require minitest/autorun) seems to do the trick. Requiring minitestin the first place seems to do the trick also.
I think you can resolve this warning by making your implementation simpler. In spec/spec_helper.rb:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/rails"
require "minitest/rails/capybara"
You are missing the require for rails/test_help. Did you remove that for a specific reason?
In Rakefile:
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks
Rails::TestTask.new("test:spec" => "test:prepare") do |t|
t.pattern = "spec/**/*_spec.rb"
end
Rake::Task["test:run"].enhance ["test:spec"]
And now run either $ rake test:spec to run all your specs, or $ rake test to run all your tests. The reason behind keeping the rake tasks under the test namespace is because this is what Spring keys on to use the running test environment. Spring uses the task namespace, not the directory name.

Resources