RSpec/Capybara without Rails Setup for Page Objects/Support Files? - ruby

So im going to be writing a framework that uses Rspec/Capybara and Selenium to do some automation testing on an app. Im using purely RSpec (no rails) and im having some difficulties in getting everything setup correctly.
The problem I am running into is when im trying to include page object files into my specs. Right now my directory looks like:
spec (Actual .spec files go here, spec_helper is also here)
spec/support (Page Object Files go here)
In my page object files my first problem is it can't find the Capybara DSL unless I do: include Capybara::DSL at the top of each page object file (Which apparently isn't a good idea according to the warning message it gives me)
The other problem is that including my page object files in my tests Im needing to do a require_relative to the specific file (Which is sort of a pain) otherwise it can't find the class.
Is there something in spec_helper that will fix this? Im not an expert in ruby so I assume Im missing something. The Capybara DSL problem I can't figure out either for example requiring require 'capybara/rspec' doesn't seem to help either.

You have a few options for Capybara::DSL -
Include Capybara::DSL into whatever base class you're using for your PageObjects so the Capybara methods are available in that class (as opposed to on the global object) - ie. the include Capybara::DSL goes inside the class definition - not at the top of the file.
Keep an instance of Capybara::Session in your page object instances and call all capybara methods on that session instance - #my_session.find(...), etc.
Always use Capybara.current_session when calling Capybara methods - Capybara.current_session.find(...), etc
As for the require issue -- you can either use require_relative to specify files to require based from the current file, or you use require and specify the location from the projects root (current working directory). If you have a directory of files you want loaded you can add something like the following to your spec_helper.rb to tell it to load all the files
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f }

Related

World vs Include in cucumber/ruby

Can anyone tell me the difference between include and World? in my env.rb file I want to expose a module, and I can't really see the difference between the approaches...
Module example:
module Test do
...
end
In my env.rb file:
World(Test)
or
include Test
Besides that, can anyone state the pros/cons of using World rather than include in cucumber/ruby?
World(Test) is the preferred method.
The purpose to using World(Test) is that you don't pollute the global namespace yet you still have all the functionality of that module available in your stepdefs.

Testing a ruby class without the required module files

I'm working on a project in Ruby on Rails. We have a controller action that uses a module within a gem. This gem isn't finished yet and it isn't on the file system.
I was told to mock the module in order to test the controller. Is there a way to test this without the actual gem? Would mocking the 'require' calls work?
We are currently using Mocha for Mocking and Stubbing.
There is a way to mock the imports in python. Maybe there is a similar answer to mocking the requires in ruby.
How to mock an import
Or please let me know what would be the best way to handle this.
Update: The person who told me to mock it, suggested adding a stub file, but that would require adding test code to the controller and I don't want to do that.
Update 2: The controller uses methods declared in the Module.
If you are writing tests to mock the method calls, they would fail. For example,
controller.should_receive(:method_in_non_existent_module).with(args) #=> errors
In a correct Red->Green TDD scenario , this is alright because the next step would be to require the gem/file, include the module and add the method call in the controller and make the test pass. But you'll not be able to make the tests pass since you can't require the file because it doesn't exist yet.
May be the developer who asked you to mock the method meant to do so not in your tests, but in your actual code. For example, he's writing a gem 'dongle-jokes' which has a method that gets the most popular dongle joke from the most recent tech conference. He doesn't want the gem to be a blocker for you to finish the controller and the views so he asks you to use a dummy interface that spits out a dummy response.
Write the tests that fail
Add a file lib/dongle-jokes.rb
Add the following to that file.
module DongleJokes
def joke
"Dongle jokes aren't funny!"
end
end
Require the file and include the module, use the method in the controller.
The test should pass now. You can remove lib/dongle-jokes.rb when you start using the actual gem.
If you're working in Rails you shouldn't need to add a require to the controller anyway, as when you add the gem to your gemfile it will be required automatically on Rails startup.
What your colleague most likely meant was that you should stub the module itself. Are you using rspec for your tests? If so you should be able to use stub_const. Let's say the module is called Payments. You can then write test code like the following:
before do
stub_const("Payments", stub)
Payments.stub(process: "payments successful")
end

Espresso Enginery

