When running rake spec on the command line for a large Rails project, I get a giant list of every rspec file that will be run.
Is there a way to hide that by default?
ruby-1.9.3-p448/bin/ruby -S rspec ./spec/acceptance/replicators/activity_replicator_spec.rb ./spec/acceptance/replicators/template_replicator_spec.rb ./spec/authorization_rules/admin_authorization_rules_spec.rb ...
When I run just rspec (no rake call) I don't get this console output.
EDIT 1
Working from phoet's answer, I tried
RSpec::Core::RakeTask.new(:spec) do |t|
t.verbose = false
t.warning = false
t.rcov = false
end
task :default => :spec
This did not solve the issue.
The last time I did this, I had to clear the rake task first.
if defined? RSpec
task(:spec).clear
RSpec::Core::RakeTask.new(:spec) do |t|
t.verbose = false
end
end
http://singlebrook.com/blog/disable-rspec-verbosity-to-hide-spec-list
You don't get such an output when calling rspec because the output comes from the RSpec::Core::RakeTask.
It's possible to configure this class and set the verbose flag:
RSpec::Core::RakeTask.new do |t|
t.verbose = false
end
Related
My very basic feature specs are passing just fine locally but failing on CircleCI and Codeship. The tests that are failing:
require 'spec_helper'
describe 'Authentication' do
describe "sign in" do
it "is the landing page for non-authenticated users" do
user = create(:user)
visit root_path
expect( page ).to have_content 'LOG IN' # On sign-in page
fill_in 'Email', with: user.email
fill_in "Password", with: user.password
click_button 'Sign in'
expect( current_path ).to eq user_path(user)
end
end
describe 'registration' do
it "allows new users to register" do
visit root_path
click_link 'Sign up'
fill_in 'Email', with: 'myfake#email.com'
fill_in 'Password', with: 'password'
fill_in 'Password confirmation', with: 'password'
fill_in 'First name', with: 'John'
fill_in 'Last name', with: 'Doe'
click_button "Sign up"
expect( current_path ).to include '/users/'
expect( page ).to have_content "Welcome! You have signed up successfully."
end
end
end
The tests both fail on the first lines where they set expectations of the pages (expect( page ).to have_content "LOG IN" and click_link "Sign up", respectively), with errors suggesting the page HTML is completely blank:
expected to find text "LOG IN" in ""
I saved screenshots on CircleCI, and they indeed show a completely blank page.
Here's where it gets interesting. I tried debugging the problem by running/watching the specs on Circle using a VNC. When I a) set driver: :selenium for the tests, b) add a sleep 1 or two to the tests before testing the page expectations, and c) manually run the test after SSHing into their servers with the VNC, I can see the tests run in Selenium (they open a browser in the VNC) and they pass perfectly.
Outside of the VNC, however, the tests fail consistently in both CI servers. With or without tons of sleeps and driver: :selenium. Any ideas what could be causing this discrepancy between the regular CircleCI/Codeship servers and their VCN/my local test environment? I got in touch with the folks at CircleCI, but they're stumped for the moment.
If relevant, I'm running Ruby 2.2.0, Rails 4.2, Capybara 2.4.4, Capybara-Webkit 1.4.1, and Selenium-Webdriver 2.44.0
Some potentially relevant files:
spec_helper.rb
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rspec/rails"
require "shoulda/matchers"
require "webmock/rspec"
require 'vcr'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |file| require file }
module Features
include Warden::Test::Helpers
Warden.test_mode!
def sign_in(user)
login_as(user, scope: :user)
end
end
module Controllers
# Pre-parse controller responses for easy access
def response_body
body = JSON.parse(response.body)
body.is_a?(Hash) ? body.to_sh : body.map(&:to_sh)
end
end
module Mock
def disable_webmock(&block)
WebMock.disable!
yield
WebMock.enable!
end
end
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
# Save a screenshot to CircleCI when a feature test fails
config.after(:each, :type => :feature) do |example|
if example.exception
artifact = save_page
puts "\"#{example.description}\" failed. Page saved to #{artifact}"
end
end
config.include Features, type: :feature
config.include Controllers, type: :controller
config.include Mock
config.include Formulaic::Dsl, type: :feature
config.infer_spec_type_from_file_location!
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.use_transactional_fixtures = false
end
RSpec::Matchers.define :hash_eq do |expected|
match do |actual|
actual.recursive_symbolize_keys == expected.recursive_symbolize_keys
end
end
VCR.configure do |c|
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
c.hook_into :webmock
c.allow_http_connections_when_no_cassette = true
c.configure_rspec_metadata!
c.ignore_hosts '127.0.0.1', 'localhost:3000'
end
ActiveRecord::Migration.maintain_test_schema!
Capybara.javascript_driver = :webkit
if ENV['CIRCLE_ARTIFACTS']
Capybara.save_and_open_page_path = ENV['CIRCLE_ARTIFACTS']
end
WebMock.disable_net_connect!(allow_localhost: true)
database_cleaner.rb
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
I can think of a couple of things to try:
If you want to get your specs to run headless, try using poltergeist rather than capybara-webkit. poltergeist has several advantages which I described here: https://stackoverflow.com/a/24108439/634576
Selenium might just be a distraction, but, if you want to get it to work, be sure that your CI environment has the right version of Firefox. Each version of selenium-webdriver seems to need a narrow range of versions of Firefox. On CircleCI, you can configure circle.yml to install a specific version of Firefox. Right now we use selenium-webdriver 2.46.2 and Firefox 39.0.3, installed with the following in circle.yml:
dependencies:
pre:
- sudo apt-get update; sudo apt-get install firefox=39.0.3+build2-0ubuntu0.12.04.1
I don't know about Codeship.
I have experienced instability of my Selenium tests on CircleCI until I came across this post https://discuss.circleci.com/t/selenium-tests-timing-out/7765/2
After adding:
machine:
environment:
DBUS_SESSION_BUS_ADDRESS: /dev/null
to my circle.yml, my tests have become stable.
I want to test a simple sign in flow, which needs a existed user in the test database.
describe 'Signin page' do
before :each do
User.generate(:email => 'automatic_tester#gmail.com', :password => 'palmdrive', :first_name => 'Automatic', :last_name => 'Tester')
end
it 'signs in a user', :js => true do
signin
current_path.should == redirect_path
end
end
def signin
## Action to sign in the user
end
## Use DatabaseCleaner since selenium driver is used
DatabaseCleaner.strategy = :truncation
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before :each do
DatabaseCleaner.start
end
config.after :each do
DatabaseCleaner.clean
end
end
Because the way to create a user is a little bit more complicated, so I defined the User.generate method to create a user. To ensure it actually works, in the rails console with test environment, running User.generate(:email => 'automatic_tester#gmail.com', :password => 'palmdrive', :first_name => 'Automatic', :last_name => 'Tester')it successfully created a user in database. Comment out the before :each, the test suite passed successfully.
But the problem is running the codes above, the test fails. It was due to the user can't be created in the database. Why can't the User.generate method create a user?
In the spec_helper add:
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
solves the issue. Then no need to use the DatabaseCleaner either
Use create instead
User.create(:....)
Note that create will create a record in your database. Writing to the DB is an expensive operation and you may want to avoid that in some cases by using new rather than create.
A better approach is to use factories. See FactoryGirl https://github.com/thoughtbot/factory_girl
My situation is a follows:
I'm running application X
X uses the gem "core"
core extends the models of X with models A, B, C, D
In development this works perfectly. However when I run
(bundle exec) rake RAILS_ENV=staging RAILS_GROUPS=assets assets:precompile
it fails on
** Execute environment
rake aborted!
uninitialized constant A
I tried to fix this issue by placing Rails.application.eager_load! before the Application.initialize! in environments.rb, but I'm afraid that only led to other errors.
Is there a way to include models from an engine in a gem BEFORE the assets:precompile?
I read something about requiring them one by one instead of eager_load all, but the path to the gem differs for every system.
engine.rb in "core":
require 'paperclip'
module Core
class Engine < ::Rails::Engine
config.time_zone = 'Amsterdam'
config.encoding = "utf-8"
config.autoload_paths += %W(#{config.root}/lib/**)
config.generators do |g|
g.test_framework :rspec, :views => false, :fixture => true
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
end
initializer "core.load_app_instance_data" do |app|
Core.setup do |config|
config.app_root = app.root
end
app.class.configure do
#Pull in all the migrations from Commons to the application
config.paths['db/migrate'] += Core::Engine.paths['db/migrate'].existent
end
end
initializer "core.load_static_assets" do |app|
app.middleware.use ::ActionDispatch::Static, "#{root}/public"
end
end
end
I prefer to put any fix in the core gem instead of application X. However if it's not possible X is fine :)
Are you sure the "core" gem is loaded in the staging environment?
rspec-rails (2.7.0) rails (3.0.10)
post: Rails 3.1 Error Catching is irrelevant for me.
Code:
class ApplicationController < ActionController::Base
unless Rails.application.config.consider_all_requests_local
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
rescue_from Exception, :with => :render_500
rescue_from FunnyException, :with => :my_errors
def my_errors(exception)
#some stuff for production
puts "=======From top====#{Rails.application.config.consider_all_requests_local}"
end
else
rescue_from FunnyException, :with => :my_errors
def my_errors(exception)
#some stuff for development
puts "=====From bottom======#{Rails.application.config.consider_all_requests_local}"
end
end
end
This code perfectly works with production/development... problem is when I wanna test it with rspec. How to switch test case between environments?
I tried adding something like:
before do
Rails.application.config.consider_all_requests_local = true
end
I get:
...=====From bottom======true .=====From bottom======true .=====From
bottom======true .=====From bottom======true
so tried
before do
Rails.application.config.consider_all_requests_local = false
end
so I get:
...=====From bottom======false .=====From bottom======false .=====From
bottom======false .=====From bottom======false
How is that even possible? ... same with changing spec_helper
config.before(:each) do
Rails.application.config.consider_all_requests_local = false
end
unless is not working. Top section is unreachable with rspec... always hits Bottom why ? I assume it is somehow tied now with Rack... but is there any solution to dynamically change this behavior inside rspec?
regards
Ok I found quite easy solution
before do
Rails.application.config.consider_all_requests_local = false
load "application_controller.rb"
end
after do
Rails.application.config.consider_all_requests_local = true
load "application_controller.rb"
end
It is part of anonymous application controller test suite.
You have to add after block... because this change will persist through other suites.
Any improvements welcome :D
edit: Using spork and guard causes for me sometimes random errors... before :all seems to solve that problem
You also need to set Rails.application.config.action_dispatch.show_exceptions = true. But since Rails caches that value, this will only work if you run your spec on its own. Fortunately, you can change these options only for the current spec by mocking the config:
before do
method = Rails.application.method(:env_config)
expect(Rails.application).to receive(:env_config).with(no_args) do
method.call.merge(
"action_dispatch.show_exceptions" => true,
"action_dispatch.show_detailed_exceptions" => false,
"consider_all_requests_local" => false
)
end
end
Thanks to:
http://atodorov.org/blog/2016/04/27/changing-rails-consider_all_requests_local-in-rspec-fails/
https://thepugautomatic.com/2014/08/404-with-rails-4/#comment-1714338343
I found that with cucumber-rails the right way of doing it is to add the #allow-rescue tag.
The logic block is defined on class level, which gets evaluated during the class load time. This is why it will not go to 'else' even if you manually set it to false at run time.
I am also curious to know what's the best way to test this. My only clue is somehow reload or re eval ActionController, similar to reload! method in rails console.
I added some confirmation dialog boxes for my Rails 3.1 application and, prior to that, their corresponding tests. Following the model of Railscast #257, I added ':js => true' to the test, added database_cleaner and modified the spec_helper.rb file accordingly.
When I run the test, Firefox launches, Capybara-Selenium fills in the fields the the appropriate username and a password, but log-in fails (i.e., "invalid username/password".) Other tests that do not have ':js => true' and also login, do still pass.
I would like to add more javascript to my application in the future and I am avoiding solutions that would hack Capybara to get this to work (e.g., click 'OK' on all dialogs.)
Any ideas what I might be missing? Fail that, any suggestions on how to debug this problem?
Thank you.
You should set use_transactional_fixtures = false for your seleniumtests.
This can be done in the spec_helper.rb with
config.use_transactional_fixtures = false
for all your tests.
Or do this for a single testcase:
describe 'testcase' , :type => :request do
self.use_transactional_fixtures = false
it 'your test', :js => :true do
testing...
end
end
This happens because selenium-tests access the database in a different way. With transactional fixtures enabled, selenium will work on an empty database -> your user does not exist and you cannot login.
For normal tests you should use transactional fixtures because your tests run much faster.
As per Avdi Grimm's post (features a detailed explanation):
Gemfile:
group :test do
gem 'database_cleaner'
end
spec_helper.rb:
config.use_transactional_fixtures = false
spec/support/database_cleaner.rb:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
I had transactional fixtures disabled but adding the :js => true block to database_cleaner.rb did it for me.