I a have some code I'd like to refactor out of my step definitions and put them inside.. helpers?
Oh and please also say how to include them, I am really having a hard time finding any solid info on that.
Straight from the rspec documentation here: https://www.relishapp.com/rspec/rspec-core/docs/helper-methods/define-helper-methods-in-a-module#include-a-module-in-all-example-groups
Include a module in all example groups
Given a file named "include_module_spec.rb" with:
require './helpers'
RSpec.configure do |c|
c.include Helpers
end
RSpec.describe "an example group" do
it "has access to the helper methods defined in the module" do
expect(help).to be(:available)
end
end
When
I run rspec include_module_spec.rb
Then
the examples should all pass
You may also benefit from a a support/helpers folder Or equivalent which is covered pretty well here: How to include Rails Helpers on RSpec
Related
I am building an API with Rails, using the rails-api gem. I want to use cucumber-rails and the gem 'Airborne' to test it.
Airborne comes with some nice helper methods for testing API responses, which I want to have access to in my step definitions. I have done this kind of thing before in Sinatra, which was relatively straightforward to configure in the /features/env.rb file.
It seems, however, that with rails-cucumber the creation of the 'World' happens behind the scenes somewhere and I don't know how to extend it to use the Airborne module after it's been created.
I have tried the following:
Airborne.configure do |config|
config.rack_app = Rails.application
end
Cucumber::Rails::World.extend(Airborne)
When(/^I make a request for information about an event$/) do
get "/events/1"
end
Then(/^I receive the information as a JSON$/) do
expect_json {}
end
I am still getting a NoMethodError on #expect_json, which is an Airborne method.
So my question is: how can I extend the instance of World in the context of cucumber-rails?
Don't panic, the World has been saved. The solution is to wrap Airborne and whatever else in a module:
module MyHelpers
include Airborne
include Capybara::DSL
end
Then pass that:
World(MyHelpers)
I am currently testing a Rails(4.2) helper with Rspec(3) successfully. However, the test file setup is a bit cumbersome. How can I streamline the require and/or include lines?
# spec/helpers/nav_helper_spec.rb
require 'spec_helper'
require_relative '../../app/helpers/nav_helper' # this seems bulky
describe NavHelper do
include NavHelper # this seems repetitive
...
end
Thanks in advance!
If you have a "default" setup you probably have a rails_helper in addition to your spec_helper. If you don't mind loading all of the Rails directories in this one spec (a bit of a performance hit) you can require that instead of the spec_helper (cleaning up the requires). But there's nothing wrong with including only what you need, it will run faster.
Rspec will also mix in the helper for you if it knows the spec type. You can either include config.infer_spec_type_from_file_location! in your spec helper, or include the type in the describe declaration:
describe NavHelper, type: :helper do
Either way you'll be able to use something like expect(helper.method_name).to eq(result) without explicitly including the module.
After using RSpec for several projects, I'm giving minitest/unit a go. I'm liking it so far, but I miss using describe/context blocks to group my tests/specs in a logical way.
I know minitest/spec provides this functionality, but I like that minitest/unit feels a bit closer to barebones Ruby.
Are there any gems that provide describe/context support for minitest/unit? Or, should I just live with my long, unorganized test files in minitest/unit?
I know several folks coming from RSpec to minitest struggling with the same question. They love the ability to nest using describe/context blocks and want to continue in minitest. There are several solutions:
Use minitest's spec DSL: While there are minor differences, the spec DSL gives you most (all?) of the good parts of the rspec DSL. The big difference is the lack of context blocks. But you can just as easily use describe in its place and everything works as you'd expect.
Use directories and files: I prefer this option. I dislike scrolling through a 300 line test file, regardless whether its using the spec DSL or the classical xUnit style. I do not find nesting unrelated tests helpful. The same rules for comprehension for code applies to tests. So break it up. Create a directory and place several files within it.
Here is an example of how my test files are organized:
test/
models/
user/
authentication_test.rb
email_test.rb
reservation_test.rb
user_test.rb
username_test.rb
I use this structure whether I'm using the spec DSL or the xUnit style. When using the spec DSL I specify what I'm testing in my describe block like so:
require "minitest_helper"
describe User, :authentications do
before do
# ...
You can also throw multiple classes into one test file:
module PizzaTest
class Isolation < ActiveSupport::TestCase
test "is awesome by default" do
assert Pizza.new.awesome?
end
end
class Integration < ActiveSupport::TestCase
fixtures :all
test "is awesome too" do
pizzas('one-with-everything').awesome?
end
end
end
and even nest test classes:
class PizzaTest < ActiveSupport::TestCase
test "is awesome by default" do
assert Pizza.new.awesome?
end
class Integration < ActiveSupport::TestCase
fixtures :all
test "is awesome too" do
assert pizzas('one-with-everything').awesome?
end
end
end
I prefer this way (only a little bit) but I think it easier to follow:
class ConventionalNameTest < ActiveSupport::TestCase
class ContextTest < ConventionalNameTest
# so much stuff...
end
class AnotherContextTest < ConventionalNameTest
# and some more...
end
I'd like to include the request helpers (from ActionDispatch::Integration::RequestHelpers [ApiDock], like post and xhr methods) also in some specs outside of my controller specs. The problem is that these request helpers are only included in spec/controller and when a controller is described.
What do I have to include/require in those specs?
I am using RSpec 2 and Rails 3.
I just solved the problem by including the below code in my acceptance helper. If you are not Steak then just simply put it in spec helper or require it from somewhere else. post and xhr methods are now available in that spec regardless in what spec it is or in what directory you are.
The code is derived from RSpec::Rails::RequestExampleGroup
RSpec::Core::ExampleGroup.class_eval do
include ActiveSupport::Concern
include ActionDispatch::Integration::Runner
include RSpec::Rails::BrowserSimulators
def app
::Rails.application
end
def last_response
response
end
end
I know it's 4 years later and many things have of course changed, but since I stumbled on this question while searching how to make other tests behave like controller tests (and thus have post and get methods and the like) I wanted to point out this solution that works with RSpec 3: if you add this to the spec_helper
config.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: { file_path: /spec\/(api|integration)/
it will make all tests in the given path have support for controller methods.
I'm adding more rspec testing to my app and would like to test a ScoringMethods module, which is in /lib/scoring_methods.rb. So I added a /spec/lib directory and added scoring_methods_spec.rb there. I required spec_helper and set up the describe block as so:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe ScoringMethods do
describe "should have scorePublicContest method" do
methods = ScoringMethods.instance_methods
methods[0].should match(/scorePublicContest/)
end
end
Now methods[0] is a String and there is no problem matching the public method name with the regular expression. And the relative path to "spec_helper" is correct.
The problem is that the entire setup doesn't seem to use the rspec library.
Running the example yields:
./spec/lib/scoring_methods_spec.rb:7: undefined method `match' for Spec::Rails::Example::RailsExampleGroup::Subclass_1::Subclass_1:Class (NoMethodError)
...
The entire Expectation and Matcher support seems to be missing. To test my supposition, I changed a working helper spec by replacing "is_instance_of" to "is_foobar_of". That test simply fails and says "is_foobar_of" is not a method of the targeted object; that it, this entire Spec::Rails::Example... hierarchy isn't present.
I've tried using other matchers as well. I've tried "be_instance_of" and some others. It seems that I'm not including the rspec library properly.
Finally, ScoringMethods is a module, just the same way Helpers are modules. So I thought that it would be possible to test a module (as opposed to classes, such as Controllers and Models).
I'd greatly appreciate your thoughts on what I've done wrong. Perhaps there is a more effective way of testing library modules? Thanks!
You should include your test block in an "it" block. For example:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe ScoringMethods do
describe "should have scorePublicContest method" do
it "should have a scorePublicContest method" do
methods = ScoringMethods.instance_methods
methods[0].should match(/scorePublicContest/)
end
end
end
You will find that the methods names returned aren't guaranteed to be in the order they exist in the file.
A model we often use when testing Modules is to include the module in either a class created for the test (inside the spec file) or included inside the spec itself.