Category Archives: RSpec

Open Source Rails Site

I found a site called Open Source Rails. It is a listing of sites that are written in Rails. I will look at it in more detail later.

It might be a good way to see how some high-profile Rails apps test stuff. I think I might be able to see how certain things are done and tested in Rails, sort of like a Rails cookbook.

Update On RailsApps Tutorials

I started using the RailsApps tutorials.

They are pretty good, but I noticed a glaring flaw: There is only one model, the User model. You don’t just create an app where users do nothing.

So I started working with a couple of them to add another model. I also wanted to be able to test them. I wanted to make Capybara tests to test actions for both authenticated and unauthenticated users, similar to what Hartl does, but with a standard authentication gem. Some of the RailsApps use Cucumber, but I have noticed that most Rails developers are not interested in Cucumber, and it looks like Capybara can do some of the things that people do with Cucumber.

One of the apps uses Devise. I have a Github repo based off of the rails3-devise-rspec-cucumber RailsApps tutorial:
https://github.com/emacadie/rails3-devise-rspec-cucumber/tree/add_book
The “add_book” branch has the authentication tests. The model is called Book.

Note 2015-06-14_12.46.25: Now at https://github.com/EMacAdie/rails_apps_dir/tree/master/rails3-devise-rspec-cucumber – HerokuPinger now at https://github.com/EMacAdie/rails_apps_dir/tree/master/heroku-pinger

I have another app that uses Omniauth called Heroku Pinger. The “second_attempt” branch has some tests that I think do what I am trying to do:
https://github.com/emacadie/heroku-pinger/tree/second_attempt

People will put up a free app on Heroku, but sometimes when they give out the URL the app will not be very responsive since Heroku puts free applications into a hibernate mode. This app was intended to allow people to have a few apps get pinged every hour. John McCaffrey told me that is not very sportsmanlike since the point of free apps is to not suck up too many resources. He is correct, but I decided to keep going because the real point was to work with OmniAuth, and eventually work with mocking and stubbing tests as well. Besides, you could ping any site, not just a Heroku site.

For the Devise app, it turned out to be pretty simple. I did some googling on how to get a Devise session in Capybara. A lot of the results said you had to mess with a Devise dependency called Warden. They say you need to put the following line in your tests:

I think that some of that information might be out of date, because I went back and commented out those lines, and the Capybara tests still do what I intend them to do. Perhaps updates to the gems made that unnecessary.

The magic is to get an instance of Capybara::Session and pass it around as you need it. I put the code in spec/support/session_provider.rb:

The Capybara::Session is stored in the “page” variable. You can use it like this:

 

I have a slightly more involved test that actually adds a book and checks that the count of Books has increased by 1.

The OmniAuth test took me longer. Part of is I later realized was that I was using methods like “get” from the Controller tests, and not the Capybara “visit” method. Capybara has a “get” method, but for some reason I got nowhere with that. I wasted a lot of time thinking it would work.

The SessionProvider class is in spec/support/session_provider.rb and looks like this:

In the tests that use this, you just do this:

 

 

I looked at the OmniAuth wiki and a few posts on StackOverflow and tried and re-tried several  times, until I had my “visit” epiphany.

Update on Chicago Ruby Testing Group

The Chicago Ruby Testing Group is currently on hold. We are revising the curriculum. We will also probably only do it once a week instead of twice a week.

Right now I am working on a short presentation on Cucumber. A big chunk of it will cover why will not be spending a lot of time on Cucumber. A big reason is the network effect: It seems like a beast, yet it does not have a lot of traction. But people might encounter it, so I think we should cover it.

Notes On Creating Test Data With FactoryGirl

A while ago Steve Klabnik posted about creating objects for tests via FactoryGirl  and there was another post in response.

I am working with FactoryGirl for Heroku Pinger. I was trying to restrict users to only create five websites.

To test this, I copied the test “creates a few websites with FactoryGirl” into a new one called “only creates five websites with FactoryGirl”. It failed. It seemed to allow the user to only create 5 sites, but at the end of the test the site count (querying on user_id) was 11. I could not figure this out.

