I am trying to set up a test on a very basic ruby project(not rails) with the factorybot gem, but can't find a way to make it work. I followed the guide https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md
which is just installing the gem, run bundle install and add to my spec/spec_helper.rb this configuration:
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.before(:suite) do
FactoryBot.find_definitions
end
end
Then I created a factories/order_factories.rb file inside the spec folder like this:
FactoryBot.define do
factory :restaurant do
id { 3 }
cooking_time { 15 }
x { 0 }
y { 0}
end
factory :customer do
id { 1 }
x { 1 }
y { 1 }
end
end
and require it from the spec file of the object I want to test. The file is order_spec.rb like this :
require_relative './factories/order_factories'
let(:restaurant) { create(:restaurant) }
describe "Order", :order do
it "should be initialized with a hash of properties" do
properties = { :customer => 1, :restaurant => 3 }
order = Order.new(properties)
expect(order).to be_a(Order)
end
end
I already tried tones of other file organisation with proper require, but keep on having the FactoryBot constant not initialized. I wonder if my Gemfile.lock is not the origin of the problem:
GEM
remote: https://rubygems.org/
specs:
activesupport (6.1.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
concurrent-ruby (1.1.8)
diff-lcs (1.4.4)
factory_bot (6.1.0)
activesupport (>= 5.0.0)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
minitest (5.14.4)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.2)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
zeitwerk (2.4.2)
PLATFORMS
x86_64-darwin-18
DEPENDENCIES
factory_bot
rspec (~> 3.0)
BUNDLED WITH
2.2.16
Is there something I am missing here?
my spec/spec_helper.rb file :
require "factory_bot"
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.before(:suite) do
FactoryBot.find_definitions
end
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
I edited my order_spec.rb like this :
require_relative "./spec_helper"
require "factory_bot"
require_relative './factories/order_factories'
but still not working..
If you have a Rails model with an attribute named y, and you have a factory that sets this attribute, it freaks out FactoryBot. It's not FactoryBot's fault, see error https://github.com/thoughtbot/factory_bot/issues/1397
Solution is to set the y attribute via
add_attribute(:y) { 0 }
Related
When using nested forms with Oracle DB, Rails renders a decimal/float (e.g. 10010.0) instead of a fixnum (e.g. 10010) for all integer fields, including the id field, resulting in exceptions when updating. With SQLite it works as expected.
Why does this happen and where do things go wrong??
The following code demonstrates the issue:
Models
class Broker < ActiveRecord::Base
has_many :execution_groups, dependent: :destroy
accepts_nested_attributes_for :execution_groups, allow_destroy: true
end
class ExecutionGroup < ActiveRecord::Base
belongs_to :broker
end
View
= form_for( #broker, html: { class: 'form-horizontal'} ) do |f|
= f.fields_for :execution_groups, include_id: true do |eg_form|
= eg_form.hidden_field :id
Result in Browser when using SQLite
...
<input id="broker_execution_groups_attributes_0_id"
name="broker[execution_groups_attributes][0][id]"
type="hidden"
value="10010" />
...
This works as expected, the nested model is updated.
Result in Browser when using Oracle
...
<input id="broker_execution_groups_attributes_1_id"
name="broker[execution_groups_attributes][1][id]"
type="hidden"
value="10010.0" />
...
This crashes with a neat exception:
ActiveRecord::RecordNotFound in BrokersController#update
Couldn't find ExecutionGroup with ID=10010.0 for Broker with ID=10040
As to be expected, AR's not finding an ID like 10010.0 because there's only ID 10010 (without the .0) available.
Current Environment
.ruby-version (rvm configuration file)
jruby-1.7.19
Gemsfile.lock (excerpt)
rails (4.0.13)
actionmailer (= 4.0.13)
actionpack (= 4.0.13)
activerecord (= 4.0.13)
activesupport (= 4.0.13)
bundler (>= 1.3.0, < 2.0)
railties (= 4.0.13)
sprockets-rails (~> 2.0)
railties (4.0.13)
actionpack (= 4.0.13)
activesupport (= 4.0.13)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
activerecord-jdbc-adapter (1.3.19)
activerecord (>= 2.2)
activerecord-jdbcsqlite3-adapter (1.3.19)
activerecord-jdbc-adapter (~> 1.3.19)
jdbc-sqlite3 (>= 3.7.2, < 3.9)
jdbc-sqlite3 (3.8.11.2)
config/database.yml
Oracle via JDBC
development:
url: jdbc:oracle:thin:#mydbhost:1522:myschema
username: myuser
password: secret
SQLite
development:
adapter: sqlite3
database: db/development.sqlite3
Solution
Digging deeper into ActiveRecord I found that specifically overwriting the id_before_type_cast method for the model does the trick:
class ExecutionGroup < ActiveRecord::Base
belongs_to :broker
def id_before_type_cast
Integer( self.id ) unless self.id.nil?
end
end
While this does the trick, the *_before_type_cast needs to be defined for any Fixnum column or you'll get the same problem with the values.
Debugging details:
Stepping into ActionView::Helpers::Tags::Base.value_before_type_cast(object) I get the following status:
# for both SQLite and Oracle
object.class == ExecutionGroup # -> true
object.respond_to?(method_before_type_cast) # -> true
# SQLite
object.id_before_type_cast # -> {Fixnum} 10010
# Oracle
object.id_before_type_cast # -> {BigDecimal} 10010.0
After applying the fix both Oracle and SQLite show the same behaviour.
object.id_before_type_cast # -> {Fixnum} 10010
I have problem with using rspec-mocks.
bundle list shows:
Gems included by the bundle:
* CFPropertyList (2.2.8)
* builder (3.2.2)
* bundler (1.7.12)
* ci_reporter (1.9.3)
* diff-lcs (1.2.5)
* excon (0.44.0)
* facter (2.4.0)
* hiera (1.3.4)
* json_pure (1.8.2)
* metaclass (0.0.4)
* mocha (1.1.0)
* puppet (3.7.4)
* puppet-lint (1.1.0)
* puppet-syntax (1.4.1)
* puppetlabs_spec_helper (0.8.2)
* rake (10.4.2)
* rcov (1.0.0)
* rspec (3.1.0)
* rspec-core (3.1.7)
* rspec-expectations (3.1.2)
* rspec-legacy_formatters (1.0.0)
* rspec-mocks (3.1.3)
* rspec-puppet (1.0.1)
* rspec-support (3.1.2)
My rspec:
require 'spec/spec_helper'
describe 'My behaviour' do
it 'should do something' do
t = double()
end
end
By my best knowledge, I done everything right, however I keep getting this kind of errors during test execution:
1) My behaviour should do something
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `double' for #<RSpec::ExampleGroups::MyBehaviour:0x10275f168>
# ./spec/puppet/util/network_device/netapp_e/my_example_spec.rb:8
And the same goes for every method from rspec-mocks such as: 'allow', 'receive', etc.
Does anybody know, why this is happening?
Did you declare that you want to use RSpec mocks? Usually this is done in the spec_helper.rb file like this:
RSpec.configure do |config|
config.mock_framework = :rspec
end
I receive the following error when I run my spec file:
I've read over the following questions to no avail:
ArgumentError: wrong number of arguments (0 for 1)
FactoryGirl issues - `factory': wrong number of arguments (0 for 1) (ArgumentError)
rspec not running because of factorygirl
ArgumentError in rspec
I'm not sure that I've set up my Ruby project with rspec and factory_girl correctly. Here are the associated files:
player.rb
class Player
attr_accessor :name
def initialize(string)
#name = string
end
end
players.rb (factory)
require './player'
FactoryGirl.define do
factory :player do
name "Cliff Levingston"
end
end
player_spec.rb
require 'spec_helper'
describe 'Player' do
context 'when created' do
it "should include a #name" do
player1 = FactoryGirl.build :player
# player1.name = "Gerald"
expect(player1.name).to eql "Cliff Levingston"
end
end
end
Gemfile
source 'hhtps://rubygems.org'
gem 'guard'
gem 'guard-shell'
gem 'rspec'
gem 'factory_girl', '~> 4.0'
gem 'rb-fsevent', '~> 0.9'
Gemfile.lock
GEM
remote: hhtps://rubygems.org/
specs:
activesupport (4.0.1)
i18n (~> 0.6, >= 0.6.4)
minitest (~> 4.2)
multi_json (~> 1.3)
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
atomic (1.1.14)
celluloid (0.15.2)
timers (~> 1.1.0)
coderay (1.0.9)
diff-lcs (1.2.5)
factory_girl (4.3.0)
activesupport (>= 3.0.0)
ffi (1.9.3)
formatador (0.2.4)
guard (2.2.3)
formatador (>= 0.2.4)
listen (~> 2.1)
lumberjack (~> 1.0)
pry (>= 0.9.12)
thor (>= 0.18.1)
guard-shell (0.5.1)
guard (>= 1.1.0)
i18n (0.6.5)
listen (2.2.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.4)
method_source (0.8.2)
minitest (4.7.5)
multi_json (1.8.2)
pry (0.9.12.2)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
ffi (>= 0.5.0)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.7)
rspec-expectations (2.14.4)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.4)
slop (3.4.6)
thor (0.18.1)
thread_safe (0.1.3)
atomic
timers (1.1.0)
tzinfo (0.3.38)
PLATFORMS
ruby
DEPENDENCIES
factory_girl (~> 4.0)
guard
guard-shell
rb-fsevent (~> 0.9)
rspec
spec_helper.rb
require 'rspec'
require 'factory_girl'
RSpec.configure do |config|
# FactoryGirl
FactoryGirl.find_definitions
# Use color in STDOUT
config.color_enabled = true
# Use color not only in STDOUT but also in pagers and files
config.tty = true
# Use the specified formatter
config.formatter = :documentation # :progress, :html, :textmate
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
I'd like to better understand what I omitted or need to add in order to remove the ArgumentError (0 for 1).
Thanks in advance.
I believe the issue is with your player model requiring an argument at initialization.
Try this instead:
class Player
attr_accessor :name
def initialize(options={})
#name = options[:name]
end
end
When FactoryGirl initializes the model, it will initialize with a nil name attribute like this:
1.9.3p448 :013 > Player.new
#<Player:0x000000017acff0 #name=nil>
You can then define the name as you intend in your commented out line. This will also allow you to initialize a Player with a hash like:
1.9.3p448 :012 > Player.new(name: "something")
#<Player:0x00000003b53008 #name="something">
I just upgraded to watir 4.0.2 from watir 2.0.4 and i am getting the below error,
C:/Ruby187/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:60:in `gem_original
_require': no such file to load -- watir/testcase (LoadError)
I searched about the error and was not able to find a solution to it.
Gem List
abstract (1.0.0)
actionmailer (3.2.8, 3.0.0)
actionpack (3.2.8, 3.0.0)
activemodel (3.2.8, 3.0.0)
activerecord (3.2.8, 3.0.0)
activeresource (3.2.8, 3.0.0)
activesupport (3.2.8, 3.0.0)
addressable (2.3.2)
akami (1.2.0)
arel (3.0.2, 1.0.1)
Ascii85 (1.0.1)
builder (3.0.0, 2.1.2)
bundler (1.0.22)
childprocess (0.3.6)
commandline (0.7.10)
commonwatir (4.0.0, 2.0.4)
erubis (2.7.0, 2.6.6)
ffi (1.1.5)
gyoku (0.4.6)
hike (1.2.1)
hoe (3.0.8)
httpi (0.9.7)
i18n (0.6.1, 0.4.2)
journey (1.0.4)
libwebsocket (0.1.5)
mail (2.4.4, 2.2.19)
mime-types (1.19, 1.18)
mini_magick (3.2.1)
multi_json (1.3.6)
mysql2 (0.3.11 x86-mingw32, 0.2.18 x86-mingw32, 0.2.6 x86-mingw32)
nokogiri (1.5.5 x86-mingw32)
nori (1.1.3)
pdf-reader (1.1.1)
polyglot (0.3.3)
rack (1.4.1, 1.2.5)
rack-cache (1.2)
rack-mount (0.6.14)
rack-ssl (1.3.2)
rack-test (0.6.2, 0.5.7)
rails (3.0.0)
railties (3.0.0)
rake (0.8.7)
rautomation (0.7.3, 0.6.3)
ruby-rc4 (0.1.5)
rubygems-update (1.8.24)
rubyzip (0.9.9)
s4t-utils (1.0.4)
savon (0.9.9)
selenium-webdriver (2.26.0)
sprockets (2.1.3)
sqlite3 (1.3.6 x86-mingw32)
sqlite3-ruby (1.3.3)
subexec (0.0.4)
text-format (1.0.0)
text-hyphen (1.0.2)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
tzinfo (0.3.33)
user-choices (1.1.6.1)
wasabi (2.1.0)
watir (4.0.2 x86-mingw32, 2.0.4)
watir-classic (3.3.0)
watir-webdriver (0.6.2)
websocket (1.0.6)
win32-api (1.4.8 x86-mingw32)
win32-process (0.6.6)
win32screenshot (1.0.7)
windows-api (0.4.2)
windows-pr (1.2.2)
xml-simple (1.1.1)
Ruby Version:ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32]
Any idea on this?
watir/testcase was removed from Watir recently. I can not find when it was removed, but the information is in CHANGES file or in Git history.
While it would probably be better to move away from Watir::TestCase, if you really need or want to use it, you can re-create it by copying the files from 3.0.
Assume you are using Ruby 1.8, which still has the test-unit gem installed by default, you can do the following:
1) Create a file named 'watir_testcase.rb' with the following code, which is basically a copy of the testcase.rb and assertions.rb file from 3.0:
require 'watir-classic'
require 'test/unit'
require 'test/unit/assertions'
module Watir
# Verification methods used by Watir::TestCase
module Assertions
include Test::Unit::Assertions
# Log a failure if the boolean is true. The message is the failure message logged.
# Whether true or false, the assertion count is incremented.
def verify boolean, message = 'verify failed.'
add_assertion
add_failure message.to_s, caller unless boolean
end
def verify_equal expected, actual, message=nil
full_message = build_message(message, <<EOT, expected, actual)
<?> expected but was
<?>.
EOT
verify(expected == actual, full_message)
end
def verify_match pattern, string, message=nil
pattern = case(pattern)
when String
Regexp.new(Regexp.escape(pattern))
else
pattern
end
full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
verify(string =~ pattern, full_message)
end
end
end
module Test::Unit::Assertions
def assert_false(boolean, message=nil)
_wrap_assertion do
assert_block("assert should not be called with a block.") { !block_given? }
assert_block(build_message(message, "<?> is not false.", boolean)) { !boolean }
end
end
end
module Watir
# This is a 'test/unit' testcase customized to exeucte test methods sequentially by default
# and extra assertions
#
class TestCase < Test::Unit::TestCase
include Watir::Assertions
##order = :sequentially
def initialize name
throw :invalid_test if name == :default_test && self.class == Watir::TestCase
super
end
class << self
attr_accessor :test_methods, :order
def test_methods
#test_methods ||= []
end
def order
#order || ##order
end
def default_order= order
##order = order
end
def sorted_test_methods
case order
when :alphabetically then test_methods.sort
when :sequentially then test_methods
when :reversed_sequentially then test_methods.reverse
when :reversed_alphabetically then test_methods.sort.reverse
else raise ArgumentError, "Execute option not supported: #{#order}"
end
end
def suite
suite = Test::Unit::TestSuite.new(name)
sorted_test_methods.each do |test|
catch :invalid_test do
suite << new(test)
end
end
if (suite.empty?)
catch :invalid_test do
suite << new(:default_test)
end
end
return suite
end
def method_added id
name = id.id2name
test_methods << name if name =~ /^test./
end
def execute order
#order = order
end
end
public :add_assertion
end
end
2) In your test case files, change the:
require 'watir/testcase'
to require the newly created file:
require './watir_testcase'
(ensuring that the path is correct for wherever you saved the file)
In my Rakefile, I have a task defined like this:
namespace :test do
desc "Run all specs."
RSpec::Core::RakeTask.new(:spec) do |t|
t.pattern = 'spec/**/*_spec.rb'
t.verbose = false
end
RSpec::Core::RakeTask.new(:coverage) do |t|
t.rcov = true
t.rcov_opts = %q[--exclude "spec"]
t.verbose = true
end
end
When running test:coverage, I get this:
./spec/foo_spec.rb:3: undefined method `describe' for main:Object (NoMethodError)
from /Library/Ruby/Gems/1.8/gems/rcov-0.9.9/bin/rcov:516:in `load'
from /Library/Ruby/Gems/1.8/gems/rcov-0.9.9/bin/rcov:516
from /usr/bin/rcov:19:in `load'
from /usr/bin/rcov:19
rake aborted!
ruby -S rcov -Ispec:lib --exclude "spec" "./spec/foo_spec.rb" failed
Below my gem list:
diff-lcs (1.1.2)
rake (0.8.7)
rcov (0.9.9)
rspec (2.3.0)
rspec-core (2.3.1)
rspec-expectations (2.3.0)
rspec-mocks (2.3.0)
Any idea? Thanks in advance.
The solution, from David Chelimsky:
http://rubyforge.org/pipermail/rspec-users/2010-December/019077.html
require "rspec"
Cheers.