This will either be the first of a series of posts on "how I became a Ruby convert" or "why Ruby is the worst language on the planet."
I've spent the last two years of my life working with Python and its popular web frameworks (Django, webapp2, and Flask). Python was the first language I ever learned, so I'm admittedly a bit biased toward the "Pythonic" way of doing things. Python favors readability of code, but it also favors exactitude. I can push bits around in memory with the same ease as a GET request. The entire community feels like it's made up of scientists who want to support that - so libraries follow the Pythonic way of doing things. Boolean tests are written the same way in each library as they are in the core Python language.
So you can imagine my frustration when I start working with Ruby on Rails... and specifically, RSpec.
Let's take a look at a webapp2 test:
import unittest
import webapp2
import main # assuming that 'main' is the name of our application
class TestHandler(unittest.TestCase):
def test_hello(self):
request = webapp2.Request.blank('/')
response = request.get_response(main.app)
self.assertEqual(response.status_int, 200)
#assuming that page should return Hello, world!
self.assertEqual(response.body, 'Hello, world!')
See how nice that looks? I've got a Test Handler, which hits my main page with a GET request. The response is called by get_response
. Then I assert that the response has a 200 status code and a body of 'Hello, world!' This is simple; it is exact. It looks like a computer science project, but you also have no doubts about what you're getting.
Let's look at this in Ruby. If I want to write a simple Boolean check, similar to the above, I could do this:
require 'test/unit'
require 'net/http'
class TestHandler < Test::Unit::TestCase
def test_hello
request = Net::HTTP.get('localhost', '/')
response = http.request request
assert_equal response.code, 200
assert_equal response.message, 'Hello, world!'
end
end
I can work with this. The double colon syntax is a little weird, but I could get used to that. Now, coming from Python... I expect that I will write unit tests in a similar manner, even if I fire up another testing framework. RSpec can't be that bad, right?
FALSE.
I'm following a very nice walkthrough over at RailsApps that takes the reader through the construction of a Ruby on Rails app. I selected one that makes use of Devise for user authentication, RSpec for unit testing and Cucumber for behavior testing. I say to myself "oh, I have heard some things about this RSpec, let's see how cool it is."
This is a test for index.html
in RSpec:
require 'spec_helper'
describe HomeController do
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
end
WHAT THE HELL IS THIS.
This is some half Ruby core/half RSpec crap that I'm seeing in front of me. All I have to do is require spec_helper
and suddenly I can just screw up the entire vibe of my code. This does not make me happy. Now I've got to deal with this hipster code where it "should be successful"
is a valid Boolean test. Per the documentation: "RSpec uses the words 'describe' and 'it' so we can express concepts like a conversation. But that doesn't appear to be how the core of Ruby works - meaning that I have no idea when I'm supposed to be writing this pseudocode or writing actual Ruby.
Perhaps I'm off base. Maybe, once I get over the learning curve, this method of striving for natural language will make sense. But right now, I've encountered my first core gem that is just jacking my entire understanding of the language's flow around - and I've only been dealing with Ruby for a week or so. I can only hope it won't be this way for the rest of my learning experience.
Don't let the internet fool you into thinking RSpec and Cucumber are the one true path for Rails testing. I thought that as well when I was starting out, but after interacting with other developers in my community, I'd say we're split something like 50/50 between RSpec and Test::Unit.
If you really want to see controversy, check out DHH's tweet heard round the (Rails)world: http://www.rubyinside.com/dhh-offended-by-rspec-debate-4610.html. You don't have to buy into the cult of vaguely natural language obfuscated pseudo code if you don't want to.