Then it hit me: FactoryGirl was creating an array of sites using the generate_factory_sites method. I would then take that array and try to create the sites again. The user’s site count is only checked in the website controller, while FactoryGirl uses the model directly. So by the time I am checking to see how many sites a user has, I am already over the limit, and the limit is set to 0. So I changed the test to put data for websites in an array of hashes first, and use the hashes to create the sites manually.

I might go back later and clean things up. (I was about to write “I will”, but let’s be honest: how often does that REALLY happen?)

I also put in something to ensure that a user can only delete their own sites. That was a hassle.

So what I tried to do is to add some sites with one user id, and then delete them with another, and then delete them with the first user ID. It did not work. The session variable user_id will not change. I read online that you can set it like this:
session[:user_id] = JDJDDJ
but that did not work.

So I added some sites, changed the user ID of that site instance, then deleted it with the first user ID.

I created two users and changed the user_id in the website model, and then tried to delete the sites. I was not able to delete the sites after changing the user_id field in the website objects. Then I changed it back and deleted the sites.

A Bit More Ruby Testing Archaeology

In two previous posts, I wrote about my frustrations with methods in Rails tests that just seem to float in space and appear out of nowhere, and that the Hartl tutorial mixes RSpec and Capybara, and that it would be nice to know which is which.

In the last post, I wrote that sometimes when you try to find which class contains a method you get “Object”, which is not very helpful.

Here is the output:
The “sign_in” method is from one of the tests in the Hartl tutorial. I was explaining this to someone about an hour ago, and I realized why self.method says that  “sign_in” is part of the “Object” class: Because it is not defined in a class. In the application, Hartl defines it in a module, but in the tests it is simply defined in a file that contains neither  a class or a module.

In the root of the Rails tutorial app, you can run a grep command to find that method:

This will give you the following result

So here is the file spec/support/utilities.rb:

As I stated, in app/helpers/sessions_helper.rb the method is in a module called  SessionsHelper

More Ruby Testing Archaeology

I made some progress on this.

If something is a class, like “page” in the Hartl tutorial (like on say spec/requests/static_pages_spec.rb)
you could just do

which would give you

I don’t know why I didn’t think of that before.

In that file he also calls some voodoo methods. In before do he has:

and

sign_in and visit are methods. You can get these by doing this:

or you could do that on one line each like this:

Which will give you:

Granted, getting “Object” is not too helpful. But it is some progress.

Someone on the Rails core team has a post about finding methods here.

Ruby Testing Archaeology

One of my frustrations with Rails is that there are few if any ‘include’ or ‘require’ statements. Now I am going to do something about it. At least something for myself.

I went through the Hartl tutorial (as do most Code Academy students, and many aspiring Rails devs). He uses RSpec and Capybara for testing. RSpec can be used for any Ruby project, while Capybara is used for web projects. I think it can be used for other Ruby web frameworks, and other testing frameworks besides RSpec.

One thing I find in the tutorial and the tests is that Hartl will just call methods and instantiate variables. I don’t always know whether he is calling something from RSpec or Capybara.

At one point, he says this: Because of subject { page }, the call to should automatically uses the page variable supplied by Capybara (Section 3.2.1). This is in refernce to the  file spec/requests/static_pages_spec.rb.

But where in Capybara does “page” come from?

You see it in code like this:

The “subject” method is used for the models as well:

But there is no “page” model, or a “page” factory.  But it raises another question in my mind: What is “subject”?

I am pretty sure “subject” is from RSpec, either
http://rubydoc.info/gems/rspec-core/RSpec/Core/Subject/ExampleGroupMethods#subject-instance_method
or
http://rubydoc.info/gems/rspec-core/RSpec/Core/Subject/ExampleMethods#subject-instance_method

In the Hartl specs (2nd edition) you see this (via grep -r subject * | grep page)
requests/static_pages_spec.rb:5:  subject { page }
requests/authentication_pages_spec.rb:5:  subject { page }
requests/micropost_pages_spec.rb:5:  subject { page }
requests/user_pages_spec.rb:5:  subject { page }

In the Hartl tutorial, at say, like http://ruby.railstutorial.org/chapters/filling-in-the-layout#sec:pretty_rspec, he says
Because of subject { page }, the call to should automatically uses the page variable supplied by Capybara (Section 3.2.1).