i use framwork Espresso with Enginery generator (Ruby gems). I create new project, and not understand how work this application. I will work with Espresso. Explain me struct Expresso Application, please.
I can run this apllication: rackup config.ru
I can edit controllers, but i not understand depending between ruby scripts in this project.
i run projects, but why this work it?
config.ru
require File.expand_path('../base/boot', __FILE__)
puts App.urlmap
run App
in project not /base/boot directory.
requiring '../base/boot' will actually load dependencies, controllers, models etc. and build the application.
The application are stored under App constant, so you can access it from different files:
https://github.com/espresso/enginery/blob/master/app/base/base/boot.rb#L9
puts App.urlmap will display all the routes to be served by app.
And run App will start your app.
You can also start app by ruby app.rb, then you do not need to pass server/port at startup.
Instead you'll set them in config/config.yml, like this:
development:
server: Thin
port: 5252
The config.ru file looks quite normal for a rack start-up file. You would start the application from the project folder, with a command like:
rackup -p 8080
The following line:
require File.expand_path('../base/boot', __FILE__)
will load in the ../base/boot file (similar to require_relative, but also works with older Ruby e.g. 1.8.7), which I would guess requires the dependencies where App is defined. The class or module App will implement a call method. To start the server, the rack host calls App.new (which is called due to run App) and then on each request it will call .call( env ) on the resulting object (the object doesn't have to be an App object, but in simpler frameworks it will be).
The variable env contains all the details of the request and the rack environment that can be inspected to fetch details of the current path, cookies, query params etc. Typically access to this data is abstracted through Sinatra and Espresso helper methods that you will use.
The Sinatra and Espresso helper methods look like they are doing magic declarations, but they are just normal methods. Usually they do some calculation and then stash a code block/lambda for rack to call later. Sinatra's get is like this . . . it isn't true declarative code. Instead, when the controller is parsed, it just takes the code block and tells the application object to call it (later) when the path matches.

How to work with classes and dependences in ruby

I have changed this question to better reflect what it is I do not understand.
For example if I try to access the methods in the railties class AppBuilder.
require 'rails/generators/rails/app/app_generator'
g = Rails::AppBuilder.new
puts g.rakefile.inspect
I get an error message activesupport-3.1.3/lib/active_support/secure_random.rb:5:in `': uninitialized constant SecureRandom (NameError)
I do not understand this. Should not each class be "independent" from other classes? Is that not the whole point of object oriented programing?
And now If it is not so more importantly how can I figure out what dependences I need to add? Is it some kind of workflow to solve this? Can I somehow figure out what dependencies to add looking at the documentation? Do this problem have something to do with load path? Can I load all dependences from a gem or rails or whatever? I just don't get it!
doc: http://api.rubyonrails.org/classes/Rails/AppBuilder.html github: https://gist.github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/app_generator.rb
there is no easy way to find out which dependencies are used within AppBuilder, cause most of the dependencies are setup somewhere else. so most of the times you need to do some trial and error to get the dependencies right.
the code that you posted has bad style. please get familiar with how to write ruby code properly. buy yourself a book i.e. eloquent ruby or just start reading ruby blogs.
dependencies in ruby is quite simple. every file that you require will be loaded and the load will recurse through the files and then load other requires. the loading will only work if all the required files are on the load path. this load path is similar to your system path and you can add directories to it to tell ruby where to look for files.
in general, there are dedicated entry-points for libraries and their dependencies. those are normally documented, so that if you use them, you get all dependencies right from the beginning. an example for this would be to require 'rails' in order to use rails or require 'active_support/all' if you just want to use active-support. if you wan't to chery-pick files/classes than you are on your own finding out which other classes you need. that part has nothing to do with oop, it's more an dependency-issue (other languages have explicit decleration of dependencies).
in your case, the next step would be to add require "securerandom" to the beginning of your file and then check wich error comes up next.

Rails 3.1 Engine plugin rspec testing (external gem Spree Commerce)

I created an engine inside an app that depends on an external gem: Spree.
And I did my best to set RSpec within that engine following this guide.
When I try testing a controller with some integrated testing:
tests_spec.rb:
require 'spec_helper'
describe "Tests" do
describe "GET /tests" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get tests_path
response.status.should be(200)
end
end
end
I get an error in the dummy app's environment.rb file, that says that following command couldn't be run:
# Initialize the rails application
Dummy::Application.initialize!
Because my controller is using Admin::ResourceController as an extension which is declared within the external Spree gem. As if rspec is unable to read that class from gemfile of the main app (the one that contains the engine plugin).
Can someone please shed some light on that?

Resources