I'm new to Ruby and RSpec. I want to create very simple RSpec test:
# test_spec.rb
require 'spec_helper'
describe TestController do
puts(Time.now)
end
But when I run the code this way rspec test_spec.rb I get error:
`<top (required)>': uninitialized constant TestController (NameError)
Can you give me some idea where I'm wrong?
If you pass a class to describe, RSpec attempts to create an instance of that class. If the specified class does not exist, you get an error.
You can pass a string instead:
describe "my first test" do
it "does something" do
expect(1).to be_odd
end
end
Running the above:
$ rspec -fd test_spec.rb
my first test
does something
Finished in 0.00178 seconds (files took 0.10381 seconds to load)
1 example, 0 failures
This error is because after the describe you need a string with the description and you are leaving it without quotes.
describe '3pController' do
puts(Time.now)
end
But the tests should be structured as follows
a (describe) can have many (it) inside (a (it) is where the tests are)
one (decribe) can have more (describe) inside or can have (context), that these at the same time has many (it).
inside this link I will leave the documentation Basic structure
Here you can see a basic example of a test
describe 'sum 2 + 2 equal 4' do
it { expect(2 + 2).to eq(4)}
end
Related
What's the best way to define a class within the context of a spec, and not have it pollute the global namespace? How does the other file even get access to that constant?
bowling_spec.rb
require "spec_helper"
describe Bowling do
context "when validate is defined" do
let(:dummy_class) {
Class.new(described_class) do
METRICS_NAMESPACE = "ExtendedClass.Metrics.namespace"
end
}
it "does nothing" do
dummy_class
end
end
end
Spec - batting_spec.rb
require "spec_helper"
describe Batting do
context do
it "does weird thing" do
expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
end
end
end
If you run the individual spec file
rspec spec/batting_spec.rb
.
Finished in 0.00285 seconds (files took 0.12198 seconds to load)
1 example, 0 failures
If you run the spec which defines the dummy class
rspec spec/bowling_spec.rb spec/batting_spec.rb
.F
Failures:
1) Batting does weird thing
Failure/Error: expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
expected NameError but nothing was raised
# ./spec/batting_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 0.01445 seconds (files took 0.12715 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/batting_spec.rb:5 # Batting does weird thing
To reproduce the error: I created a repo: https://github.com/pratik60/rspec-pollution with updated Readme
Running rspec spec/batting_spec.rb spec/bowling_spec.rb
2 examples, 0 failures
Running rspec spec/bowling_spec.rb spec/batting_spec.rb
Gives the error you mention.
Using binding.pry:
describe Batting do
context do
it "does weird thing" do
require 'pry'
binding.pry
expect { self.class.const_get(:METRICS_NAMESPACE) }.to raise_error(NameError)
end
end
end
self.class.ancestors
[RSpec::ExampleGroups::Batting::Anonymous,
RSpec::ExampleGroups::Batting::Anonymous::LetDefinitions,
RSpec::ExampleGroups::Batting::Anonymous::NamedSubjectPreventSuper,
RSpec::ExampleGroups::Batting,
RSpec::ExampleGroups::Batting::LetDefinitions,
RSpec::ExampleGroups::Batting::NamedSubjectPreventSuper,
RSpec::Core::ExampleGroup,
Going down the inheritance tree
RSpec::Core::ExampleGroup::METRICS_NAMESPACE
(pry):4: warning: toplevel constant METRICS_NAMESPACE referenced by RSpec::Core::ExampleGroup::METRICS_NAMESPACE
=> "ExtendedClass.Metrics.namespace"
Checking the first object on the chain
Object::METRICS_NAMESPACE
=>"ExtendedClass.Metrics.namespace"
Even further
Class::METRICS_NAMESPACE
(pry):2: warning: toplevel constant METRICS_NAMESPACE referenced by Class::METRICS_NAMESPACE
=> "ExtendedClass.Metrics.namespace"
TL ; DR
As you said, when you did METRICS_NAMESPACE = "ExtendedClass.Metrics.namespace", you created a global namespace constant. (That is, a constant inside the uppermost ruby constant, Class)
Simply do this instead
Class.new(described_class) do
self.const_set('METRICS_NAMESPACE', "ExtendedClass.Metrics.namespace")
end
rspec spec/bowling_spec.rb spec/batting_spec.rb
Finished in 1.55 seconds (files took 0.08012 seconds to load)
2 examples, 0 failures
There is need to build a rspec framework where in we don't want to write feature files and respective step definitions, to run our tests.
So far this is what I have tried this is test run, if it works I will write more.
my_example_spec.rb
require 'rspec'
describe 'Mybehaviour' do
def testMethod
visit(LoginPage).test
end
end
login_page.rb
class LoginPage
include PageObject
page_url("#{FigNewton.base_url}/login")
element :username, "input[id='username']"
element :password, "input[id='password']"
element :submit, "input[id='submit']"
def test
puts "excellent"
end
end
I am using Rubymine when I right click my example file and run it , it gives me
Run options: include {:full_description=>/Mybehaviour/}
All examples were filtered out
0 examples, 0 failures, 0 passed
Finished in 0.000315 seconds
Process finished with exit code 0
Empty test suite.
So I changed it too:
require 'rspec'
describe 'Mybehaviour' do
it 'test Method' do
visit(LoginPage).test
true.should == false
end
end
it gives me:
Run options: include {:full_description=>/Mybehaviour/}
NameError: uninitialized constant LoginPage
./my_example_spec.rb:6:in `block (2 levels) in <top (required)>'
-e:1:in `load'
-e:1:in `<main>'
1 example, 1 failure, 0 passed
Finished in 0.001273 seconds
Process finished with exit code 1
What is the difference when I was using def and when I used it?
I understand that I need to initialize LoginPage, but where and why it is calling it as constant LoginPage instead of class LoginPage.
PS:New to rspec
My guess is you need to require login_page.rb in your spec_helper.rb (if you have one), or at the top of my_example_spec.rb
The test doesn't know about the LoginPage class, and so when it hits visit(LoginPage).test on line 6 it thinks LoginPage is an undefined constant. It doesn't know that you have defined it as a class.
Try adding:
require 'login_page'
either in your spec_helper.rb or after require 'rspec' in my_example_spec.rb
I am trying to test a helper in a Rails application. I am new at rspec and am having a hard time getting the test to run. Here is my test file:
require 'spec_helper'
describe "ServiceHoursHelpers" do
include ServiceHoursHelper
describe "test" do
it "should equal Jason" do
test.should eql("Test")
end
end
end
And here is my test file:
module ServiceHoursHelper
def test
"Test"
end
end
Here is the command I am running
rspec spec/helpers/service_hours_helper_spec.rb
It isnt succeeding and there are no errors, so obviously I am not hitting the code. What is it that I am missing?
Try run your test method like this:
helper.test.should eql("Test")
I've some tests that randomly fail, approx. 20% of times. It means that WITHOUT changing the code, each time that I run the tests 1 time out of 5 will fail with "Factory not registered" error. It's very weird.. :(
This is the consone output:
Failures:
1) Unit#new_from_string returns factor for metric conversions
Failure/Error: FactoryGirl.create :taza
ArgumentError:
Factory not registered: taza
# ./spec/models/unit_spec.rb:29:in `block (2 levels) in <top (required)>'
Finished in 0.29619 seconds
4 examples, 1 failure
Failed examples:
rspec ./spec/models/unit_spec.rb:22 # Unit#new_from_string returns factor for metric conversions
Randomized with seed 61727
And this is the code:
file: "unit_spec.rb"
require 'spec_helper'
describe Unit, "#new_from_string" do
it "parses the string and returns a Unit object" do
[some tests...]
FactoryGirl.find_definitions
u = FactoryGirl.create :taza
FactoryGirl.create :tbsp
[tests...]
end
it "returns factor for metric conversions" do
[tests not involving factory girl...]
# the following is line 29, that fails
FactoryGirl.create :taza
[tests...]
end
end
file "spec/factories/units.rb":
FactoryGirl.define do
factory :taza , :class => CustomUnit do
singular 'taza'
plural 'tazas'
physical_type Unit::VOLUME
equivalence_factor 200
equivalence_unit 'ml'
end
[other factories...]
end
I think the problem is on this line
FactoryGirl.find_definitions
Actually there is no need for this line when your factories are in correct directories(I see it is), and you put gem factory_girl_rails in Gemfile.
I think, 20% of time, the second test get run at first. At this time, there is no definition of Factory and the test failed. The other test has such definition and get passed. In other time, the first test run first so definition exists.
My suggestion:
Make sure you have factory_girl_rails, not factory_girl in Gemfile.
Remove that line of definition.
[optional but recommended] Put all definition in a single file spec/factories and remove all other factory files, if you don't have too much factories. This would be easier to manage.
So I'm using rspec to test my code as I'm going through the Rails Tutorial, and I keep getting this error when I test the code in listing 3.20. Everything checks out when I look at it with my eyeball, but RSpec doesn't seem to like it.
(Note that I just did one of the pages, not all three because they all give the same error)
james#tristan:~/rails_projects/sample_app$
rspec
spec/controllers/pages_controller_spec.rb
F...
Failures:
1) PagesController should have the
right title
Failure/Error: response.should have_selector("title",
expected following output to contain a | Home tag:
# ./spec/controllers/pages_controller_spec.rb:13:in
`block (2 levels) in '
Finished in 0.97999 seconds 4
examples, 1 failure
james#tristan:~/rails_projects/sample_app$
At the top of that spec file it says:
before(:each) do
#
# Define #base_title here.
#
end
Does your spec assign a value to #base_title?