So where does “page” come from? I am looking around the Capybara docs, and on http://rubydoc.info/github/jnicklas/capybara/file/README.md I see this:
Full reference: Capybara::Node::Matchers

Capybara has a rich set of options for querying the page for the existence of certain elements, and working with and manipulating those elements.

page.has_selector?(‘table tr’)
page.has_selector?(:xpath, ‘//table/tr’)
page.has_no_selector?(:content)

page.has_xpath?(‘//table/tr’)
page.has_css?(‘table tr.foo’)
page.has_content?(‘foo’)

After some googling and some digging, and it looks like “page” is part of the Capybara::DSL module:
http://rubydoc.info/github/jnicklas/capybara/master/Capybara/DSL

It looks like it returns a Capybara::Session object.

At some point I will make a separate page or post with just the methods that pop out of nowhere, and whether they are RSpec or Capybara.

 

Ruby Announcements

They are not announcements about Ruby in general, just about me.

First off, I submitted two proposals to speak at Lone Star Ruby Conf in Austin, Texas in August. One was accepted, and one was rejected. I started work on my presentation. I may also start the other presentation later at some point.

Also: The RSpec Study Group that I keep talking about is finally getting off the ground. The first day will be July 9th. Expect more details soon. It may be known at the Chicago Ruby Testing Group, since we will talk about more than just RSpec. We will still focus on Ruby testing technologies, so Python, PHP, dot NET and Java people will be out of luck. I am working on this with another Code Academy alum, with some help from a couple of Code Academy mentors.

 

Coding Without Testing – just for now

Since I got done with Code Academy, I have not done as much coding as I should be doing.

I am still working on getting the Ruby Testing Group off the ground. I am going through The RSpec Book, and I am going through The Well Grounded Rubyist. I am still going through all my stuff (I am amazed at how much I have accumulated).

I am still learning new stuff. I think now that I have perhaps subconsciously inhibited myself from coding because I am not ready to test all parts of a Rails app from the beginning. I still want to be a great coder, and I know that requires writing tests, but I think that I need to start building. Even if that means not writing tests right now.

Notes On Making a Gem


I decided to make a gem for a bit of practice. I did some googling, and I found a good RailsCast on it.

He uses bundler, which takes care of a lot of the heavy lifting. All I did was run

This will create a directory with the same name as whatever you called the gem. Then to add RSpec, cd to the directory that was created. Then run

I wanted to make a gem with a few layers in the directory tree. Java package names tend to have multiple levels, while most Ruby gems seem to only go one level deep. Perhaps I will never write a gem that has too many levels, but I wanted to make one with a few levels anyway.

I decided to start with a state in the first level. I added

to lib/states.rb
Then add a file: lib/states/hawaii.rb

Then I added a test file. Then in spec/spec_helper.rb, add

I added the  file spec/states/hawaii_spec.rb

There is another way to recognize the module levels in the RSpec file:

I put

in each spec file.

I also added a class lib/states/illinois.rb, and a test file in spec/states/illinois_spec.rb.

I then tried to add a few classes for Champaign County and Urbana. I tried to put them in a directory lib/states/illinois and in spec/states/illinois.

I got this error:

But I changed the directory name to illini, and I updated the files accordingly, and it worked. I changed it all back to “Illinois”, and it stopped working again. So now the module is back to “Illini”. I do not know if Ruby or RSpec will not allow a directory and a class to have the same name, or if I just needed to put illinois.rb in a higher directory. There is a states.rb and a states directory. Perhaps the gem name is an exception to the uniqueness rule. But in the future I will stick with using different names.

So, to summarize, I ran

Then to add RSpec, I ran

For every class that I made, I put a file in lib, a corresponding file in spec, and I put a require statement in the states.rb file.
And the class file names must not be the same as the directory names.


I am sure that for a lot of Ruby people, this post will be review. I tried making a gem using some of the code from the RSpec book as a basis, and I could not get it to work. I did the guy thing by trying something without reading the directions. I am thinking of proposing a talk for Lone Star Ruby Conf, and I need to be able to get a gem to work.