I learned how to test image file uploading from this excellent article:
https://jeffkreeftmeijer.com/2010/2014/using-test-fixtures-with-carrierwave/
Adapting those ideas for my app, I've got this test that works:
test "uploads an image" do
pic = Picture.create(:image => fixture_file_upload('/files/DJ.jpg','image/jpg'), :user => User.first)
assert(File.exists?(pic.reload.image.file.path))
end
I would like to test the same thing for the user interface, so I would think that this test would also pass:
test "create new picture" do
capybara_login(#teacher_1)
click_on("Upload Pictures")
fill_in "picture_name", with: "Apple"
attach_file('picture[image]', Rails.root + 'app/assets/images/apple.png')
check("check_#{#user_l.id}")
check("check_#{#admin_l.id}")
click_on ("Create Picture")
#new_pic = Picture.last
assert_equal "Apple", #new_pic.name
assert #new_pic.labels.include?(#user_l)
assert #new_pic.labels.include?(#admin_l)
assert #teacher_1, #new_pic.user
assert File.exists?(#new_pic.reload.image.file.path)
end
But it fails on the last line, asserting the existence of the file.
Below are the parts of my test_helper that I thought would be relevant. I can show the whole test_helper if someone thinks it necessary.
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
require 'capybara/rails'
Minitest::Reporters.use!
CarrierWave.root = 'test/fixtures/files'
class CarrierWave::Mount::Mounter
def store!
# Not storing uploads in the tests
end
end
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
include ApplicationHelper
include ActionDispatch::TestProcess
CarrierWave.root = Rails.root.join('test/fixtures/files')
def after_teardown
super
CarrierWave.clean_cached_files!(0)
end
end
Everything appears to be working as expected in development and production.
Thank you in advance for any insight.
Related
After upgrading my rails app to 4.2, I started writing automated tests.
I started by doing something super simple:
class SimpleTest < ActionDispatch::IntegrationTest
test 'Browse a page' do
assert true
get '/'
assert_response :success
end
end
But when I:
▶ rake test
▶ bin/rake test
Nothing happens. No error, no blocking, process finishes, just nothing.
Did I miss something?
I was missing the require 'test_helper' at the beginning of my test, containing:
# /test/test_helper.rb
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
# Setup all fixtures in test/fixtures/*.yml 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...
end
I'm preparing some integration tests on my rails 3.2.16 application, I figured that, in my user scenarios, I have several calls that I repeat over many tests, so I would like to DRY them up, by placing them in a separate common module,
for example I have created /test/integration/my_test_helpers.rb:
require 'test_helper'
module MyTestHelper
def login_user(email, password, stay = 0)
login_data = {
email: email,
password: password,
remember_me: stay
}
post "/users/sign_in", user: login_data
assert_redirected_to :user_root
end
end
and tried to use it in my integration test:
require 'test_helper'
require "./my_test_helpers.rb"
class CreateCommentTest < ActionDispatch::IntegrationTest
setup do
#user = users(:user1)
end
test "create comment" do
login_user #user.email, "password", 1
end
end
I get exception:
`require': cannot load such file -- ./my_test_helpers.rb (LoadError)
How can I load the module? is it right to make MyTestHelpers a module?
You should put your helper in support folder(test/support/my_test_helpers.rb, or something) and load module in test_helper.rb:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require_relative "./support/my_test_helpers"
require "minitest/rails"
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
fixtures :all
# Add more helper methods to be used by all tests here...
end
Do not remember include your module:
require 'test_helper'
class CreateCommentTest < ActionDispatch::IntegrationTest
include MyTestHelper
setup do
#user = users(:user1)
end
test "create comment" do
login_user #user.email, "password", 1
end
end
Getting the following when running my capybara rails tests with "rake test". Problem seems to be url helpers I'm using in my application.html.erb:
DashboardLoginTest#test_login_and_check_dashboard:
ActionView::Template::Error: arguments passed to url_for can't be handled. Please require routes or provide your own implementation
app/views/layouts/application.html.erb:29:in `_app_views_layouts_application_html_erb__938277815294620636_4045700'
test/integration/dashboard_login_test.rb:6:in `block in <class:DashboardLoginTest>'
Here's line 29 in application.html.erb that its complaining about:
<%= link_to("asdf", root_path, {:class => 'brand'}) %>
Here's what the test looks like:
test "login and check dashboard" do
visit("/")
assert page.has_content?("welcome")
end
Here's my test_helper.rb:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'factory_girl'
require 'capybara/rails'
include Warden::Test::Helpers
Warden.test_mode!
def main_app
Rails.application.class.routes.url_helpers
end
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
fixtures :all
end
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
include Rails.application.routes.url_helpers
def sign_in(user = nil)
if user.nil?
user = FactoryGirl.create(:user)
$current_user = user
end
login_as(user, :scope => :user)
user.confirmed_at = Time.now
user.save
end
end
I'm using capybara with minitest on Rails 2.3.14. Like most applications, this one also requires login to do anything inside the site. I'd like to be able to login once per test-suite and use that session throughout all tests that are run. How do I refactor that to the minitest_helper? Right now my helper looks something like this:
#!/usr/bin/env ruby
ENV['RAILS_ENV'] = 'test'
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
gem 'minitest'
gem 'capybara_minitest_spec'
require 'minitest/unit'
require 'minitest/spec'
require 'minitest/mock'
require 'minitest/autorun'
require 'capybara/rails'
require 'factory_girl'
FactoryGirl.find_definitions
class MiniTest::Spec
include FactoryGirl::Syntax::Methods
include Capybara::DSL
include ActionController::URLWriter
before(:each) do
# .. misc global setup stuff, db cleanup, etc.
end
after(:each) do
# .. more misc stuff
end
end
thanks.
Here’s an example of multiple sessions and custom DSL in an integration test
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
fixtures :users
test "login and browse site" do
# User avs logs in
avs = login(:avs)
# User guest logs in
guest = login(:guest)
# Both are now available in different sessions
assert_equal 'Welcome avs!', avs.flash[:notice]
assert_equal 'Welcome guest!', guest.flash[:notice]
# User avs can browse site
avs.browses_site
# User guest can browse site as well
guest.browses_site
# Continue with other assertions
end
private
module CustomDsl
def browses_site
get "/products/all"
assert_response :success
assert assigns(:products)
end
end
def login(user)
open_session do |sess|
sess.extend(CustomDsl)
u = users(user)
sess.https!
sess.post "/login", :username => u.username, :password => u.password
assert_equal '/welcome', path
sess.https!(false)
end
end
end
Source : http://guides.rubyonrails.org/testing.html#helpers-available-for-integration-tests
I recently switched a very simple rails app from rspec to minitest. I also use capybara and factory_girl.
I have 3 separate integration test files, all of which involve logging the user in using something along the lines of:
before(:each) do
user = Factory(:user)
visit login_path
fill_in "Email", :with => user.email
fill_in "Password", :with => user.password
click_button "Log in"
end
After I switched to minitest, it seems as if the sessions ceased to tear down after each test. For instance, I would test login using the above code in a test file named "users_integration_test.rb" and when it begins running another test file, say "sessions_integration_test.rb", the user is already logged in before I can log in again using the above code.
My question is: Is this an intentional difference between rspec and minitest, and I simply need to logout the user after each test? Or did I make a mistake setting up minitest?
I am using the same minitest_helper file as in the Minitest Railscast.
I don't know the difference but below code may work.
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "minitest/autorun"
require "capybara/rails"
require "active_support/testing/setup_and_teardown"
class IntegrationTest < MiniTest::Spec
include Rails.application.routes.url_helpers
include Capybara::DSL
after do
reset_session!
end
register_spec_type(/integration$/, self)
end
class HelperTest < MiniTest::Spec
include ActiveSupport::Testing::SetupAndTeardown
include ActionView::TestCase::Behavior
register_spec_type(/Helper$/, self)
end
I got it to tear down correctly with this. Hope it helps!
Mr. Maeshima's answer may very well work too. I have not tried.
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "minitest/autorun"
require "capybara/rails"
require "active_support/testing/setup_and_teardown"
Dir[Rails.root.join("test/support/**/*.rb")].each {|f| require f}
DatabaseCleaner.strategy = :truncation
class IntegrationTest < MiniTest::Spec
include Rails.application.routes.url_helpers
include Capybara::DSL
register_spec_type(/integration$/, self)
Capybara.javascript_driver = :selenium
after do
DatabaseCleaner.clean # Truncate the database
Capybara.reset_sessions! # Forget the (simulated) browser state
Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
end
end
class HelperTest < MiniTest::Spec
include ActiveSupport::Testing::SetupAndTeardown
include ActionView::TestCase::Behavior
register_spec_type(/Helper$/, self)
end