World vs Include in cucumber/ruby - 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.

Related

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

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 }

Best way of using Ruby module for configuration data

I am somewhat new to Ruby, especially the more advanced concepts like modules and mixins, so I might be using module totally out of context..
I am currently writing an internal test framework using Capybara and I am trying to figure out the best/easiest way of handling configuration data. I file a file called config.rb and within it I want to store configuration settings per environment. For example:
module QAConfiguration
config data goes here
end
module DevConfiguration
config data goes here
end
The simplest example of configuration data is usernames and password. QA and Dev of course use different users. I am thinking of two different ways of going about this but I want to make sure I am following at least a decent practice and not going into the weeds.
module QAConfiguration
USERNAME = 'test'
PASSWORD = 'test'
end
or..
module QAConfiguration
def username
'test'
end
end
And so on. Which is the best way of approaching this?
A module probably isn't the best way to implement this. Generally when testing (I use rspec) we use helper files that contain reusable code.
Object attributes like usernames and passwords are usually handled by Factories. A great gem for factories is FactoryGirl.
A common way to store configuration in ruby/rails is in a yaml file. You could for example create a file called config/test_conf.yml with yaml format:
username: 'your_user'
password: 'somepass'
Then where you need the config data:
config = YAML.load(File.read("#{Rails.root}/config/test_conf.yml"))
puts config['username']
And finally, you will usually only put a test_config.yml.example on git/svn and in your app setup readme note that they need to cp config/test_config.yml.example config/test_config.yml and edit the file.

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

Utility Classes In Ruby on Rails

This is probably a stupid question, but I'm new to Ruby on Rails and I could use a little guidance. I want to have a helper/utility class that performs a group of network operations and returns results. Where do I put that class and how do I use it.
I've created network_helper.rb in my app/modulename/helpers directory. In my controller when I try to do
myNetworkHelper = ModuleName::NetworkHelper.new
results = myNetworkHelper.getResults
I get an error
undefined method `new' for MyModule::NetworkHelper:Module
I'm sure this is just a misunderstanding of how ruby on rails works. Can I get some clarification?
Would it be better to make this a class instead of a module and put it in libs? And can I add subfolders in libs and have them automatically loaded?
Lib or Classes
Little utility classes like this typically go in the lib folder, though some people prefer to create a folder called classes. Whichever you choose, make sure you import the folder in config/application.rb, as the lib folder is not autoloaded:
config.autoload_paths += %W(#{config.root}/lib)
Concerns
If instead of a utility class, you want to extend some of your models with reusable code, you may also wish to look at the new Rails 4 concerns folders which encourage you to extract reusable modules:
see: How to use concerns in Rails 4
To use new, the thing your calling it on must be a class, not a module. You're using a module. Change module to class in lib/utilities/network_utility.rb.
I cannot verify this at the moment, however I believe one place you can store your custom modules and classes is the lib directory. Alternatively, you should be able to store them in the app directory in the manner you have indicated by adding the following line to your environment.rb:
config.load_paths << File.join(Rails.root, "app", "modulename")
Also, check out Yehuda Katz's answer, which I think not only answers your question better, but also contains some very interesting and useful information and concepts relating to your situation. Hope that helps!
Add your class to app/lib folder instead of lib, so that you don't change autoload paths!
Explanations:
The accepted answer suggests adding the classes to lib.
But according to this discussion:
The lib folder does not belong to the autoload paths since Rails 3.
So it's discouraged to add lib under autoload path. Use app/lib instead.

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.

Resources