Copyright © 2010 The G String. All Rights Reserved. Snowblind by Themes by bavotasan.com. Powered by WordPress.
Posts Tagged ‘ Rails ’
In my current Ruby on Rails project, I’m learning about Notahat’s machinist testing framework to build object graphs on which to write unit tests. Its a nice improvement on fixtures; using an object-orientated, programmatic approach to creating test data.
In the pursuit of 100% code coverage, I hit on a problem when trying to test UploadColumn, which was being used for handling images on a Product class. Normally in a Test::Unit class, I could invoke the fixture_file_upload method to simulate the multi-part form upload of an image, but in machinist I couldn’t do that. After finding next to nothing in the way of documentation for testing Upload column, I did some rummaging around in the gem and found the solution.
At the top of your blueprints file, include UploadColumn:
include UploadColumn
Then, in your blueprint, you can use the UploadedImage class to represent your uploaded image:
Product.blueprint do
title
description
image { UploadedFile.upload(File.new(RAILS_ROOT + ‘/test/fixtures/label.png’)) }
end
I hope that helps somebody…
In my last contract role, I encountered the ruby-based RSpec testing framework for the first time. For those who haven’t looked into it yet, it provides a testing framework for unit, functional, integration and view tests, using a nearly plain English style of test definitions. The title of this blog entry borrows from the typical usage: rather than writing assertions, as with traditional testing frameworks, RSpec steers towards specific expectations for methods, such as
response.should have_tag(‘div’)
As far as I can tell, this code is rather like a wrapper around assert statements and spec tests inherit from the Test::Unit class, allowing traditional assert statements in tests. However, to follow the fanatic principles of BDD (Behavioural Driven Development), we should write tests using the RSpec format.
Why Test-Driven?
I’m a Java developer to begin with. I was drawn into the world of Rails because I was impressed with the ease of obtaining a working website in moments: the scaffold. I liked the fact that you didn’t need to know in advance every little detail about your system, because it was easy to change things afterwards. I liked the fact you could alter the code, press a refresh button on your browser, and instantly see your changes (you can’t do that with servlets, you have to re-start the container). This approach, known as agile programming, depends on this ease of changing your mind after you’ve built something. Writing tests is a very important part of agile programming, because tests are what tell us when we inadvertantly break something when making these ‘agile’ changes. Eventually, someone pointed out that the most correct way of programming therefore was starting with your test, and then implementing the code. That practice is undeniably the best way forward, but it tends to a pedantic style of Rails programming; the idea that there is a ‘correct’ way of testing that we ‘should’ adopt.
With TDD, it feels like I’ve lost a little bit of that nice, agile approach, for in order to write the test for some code I need to know what the code does first, rather like a return to up-front designs. That’s OK- because I ought to know enough about what I want to write anyway: but in practice I’m never going to write tests in advance for anything that Rails generates. I’m probably only going to test things that I wrote, which are over a few lines of code long. In RSpec, I can write tests that check for elements of a certain ID or CSS class: I’d much rather create the page first and then test it afterwards: otherwise I have to decide these things in advance: rather than being able to change my mind easily afterward.
When deadlines are tight, or there isn’t some test manager watching you, tests are the first thing to go, because programmers don’t like writing tests, and writing tests is not as expressive or as fun as working with the real code and seeing it work in the browser.
But then comes along a crowd talking about BDD: behavourial-driven development.
Not TDD; We Need BDD: Behavioural-Driven Development
I’ve tried to see a practical different between TDD and BDD, but its essentially the same idea: writing tests against your code, ideally before you start. If you know the difference, please tell me. For someone or the other, the difference was so profound that another test framework was needed seperate from the Rails test framework: RSpec.
RSpec (and BDD) move away from assertion-led tests such as
assert_equal 50, my_variable
to a programming syntax that is closer to English, focussing on the expectation of that code:
my_variable.should == 50
If I had to say which was easier to read: I’d probably say that the RSpec version is marginally easier; but as I programmer I can read both and I’m used to the first one. Rather than writing real code and adding value to the project, I’m fishing around the appaulingly-designed RSpec website, looking for documentation on how to write something equivalent to a test I could have otherwise written in a few seconds.
The test definition is also different, allowing arbitary phrases as part of the test block, to try and be more readable:
it ‘should complete the order and then deliver an e-mail’ do
Inevitably, all of this plain-English code, while a nice idea, makes the tests verbose and longer to type. If I change the test expectation, I have to change the definition too, if I want to keep it accurate. Yet I don’t really see what benefit it brings: non-technical people are never going to read it, and apart from sticking in fancy HTML reports, again which no-one will read, the programmer is doing extra typing for no return.
Should Do More Work!
RSpec doesn’t just provide changes in syntax. The BDD crowd deem the rails functional test inadequate, for it invokes both controller and view code in order to create the response. From my perspective, the rails approach is just fine: I want to know that when you are routed to a controller action, that action runs successfully, things happen in the database and something is rendered down to the client. BDD says we’re skimping off work doing that; we should test controllers and views seperately. That is, your view should work even if your controller doesn’t and vice versa. Once you know you have a working view and a working controller, you can run integration tests to make sure they work together. However, I think this is overkill. If I can see my view working in a browser, and the test says that under this or that circumstance I get a HTTP 200, 404 or 500, I’m done. I’m never going to switch database engines or run my controllers separately from my views.
Furthermore, RSpec introduces mock objects to abstract-away from the database. As test concepts go, I’ve looked at several frameworks for mocking objects and the concept just seems crazy to me. If I’m writing a database-driven website, why do I want to abstract away from the database? Its database-driven! Why write complex, badly-documented, boring code that isn’t the actual thing? Its doubling the work, and is probably not worth it. If you’re getting a nice daily rate to write this stuff, fine; but I wouldn’t bother with it on my projects, and I can’t see how it delivers business value in the long-term.
Should be_easier
All of these opinions come back to this point: that test code should support the development process, not supplant nor hinder it. All the time spent on writing mocks, seperate tests, getting code coverage up to 100% has its value, but it certainly has a diminishing return. The first few tests that are written, covering the critical part of the codebase, are the most valuable and the easiest to do. Debugging a view test when you can see it working fine in the browser is frustrating and unhelpful.
I think my dislike also stems from the word ‘should’; an interesting word, meaning something that isn’t, but we want or expect. Everywhere we say ‘it should be this way’, we implicity say ‘it should be this way, but it is not that way’. For example, how many records will be in the database after some action? It should be 5- so let’s assert that we have 5. As a friend of mine is fond of saying, “a should is a shit”, I’d rather assert something than bang on about what ought to be this and what ought to be that.
Continue Reading »I’m almost through ironing out the glitches caused by upgrading a rails 2.0.2 application to 2.2.2. Between the snippets of documentation scattered all over the web, I’ve muddled through a process that has taken a couple of days and been one of the trickiest framework upgrades I’ve had to make. For a long time, Rails kept me under the illusion that things were as easy as ‘rake makeeverythingwork’, but I think its true to say that the further I am into a rails project the less helpful the framework becomes.
I migrated two systems in parallel, my development and production environments, running xubuntu and debian etch respectively.
The first problem, as always is the case with ruby, is the documentation. In one sense, I quite like the anarchy of a completely disorganised documentation system cobbed together only by a decent search engine, but I must say that with this rails upgrade I felt very much on my own in terms of help and support, having to glean tips and derive solutions from several blogs, wikis and rdocs.
The next wall I ran into was related to the rubygem system. Far from the ‘packaging bliss’ I was sold on initially, the source index file is now so large that it completely eats the system memory and swap on my old development laptop, taking an extremely long time to complete. I learned the –no-update-sources option for gem installs, which avoids lengthly index updates. Eventually, I used gems to update rails:
gem update rails
There may have been some more commands in there. On my ubuntu laptop, I found that once I had a copy of rails 2.2.2 that everything broke, asking for a 1.3.1 version of rubygems. Using the ordinary method gem update –system didn’t work; claiming that there was nothing to update. Instead, I downloaded the gem from http://www.rubygems.org/ and installed it myself:
sudo gem install –no-update-sources –local rubygems-update-1.3.1.gem
sudo update_rubygems
Then I replaced the missing mysql adapter. Rails 2.2.2 dropped the mysql adapter from the framework, meaning that I have to re-install it to keep my app running. I will note here that the functionality that sold me on rails the first time I saw it has now been removed by default; as though rails introduced a quick method of making web-based views on mysql databases to catch peoples attention, and now they’re slowing leading them away to some other technological viewpoint. Anyway, to fix on linux I needed the mysql client development headers, found in the libmysqlclient15-dev package:
sudo apt-get install libmysqlclient15-dev
sudo gem install mysql
I was ready to run my unit and functional tests, to see what broke. In short, my application had problems with deprecated features and third-party plugins:
- In places, my application used request.relative_url_root to build URLs to resources relative to the public folder (I didn’t find a decent way of doing this without calling this method, I’d like to have something similar to image_tag). Anyway, the method was deprecated, replaced with ActionController::Base.relative_url_root. The new method returns nil if the application is deployed in the root of the domain (no context), which broke some calls which were building URL strings, so I created my own helper method to retrieve the context and changed all calls to it.
- The country_select helper has been removed. There is a replacement plugin available at http://github.com/rails/country_select/tree/master, but I found that it doesn’t work with rails 2.2.2. To avoid ‘wrong number of arguments’ errors, the following tweak is needed on line #7 of country_select.rb in the vendor/plugins/country_select/lib folder:
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options)
InstanceTag.new(object, method, self, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options) - The acts_as_commentable, acts_as_voteable and acts_as_rateable plugins all broke, giving ‘Unitialized constant’ errors. This is fixed by tweaking the init.rb file for each plugin to ensure the plugin library files are loaded correctly:vendor/plugins/acts_as_commentable/init.rb:
require File.dirname(__FILE__) + ‘/../acts_as_voteable/lib/acts_as_voteable’
require File.dirname(__FILE__) + ‘/../acts_as_voteable/lib/vote.rb’
ActiveRecord::Base.send(:include, Juixe::Acts::Voteable)require File.dirname(__FILE__) + ‘/lib/acts_as_commentable’
require File.dirname(__FILE__) + ‘/lib/comment’
ActiveRecord::Base.send(:include, Juixe::Acts::Commentable)
vendor/plugins/acts_as_rateable/init.rb:
require File.dirname(__FILE__) + ‘/lib/acts_as_rateable’
require File.dirname(__FILE__) + ‘/lib/rating’
ActiveRecord::Base.send(:include, Juixe::Acts::Rateable)
vendor/plugins/acts_as_voteable/init.rb:
require File.dirname(__FILE__) + ‘/lib/acts_as_voteable’
require File.dirname(__FILE__) + ‘/lib/vote.rb’
ActiveRecord::Base.send(:include, Juixe::Acts::Voteable) - Unobtrusive Date Picker became obtrusive, requiring a complete removal from my application and re-install from http://github.com/thincloud/unobtrusive_date_picker/tree/master. Make sure the version you download has the correct copy of 12_hour_time.rb, I found that the one installed via git was the old version.
Hence I finally could run the application on the rails 2.2.2 framework. The debugging continues….
Continue Reading »Two months ago, Indymedia London launched a new version of an alternative London-centered news website using Ruby on Rails and Debian/GNU Linux. After several months of indecision about what system to use for content management; whether to continue development of an existing Java-servlet application, to use Drupal or to develop something new, the London-based collective have arrived at a topical activist news website that has successfully been adopted by the activist community, and is fresher and richer in content than ever before.
The system, called Hyperactive, is a rails application that embodies the strongest recent trends in web development. It make extensive use of RSS to syndicate content, including videos and comments a la YouTube and is soon to include mapping from OpenStreetMap on its events section. It has also been adopted by a Danish IMC, and looks set to become more established in the wider network.
It is a triumph of the open-source software development model, based entirely on free-software, and developed without traditional planning constraints or limitations. It is particularly pleasing that Indymedia bring their own non-hierarchical ideals to the process; a group of individuals from different backgrounds and countries are contributing to the codebase, although the group have never all been together in the same space, nor is there an appointed manager or team leader.
I’m glad to say I have been making my first commits to the codebase recently, contributing a ‘featured groups’ section to the bottom of the homepage. Starting from an idea over beers in a South-London pub, the feature was coded on the spot and turned around in less than a couple of weeks. In essence, the available open-source technology, from operating systems to IDEs to version control make it possible for part-time energy to result in professional and fresh websites.
The project demonstrates quite clearly what is possible, when a small number of unpaid developers achieve functionality not far behind huge corporate websites. Behind them are even more volunteers contributing to moderation, testing and promotion.
Yet the problems of under-capitalisation and lack of resources are still present. The huge corporations, with their advertising revenue and share capital have the advantage of huge bandwidth and hardware redundancy, while many of the alternative websites rely on donations and a dedicated following. The dilemma as developers is how continue innovating with open-source software whenever it falls behind the latest products from the software giants; for the open-source developer, nurturing new projects by utilising and contributing to them can sometimes mean offering an uncompetitive product, and in the field of news and politics there are huge resources available to the mainstream media.
But for the sake of a few hours work here and there, when you can see the difference made by your efforts; when it is fun to work on an open-source project, its hard to see the open-source and voluntary sources of energy ever drying up.
If you are interested in contributing to the development of the project, have a look at escapegoats project website.
Continue Reading »