I can't figure out how to give a file in one of my Factories. I'm using the default test suite of rails 5, Factory Bot, and Paperclip. This is the test I'm running:
require 'test_helper'
class AttachmentTest < ActiveSupport::TestCase
test "should be valid" do
p "should look into: #{ActionController::TestCase.fixture_path}"
ressource = build(:attachment)
assert ressource.valid?
end
end
This is my fixture:
include ActionDispatch::TestProcess
FactoryBot.define do
factory :attachment do
file { fixture_file_upload('files/invoice.pdf', 'application/pdf') }
association :attachable, factory: :mission
end
end
I've invoice.pdf in /Users/Daniel/GitHub/haeapua-rails/test/fixtures/files (both values copy / pasted here directly from terminal)
The trace I get
# Running:
"should look into: /Users/Daniel/GitHub/haeapua-rails/test/fixtures/"
E
Error:
AttachmentTest#test_should_be_valid:
RuntimeError: files/invoice.pdf file does not exist
test/factories/attachments.rb:5:in `block (3 levels) in <top (required)>'
test/models/attachment_test.rb:7:in `block in <class:AttachmentTest>'
bin/rails test test/models/attachment_test.rb:5
I'm missing something but can't figure out what. As I'm using FactoryBot, does it change the fixtures/files path? How could I know it?
Edit
Try to move the invoice to this places:
/Users/Daniel/GitHub/haeapua-rails/test/fixtures/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/factories/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/files/invoice.pdf
Related
I have a model that describes a patient (a Packet) which references the destination hospital and the transporting ambulance:
class Packet < ActiveRecord::Base
belongs_to :hospital
belongs_to :provider
validates_presence_of :hospital_id
validates_presence_of :provider_id
end
class Hospital < ActiveRecord::Base
has_many :packets
end
class Provider < ActiveRecord::Base
has_many :packets
end
and my RSpec specification:
require "rails_helper"
RSpec.describe Packet, :type => :model do
it "creates a new packet" do
hospital = Hospital.create(:name=>"Community Hospital")
provider = Provider.create(:name=>"Community Ambulance", :unit=>"Ambulance 3")
packet = Packet.new()
packet.hospital = hospital
packet.provider = provider
packet.save
end
end
RSpec fails with:
1) Packet creates a new packet
Failure/Error: packet.hospital = hospital
ActiveModel::MissingAttributeError:
can't write unknown attribute hospital_id
The thing I don't get is that the meat of my test (everything in the "it" block) runs fine in the rails console, with no errors. Why would I get the unknown attribute in the rspec test but not in the console?
Full stack trace:
Garys-MacBook-Air-2:EMSPacket gary$ rspec
F
Failures:
1) Packet creates a new packet
Failure/Error: packet.hospital = hospital
ActiveModel::MissingAttributeError:
can't write unknown attribute `hospital_id`
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute.rb:124:in `with_value_from_database'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute_set.rb:39:in `write_from_user'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute_methods/write.rb:74:in `write_attribute_with_type_cast'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute_methods/write.rb:56:in `write_attribute'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:92:in `write_attribute'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/attribute_methods.rb:373:in `[]='
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/associations/belongs_to_association.rb:80:in `replace_keys'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/associations/belongs_to_association.rb:14:in `replace'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/associations/singular_association.rb:17:in `writer'
# /Users/gary/.rvm/gems/ruby-1.9.3-p327/gems/activerecord-4.2.0/lib/active_record/associations/builder/association.rb:123:in `hospital='
# ./spec/models/packet_spec.rb:9:in `block (2 levels) in <top (required)>'
Finished in 0.14495 seconds (files took 7.49 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/packet_spec.rb:4 # Packet creates a new packet
RSpec is trying to test everystep inside the it block, that's why the test is failing but the console works. You have to create the record with the attributes and relations before testing it, and then test something.
The code you pasted for the tests id not actually testing anything.
Try to tests things that can really fail, like saving with errors, or creating without associations. But not repeating the steps inside the test.
describe "When creating new package" do
let(:hospital) {Hospital.create(attributes)}
let(:provider) {Provider.create(attributes)}
let(:packet) {Packet.create(hospital_id: hospital.id, provider_id: provider.id)}
it "should have the associations linked" do
expect(package.hospital_id).to eq(hospital.id)
expect(package.provider_id).to eq(provider.id)
end
end
EDITED:
Remember to run your migrations for the test database:
rake db:test:prepare
I like to use https://github.com/thoughtbot/shoulda-matchers in my tests
it would be
describe 'associations' do
it { should belong_to :hospital }
it { should belong_to :provider }
end
describe 'validations' do
it { should validate_presence_of :hospital_id }
it { should validate_presence_of :provider_id }
end
Anyway take a look at https://github.com/thoughtbot/factory_girl, it will help you with tests also.
Credit to Jorge de los Santos, the problem was the setup of my test database. Thanks Jorge!
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)
I am trying to test a carrierwave image upload to a model, using RSpec / capybara / Factory girl for Rails.
This specific test tests the validation that an image should be present.
At the moment, I have this code:
it "should accept a spotlight record with spotlight info" do
feature = create :feature, spotlight: true, spotlight_description: "description", spotlight_image: File.open(Rails.root.join "/app/assets/shopstar_logo_stamp.png")
expect(feature).to be_valid
end
But somehow the image isn't detected, and I get this error:
Failures:
1) Feature validations should accept a spotlight record with spotlight info
Failure/Error: feature = create :feature, spotlight: true, spotlight_description: "description", spotlight_image: File.open(Rails.root.join "/app/assets/shopstar_logo_stamp.png")
Errno::ENOENT:
No such file or directory - /app/assets/shopstar_logo_stamp.png
# ./spec/models/feature_spec.rb:32:in `initialize'
# ./spec/models/feature_spec.rb:32:in `open'
# ./spec/models/feature_spec.rb:32:in `block (3 levels) in <top (required)>'
How can I specify a path to an image in assets and use it for testing?
Or alternatively, what is a better way of testing a carrierwave image upload?
If this is an acceptance test/integration test you'll actually want to do it from the users perspective using capybara like this:
feature 'user uploads image' do
scenario '#Image' do
count = ImageModel.count
visit new_image_path
attach_file('css_selector_here', File.join(Rails.root, '/spec/support/herst.jpg'))
click_button('Submit')
expect(page).to have_content('Image uploaded successfully!')
expect(ImageModel.count).to eq(count + 1)
end
end
If you're after a unit test, do something like this with FactoryGirl in spec/factories/factory.rb
Factory.define :feature do |f|
f.spotlight true
f.spotlight_description "description"
f.spotlight_image { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec', 'support', 'feature', 'images', 'shopstar_logo_stamp.jpg')) }
end
now in your unit test you can run your test:
it "should accept a spotlight record with spotlight info" do
feature = create :feature
expect(feature).to be_valid
end
I am attempting to write a model test, like so:
require 'spec_helper'
describe Five9List do
before :each do
#five9_list = Five9List.new(name: 'test_list', size: '100')
end
describe "#new" do
it "takes two parameters and returns a Five9List object" do
#five9_list.should be_an_instance_of Five9List
end
end
describe "#name" do
it "returns the correct name" do
#five9_list.name.should eql "test_list"
end
end
describe "#size" do
it "returns the correct size" do
#five9_list.size.should eql 100
end
end
end
Currently, this succeeds and works fine. That's because my model is using attr_accessible, like so:
class Five9List < ActiveRecord::Base
attr_accessible :name, :size
end
If I want to get rid of attr_accessible and follow the rails 4 convention of using strong_params, how would I write that to where my rspec test would still succeed?
Adding this in my controller:
private
def five9_list_params
params.require(:five9_list).permit(:name, :size)
end
And removing attr_accessible does not work.
EDIT
Here is the error I receive from rspec .:
Failures:
1) Five9List#name returns the correct name
Failure/Error: #five9_list.name.should eql "test_list"
expected: "test_list"
got: nil
(compared using eql?)
# ./spec/models/five9_list_spec.rb:16:in `block (3 levels) in <top (required)>'
2) Five9List#size returns the correct size
Failure/Error: #five9_list.size.should eql 100
expected: 100
got: nil
(compared using eql?)
# ./spec/models/five9_list_spec.rb:22:in `block (3 levels) in <top (required)>'
Finished in 0.03303 seconds
4 examples, 2 failures, 1 pending
Failed examples:
rspec ./spec/models/five9_list_spec.rb:15 # Five9List#name returns the correct name
rspec ./spec/models/five9_list_spec.rb:21 # Five9List#size returns the correct size
Randomized with seed 20608
There's nothing wrong with your spec. I can only guess that you're not running Rails 4 or you've installed the ProtectedAttributes gem.
I followed a few tutorials and docs of FactoryGirl to use with RSpec. Currently I get one error when trying to use FactoryGirl.create:
describe "GenericRecipesController" do
describe "GET 'index'" do
it "displays list of generic recipes" do
generic_recipe = FactoryGirl.create(:generic_recipe)
visit '/recipe'
response.should be_success
end
end
end
And the error:
GenericRecipesController GET 'index' displays list of generic recipes
Failure/Error: generic_recipe = FactoryGirl.create(:generic_recipe)
NameError:
uninitialized constant GenericRecipe
# ./spec/integration/generic_recipes_spec.rb:8:in `block (3 levels) in <top (required)>'
The rest of code is there.
You can try this:
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
# ...
end
I think problem in a nesting model in module
Upd: delete file /spec/factories.rb, in file /spec/support/factories.rb make
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
When you will run tests, probably will see 'can not load table'. Make
rake db:migrate RAILS_ENV=test
and try again.
You don't seem to have a GenericRecipe model in your app. Factory Girl is looking for a Model called GenericReciper and can't find it.