Print running spec name - ruby-on-rails

I have an issue while running my specs for a rails application with rake, it freezes on a certain spec. I would like to see what spec is running.

I have pretty funny answer for you.
The problem as I see it is that the name of the spec is written after the success or failure. And in your case it will never happen.
So you can bring a custom formatter! Yes, it will work. The problem is that base formatter defines a lot of points like when group starts, when example starts, but available formatters ( http://github.com/rspec/rspec-core/tree/master/lib/rspec/core/formatters/ ) don't use the example_started method which is exactly the one you need.
Creating custom formatter is simple - just put this file into the spec/support/formatters/anxious_formatter.rb
class AnxiousFormatter < RSpec::Core::Formatters::DocumentationFormatter
def example_started(example)
message = "- #{example.description}"
output.puts message
output.flush
end
end
Then you can run this with:
spec -r spec/support/formatters/anxious_formatter.rb -f AnxiousFormatter spec/models/...
The example above is for Rails 3 and RSpec 2.0 - for previous version it will slightly differ. More about custom formatters (for Rails 2 and RSpec 1.x) can be found on the project wiki: https://github.com/dchelimsky/rspec/wiki/custom-formatters
Funny, isn't it?

Related

Execute an rspec test in Rails Console

Say I have a user_spec.rb for my User model, and I want to run that test inside the rails console.
My first thought is to execute the usual shell command:
exec("./spec/user_spec.rb")
But is there a simpler way to run the spec? I'm trying to automate some of the tests (and reinvent the wheel a little, yes), so being able to trigger an rspec test inside of another Ruby class seems ideal.
Edit:
output = `./spec/user_spec.rb`
This will provide the rspec output and $?.success? will then provide a pass fail value. Is this the best solution here? Or is there a way to call an RSpec class itself?
As pointed out by Anthony in his comment, you can use RSpec::Core::Runner to basically invoke the command line behavior from code or an interactive console. However, if you use something like Rails, consider that your environment is likely going to be set to development (or even production, if this is where you'll execute the code). So make sure that whatever you do doesn't have any unwanted side-effects.
Another thing to consider is that RSpec globally stores its configuration including all example groups that were registerd with it before. That's why you'll need to reset RSpec between subsequent runs. This can be done via RSpec.reset.
So putting it all together, you'll get:
require 'rspec/core'
RSpec::Core::Runner.run(['spec/path/to_spec_1.rb', 'spec/path/to_spec_2.rb'])
RSpec.reset
The call to RSpec::Core::Runner.run will output to standard out and return the exit code as a result (0 meaning no errors, a non-zero exit code means a test failed).
..
Finished in 0.01791 seconds (files took 17.25 seconds to load)
2 example, 0 failures
=> 0
You can pass other IO objects to RSpec::Core::Runner.run to specify where it should output to. And you can also pass other command line parameters to the first array of RSpec::Core::Runner.run, e.g. '--format=json' to output the results in JSON format.
So if you, for example, want to capture the output in JSON format to then further do something with it, you could do the following:
require 'rspec/core'
error_stream = StringIO.new
output_stream = StringIO.new
RSpec::Core::Runner.run(
[
'spec/path/to_spec_1.rb',
'spec/path/to_spec_2.rb',
'--format=json'
],
error_stream,
output_stream
)
RSpec.reset
errors =
if error_stream.string
JSON.parse(error_stream.string)
end
results =
if output_stream.string
JSON.parse(output_stream.string)
end
Run bundle exec rspec to run all tests or bundle exec rspec ./spec/user_spec.rb to run the specific test

Install generator won't see a method I defined

I'm trying to use my Engine in another app to test the install generator and it seems to be failing. I haven't used my install generator for a long time, so I'm not sure when it broke (or if it ever truly smoothly worked). My project is based off radar/forem, so I tried to borrow a lot of their code (including the generator).
Edit: My installer works for the engines test/dummy but not in other apps. Why?
GH issue: https://github.com/NJayDevelopment/mongoid_forums/issues/16
Here is the log:
$ rails g mongoid_forums:install
What is your user class called? [User]
What is the current_user helper called in your app? [current_user]
Defining mongoid_forums_user method inside ApplicationController...
insert app/controllers/application_controller.rb
Adding mongoid_forums initializer (config/initializers/mongoid_forums.rb)...
create config/initializers/mongoid_forums.rb
(erb):5:in `template': undefined method `per_page' for MongoidForums:Module (NoMethodError)
The route is successfully added, however the initializer/mongoid_forums.rb is a blank file. The method is defined exactly how radar/forem does it, what could be the error?
Here is the relevant code:
Per page method definition: https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/mongoid_forums.rb#L33
Mattr accessor:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/mongoid_forums.rb#L9
Initializer template:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/generators/mongoid_forums/install/templates/initializer.rb
Install generator at error point:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/generators/mongoid_forums/install_generator.rb#L47
Turns out when you try requiring mongoid_forums in pry, you'll see that an error involving decorators occurs. The issue is fixed here in my pull request to decorators: parndt/decorators#13
It's because of the way files are required and how load! is called over there.
Waiting on PR status, that is the same version that radar/forem uses as well.

After hook for the entire feature in cucumber

In cucucmber i want to run a step after all the scenarios in a feature are run, can I have an after hook for the entire feature, I currently have after hooks for each scenario.
I know its been a long time, but i havent been a user here for long but,
There is an exit hook that is used like this:
at_exit do
# Add code here
end
This should be placed in your env.rb file or the features/support directory
Here's a great link
It's a bit of a workaround, but you could just have scenarios at the beginning and the end of the feature for setup/teardown. Scenarios are run in the order that they are specified so as long as you have the setup scenario at the top and the teardown at the bottom then it works fine.
I also name the Scenario 'Scenario: feature setup' and 'Scenario: feature teardown' to make it more obvious when outputting the results to a formatter.
You can use a custom formatter, and use the after_feature method.
(I used to have a link with more information, but #katta just pointed out that its no longer available)
Sure, just tag your feature.
After('#mytag') do
#Do your magic here
end
This documentation might help: http://cukes.info/cucumber/api/ruby/latest/Cucumber/RbSupport/RbDsl.html#AfterStep-instance_method

The After hook in cucumber

Folks,
I am having some trouble working with the Afterhook. I have organized my tests in folders like this:
features/Accounts/accounts_api.feature
features/Accounts/step_definition/account_steps.rb
features/labs/create_lab.feature
features/labs/step_definition/labs_steps.rb
Now I have an After hook present in the step definition of the Accounts feature, I want that hook to run after every scenario of the "Accounts" feature, but I do not want it to run after every scenario of the "labs" feature. I tried this:
cucumber --tags #newlabs
the above should run all the scenarios present in the labs feature tagged as newlabs but what I am seeing is that once the scenario tagged as#newlabs runs the #after hook present in the step definition of Accounts starts to run. I am thinking why is this happening, am I using the hook in the wrong way or is my overall understanding of hooks wrong?
Thanks a lot for taking the time to respond, this helps a lot.
Hooks don't care what step definition script they're located in and will run for every scenario. Or, more specifically, your after hook will run after every scenario that runs, for every feature, regardless of the tags you pass in to Cucumber.
If you want a little more control over that, check out the Cucumber wiki page on hooks and look in the section called 'Tagged hooks'.
Possibly you define After hook in wrong place. Note that After hook (as well as other hooks) must be defined in the .rb, not in the .feature file. Common place for hooks is features/support/hooks.rb. You will define your hook this way:
# features/support/hooks.rb
After('#newlabs') do # will run after each scenario tagged with #newlabs
# your teardown ruby code
end
# features/Accounts/accounts_api.feature
#newlabs # tag all scenarious of this feature with #newlabs tag
Feature: your feature
Scenario: your scenario
Given: ...
When: ...
Then: ...
In cucumber output you won't see that After hook is executed (unless you output something to STDOUT from the hook definition) - hooks will run implicitly.

How to skip certain tests with Test::Unit

In one of my projects I need to collaborate with several backend systems. Some of them somewhat lacks in documentation, and partly therefore I have some test code that interact with some test servers just to see everything works as expected. However, accessing these servers is quite slow, and therefore I do not want to run these tests every time I run my test suite.
My question is how to deal with a situation where you want to skip certain tests. Currently I use an environment variable 'BACKEND_TEST' and a conditional statement which checks if the variable is set for each test I would like to skip. But sometimes I would like to skip all tests in a test file without having to add an extra row to the beginning of each test.
The tests which have to interact with the test servers are not many, as I use flexmock in other situations. However, you can't mock yourself away from reality.
As you can see from this question's title, I'm using Test::Unit. Additionally, if it makes any difference, the project is a Rails project.
The features referred to in the previous answer include the omit() method and omit_if()
def test_omission
omit('Reason')
# Not reached here
end
And
def test_omission
omit_if("".empty?)
# Not reached here
end
From: http://test-unit.rubyforge.org/test-unit/en/Test/Unit/TestCaseOmissionSupport.html#omit-instance_method
New Features Of Test Unit 2.x suggests that test-unit 2.x (the gem version, not the ruby 1.8 standard library) allows you to omit tests.
I was confused by the following, which still raises an error to the console:
def test_omission
omit('Reason')
# Not reached here
end
You can avoid that by wrapping the code to skip in a block passed to omit:
def test_omission
omit 'Reason' do
# Not reached here
end
end
That actually skips the test as expected, and outputs "Omission: Test Reason" to the console. It's unfortunate that you have to indent existing code to make this work, and I'd be happy to learn of a better way to do it, but this works.

Resources