The Successor to GTD
January 26th, 2010
It seems that GTD, that favourite of serial procrastinators, is being supplanted in people’s affections.
That should be reversed, so he could see it in a mirror.
Finally, a sentiment we can all get behind
January 25th, 2010
From the ever-fantastic Photoshop Disasters blog, someone from the Globe forgot to replace that trust standby placeholder text with the real content.
Snow Leopard Developer Upgrade Notes
January 6th, 2010
Apple’s latest release of OS X is version 10.6, or “Snow Leopard”. For most users, upgrading isn’t a worry: you upgrade, and everything just works. Developers, however, will find that upgrading is more haphazard, as the environment has switched from 32-bit to 64-bit. Plus, you have to find enough downtime in which to upgrade & deal with any issues that arise. For me, that downtime finally occurred over the Christmas/New Year’s holiday period. In a hazy, and admittedly alcohol-induced moment, I rashly decided to install 10.6 around midnight a couple of days ago, forgetting that I hadn’t fully thought out what to do with all the Rails apps I had on my machine.
So here are some notes for when/if you want to take the plunge to 10.6 (which I recommend that you do). Matt Aimonetti’s August 2009 article on the Riding Rails blog contains very good general information. What I took away from it is that Snow Leopard requires 64-bit versions of your Unixy software: remaining 32-bit isn’t an option, as I’d hoped (from a position of laziness, that is, prone). So you’ll need to recompile not just all your MacPorts goodies, but of equal importance, all your gems.
Matt suggests that upgrading ain’t that bad. In my experience: lies, all lies. Virtually nothing he or the commenters suggested worked for me, so like some crazed frontiersman, I had to forge my own path. I blew everything away & started afresh. Here’s what I did:
- Before anything: export your databases (or at least have their contents close to hand in some fashion);
- Start your MacPorts dance, installing/upgrading to the latest MacPorts & then installing all the software you need;
- I had a lot of trouble updating MySQL. The tips in this article did me a real treat when nothing else worked;
- A little titbit of info: apparently you can have problems with the MySQL gem, as apparently it wants to compile as 32-bit. You’ll have to force it to compile as 64-bit:
sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-include=/opt/local/include/mysql5 --with-mysql-lib=/opt/local/lib/mysql5 --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config - Re-create your databases & use your db exports to populate them;
- For Rails apps that have gems in vendor/gems (thanks to Ian for this), you’ll need to recompile them for 64-bit:
rm -rf vendor/gems/* ; sudo rake gems:install ; rake gems:unpack ; rake gems:build - For Rails apps that don’t have gems in vendor/gems (boo! hiss!), the situation is more hit & miss. The easiest option is to just install new versions of all your old gems. However, I wanted to take this as an opportunity to prune through the thicket, hence my slight pain. If you follow my lead here, just try to run your app & see what gem is missing: then install it.
The end result: when the sites popped up, I was stunned by how quickly they appeared. In addition, the whole compiling MacPorts apps was shockingly quick.
Cucumber 0.5 + Textmate bundle not running @wip
December 21st, 2009
This is a quick one.
Cucumber's recent version bump includes a new and improved html report generator (for textmate users, at least) borrowing javascript from rspec. That is to say, when you run your features it will be more like when you run your specs, progress bar and so on. I like that now it shows undefined step snippets in the textmate window in a usable form, that's a timesaver.
The update has changed cucumber's rake tasks to have its @wip settings in your cucumber.yml profile instead of in the rake tasks. This is great, as it's nudged me away from editing the generated rake files and having upgrade pain.
A side-effect of putting these settings into the profiles is that anything other than rake tasks will also use these settings, including the Textmate bundle.
Since the Textmate bundle doesn't understand tags I just gave it a separate profile:
cucumber.yml:
default: --format progress --require features --color --tags ~@wip,~@pending --strict
wip: --format pretty --require features --color --tags ~@pending,@wip:4 --wip
textmate: --require features --format html
TM_ CUCUMBER_OPTS = '--profile textmate'
Which runs all the features you tell it to.
Anachronic and Vines, calling time on my plugin virginity
November 20th, 2009
I released my first two real open source projects this week, both Ruby. Kind of nice, never thought it would happen, then it just did.
Vines is a (very small currently) bundle of useful general step definitions for Cucumber, it's not currently rails specific, and I may make rails-specific steps a different include so it can be used for regular ruby projects.
The only step currently available is very simple, but not provided by cucumber. From its own feature tests:
Feature: Should happen steps
In order to assert errors in my steps
As a developer
I want to talk about a step's side effects or consequences
Scenario: step raises
Then an error should occur when I eval `raise`
Scenario: step raises a certain type
Then an ArgumentError error should occur when I eval `raise ArgumentError`
That's pretty simple stuff. There was and will be more there, but the code and dependencies had too many rough edges for now.
Anachronic went straight to plugin; in integration testing Paperclip I wanted to know whether deleting site images (my model wrapper for a paperclip image attachment) was cleaning up files correctly. I wanted to do it in Cucumber, and I wanted the steps to be simple.
The idea is very simple really:
When I add a site image
Then the images directory should have changed
When I delete the site image
Then the images directory should be back to how it started off
You could, of course, use git for this, but I didn't care about file contents, only whether the files still existed. I think it'd make the tests slow. You may also like to use some combination of ls and diff; have fun with those man pages.
Simple solution -- snapshot file and directory names recursively, then spot the difference between snapshots.
Wrote some specs, wrote some code, specs passed, put into the rails app as a plugin, wrote steps, green feature. Magic.
So, at last, something other than forks on my github page!
Non-Latinate Characters Coming In Domain Names
October 26th, 2009
So says ICANN. How long will it be before we start seeing phishing scams for visiting Microsoƒt.com?
And, more importantly, how many people will fall for it?
All joking aside, this could open up a huge jug of hurt for end-users. End-users have become completely used to a basic basic Latin character set & are wholly unaware of the variations that can occur. Whilst my example above is blindingly obvious, less obvious examples—such as using the dot-less ‘i’ in Turkish— could cause no end of problems. Don’t get me wrong, this is a necessary step; it’s merely a question of how we cope with the change.
Yet more Cucumber Tagging
October 1st, 2009
Cucumber now comes with some rake tasks to help you out on your road to tag-happiness.
rake cucumber:ok will run any scenarios not tagged with @wip
rake cucumber:wip will run any scenarios tagged with @wip and if there are more than 2 of them, or any pass, it will complain. That's not as bad as it sounds, it can be handy info.
I added ~@pending tag to the rake tasks as I wrote some features to sort out later; I don't want them executing and don't want to delete or move them. Why record the ideas in another place, they'll just get lost.
New Poster: Folk Psychology Conference
August 21st, 2009
Well, it may be holiday time for many people, but it hasn’t been for us. We’ve been up to (and past) our eyeballs in work, particularly graphic design work, for the past several months. One of the items we’ve been working on is this.
The “Culture & the Mind” Project assembles individuals from a wide range of academic fields to investigate different subjects. This year the focus is “Folk Psychology”: what we, in our everyday lives, do when we attribute beliefs or desires onto other people. One of the questions the conference (and the Project in general) will attempt to do is to examine what aspects of folk psychology are innate, and what change depending upon one’s cultural upbringing.
The client had a great desire to have fun with the poster, in particular to hark back to 60s & early 70s design. I took the opportunity to quote that, but also to pay homage to one of my all-time favourite graphic designers, Steven R. Gilmore. You can only go so far quoting Jefferson Airplane & Skinny Puppy posters, though: psychedelic typography & brain imagery act as visual hooks to make the viewer take a closer look at the content of the conference.
An even simpler cucumber tagging system
August 11th, 2009
Release versions are one way to handle your tags, but as Ian pointed out, really for most people (and perhaps me) it's excessive. I'd go further to say it's superfluous, clumsy and overly bureaucratic, all in all not very agile. Not bad for something I came up with!
While this sort of thing will take some iterating and is really down to how you arrange your work, the following simple scheme may provide a good foundation.
Tags: @stable
And that's it. Write your features, when they pass mark them as @stable, and when you want to do a regression test run it against all your @stable features.
cucumber --tags @stable -f progress features
You could even rake or alias it for added comfort.
Tags: @stable @wip @pending
In the above an untagged feature can be a work in progress, or left pending for later. While this is enough for regression testing, tagging these features as well has some workflow benefits. It's your metadata, why not use it.
Take for example the feature you quickly sketched out over lunch a week ago to flesh out later, where was it again? If it were tagged you could do a project search (TextMate) or equivalent to find the elusive text. Why waste Time looking when you can Search?™
Tag it your way
One of the nice things about these tags is you can build on this scheme quite easily, by domain, release number, external resource connectivity, or whatever you like.
This is inherently YMMV, and it should be interesting to see what other people find useful.
That Cuking Paperclip!#$!
August 4th, 2009
No, nothing to do with MS Office, promise.
This is a rehash of a conversation I had on the Cucumber mailing list / Google Group
If you are using the Paperclip plugin to handle user image submissions you may run into some head-scratching trouble when testing this with Cucumber. The following approach, while perhaps not ideal, tests the full stack, short of a browser.
The following example uses Machinist for random file selection and could be simplified to a single test image if desired.
Sample Images
Put some images into spec/fixtures directory with a common name, e.g. example1.jpg example2.gif example3.jpg and so on
Steps
My paperclip binding is called picture and it's on my service object. This is in my service steps file:
def new_picture
@new_picture ||= Sham.image
end
When /^I provide an image file for "picture"$/ do
attach_file "service_picture", new_picture.path
end
And in my Sham.define block (in spec/blueprints.rb)
image do
images = []
dirpath = File.join Rails.root, 'spec', 'fixtures'
Dir.new(dirpath).each { |file| images << File.new(File.join (dirpath, file)) if file =~ /^example\d/ }
images[rand(images.length)]
end
Assertions?
Then /^I should see my photo$/ do
response.should have_selector("img[src*=''#{File.basename new_picture.path}])
end
or
response.body.should =~ /#{File.basename new_picture.path}/
and so on.
Note that paperclip will give you addresses resembling this:
http://localhost:3000/system/pictures/2/index/example5.jpg?1258339851
so watch out for the secret token after the ? and don't just use == on the file path.
File Hangover
The gotcha is cleaning up the files afterwards, since we're not using the database for a file store. I took this approach (which is hacky but works, on unix) to put the paperclip test files into a different directory and delete the directory afterwards.
features/support.env
#remove paperclip files
require 'paperclip' #make sure it's loaded, else cue intermittent weirdness
module Paperclip::Interpolations
alias_method :org_attachment, :attachment
def attachment(att, style)
"CUKE/" + org_attachment(att, style)
end
end
After do
`rm -rf #{"#{RAILS_ROOT}/public/system/CUKE"}`
end
#end remove paperclip files
This wants to be an after block so that your database and file system stay in synch through your tests. Using an after all block (or equivalent) would mean the database having no pictures in it, but the directory having image files in it. While that may seem to work ok it's unnecessarily inconsistent.
Testing Domain and Release Specific Features via Cucumber Tags
August 1st, 2009
While my last post highlighted spork as a way to speed up your rspec runs, unfortunately it doesn't currently seem to work out-of-the-box with cucumber. While I am sure this will be resolved in good time there is another approach to speeding up your feature runs & more besides: Tags!
Feature Spaghetti
At some point you will likely find yourself wanting to run a subset of your features rather than all of them, they may be spread across different files and directories, perhaps they're mixed within files but part of a different release. Recently I found myself having written up scenarios from an initial planning meeting which were broken up into 2 reasonably sized releases. The trouble with a straight cucumber features run is the output is a mess. It's cluttered with pending, undefined and even failing steps which you probably aren't interested in yet. Not only does this slow down the run but the terminal spam can be a real hindrance.
But wait, there's --help
cucumber --help, cukes.info and Joseph Wilk's talk at Rails Underground to the rescue!
While undefined stubs are nixed by -i or --no-snippets this absolute; you don't get the snippets you *do* want. Joseph's talk introduced me to cucumber's tagging functionality, which so far I had skirted around and avoided. While it's not yet in the Rspec Book there is a chapter on Cucumber to be added.
Meta Tags ain't just for SEO
In brief, Cucumber tags are really useful.
I broke my features up into domain tags (@services and @admin) and into releases for those written @0_2 @0_3 corresponding to my release plans.
They're easy to add: just add them to the top of your features or individual scenarios, see the wiki. If you're going to add them to an existing project this might be a big task, it can probably be automated. I found copy-paste sufficient for 10-15 feature files. If you know about it when you start out then it's painless as you just do it when you start writing the feature or allocate it to a release/iteration/etc.
Now when I'm working on a services feature I can just run pertinent features with
cucumber --tags @services -f progress features
This will also do the .-UF dance rather than printing out all the features.
Besides this I can test the features release by release, testing the current release goals. There doesn't seem to be much point checking 0.3 features when still working on 0.2.
cucumber --tags @0_2 features
No more fluff or failures for things I probably wrote earlier than I should have done.
But… But… What About The Customer?
The only downside I see to tagging is if you want to send the raw files to your customer for amendment. If you don't want them to see the tags you can try running them through cucumber and piping the result into text, or use cucumber's own file saving functionality. If your steps aren't all green you may have to fiddle with this a bit to get rid of error messages, undefined step stubs, etc.
I did something like this, as it was quicker than finding the right settings:
cucumber --quiet --tags @0_2 features > v0_2-features.txt
To diverge for a moment you're probably only interested in this if you're writing declarative features for the benefit of customer communication. If you're using cucumber purely for integration testing with "imperative" steps then you probably don't want to do this, as their eyes will glaze over. You may like to try some of the other tags shown by --help too, such as --expand for scenario outline tables.
For a comparison of imperative and declarative steps take a look at Ben Mabey's 2008 post. It's old and the technology has changed but the issue is identical. As Ben says, both approaches have their uses.
Forging Ahead
When moving forward with your project running one release at a time will become laborious. You will want to run several versions, and I don't suggest tagging features as @0_2 @0_3 etc, this would get old fast. An alternative is to run several tags at once
cucumber --tags @0_2,@0_3,@0_4 features
This sort of fiddling seems to lend itself to project-specific rake tasks, which I will be experimenting with some time soon.
Actually this doesn't work, it looks for scenarios with both tags, not either (intersection not union), so rake tasks or similar really will be handy for chaining feature runs.
Shoulda Sporked That
July 28th, 2009
One of the feelings I got from Rails Underground (best not to ask about the others!) is that while RSpec, Cucumber and family have laid tracks in the Rails toolkit and community, many still use TestUnit.
Alternatives are good in some senses, but make me feel like I'm missing out and worry about chasing the wrong rabbit. Seeing things bridged can be nice, and here's an example of that. This one is extra-nice because it also patched what was, to my eyes, a crack in the plaster.
Shoulda for RSpec
I've got some rspec view and controller macros I am considering pulling out into a plugin, but decided to look around for alternatives first. Remarkable is noted on some wiki or other, but I couldn't make much sense of it. rspec_on_rails_macros is a sensible looking alternative, but the origin has been out of development for some time and the forks are somewhat confusing. Looking around did have a positive consequence though -- they pointed out that Shoulda now has rspec support!
That may sound confusing, since Shoulda is another way of writing declarative unit tests (with a similar looking syntax to rspec), but the bonus is a raft of new matchers. So far only the model macros are available but more are promised to come.
Instant gratification:
- it "should not be valid without a meta description" do
- Service.make_unsaved(:meta_description => nil).should_not be_valid
- Service.make_unsaved(:meta_description => '').should_not be_valid
- end
-
- it "should not be valid without meta keywords" do
- Service.make_unsaved(:meta_keywords => nil).should_not be_valid
- Service.make_unsaved(:meta_keywords => '').should_not be_valid
- end
-
+ it { should validate_presence_of(:name) }
+ it { should validate_presence_of(:teaser) }
I'd Spork That
Next up is Spork, a must-have if you find your specs are running slowly.
You get another executable to add to your workbench, spork, this is a distributed ruby server which uses forking (unix only) to cut down start-up times. Pretty cool I think, get set up to a common starting point then clone it per run.
I find this config works for me, without having to restart the server when I change Machinist blueprints or helper files
require 'rubygems'; require 'spork'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.dirname(__FILE__) + "/../config/environment"
require 'spec/autorun'
require 'spec/rails'
require 'shoulda'
require 'webrat'
Dir[File.dirname(__FILE__) + "/spec_helpers/**/*.rb"].each do |file|
require file
end
# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
Spec::Runner.configure do |config|
config.use_transactional_fixtures = true
config.use_instantiated_fixtures = false
config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
config.include Webrat::Matchers, :type => :views
#machinist setup
config.before(:all) { Sham.reset(:before_all) }
config.before(:each) { Sham.reset(:before_each) }
#end machinist setup
end
end
Spork.each_run do
# This code will be run each time you run your specs.
require File.expand_path(File.dirname(__FILE__) + "/blueprints")
Spec::Runner.configure do |config|
config.include ViewHelpers, :type => :views
config.include ControllerHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller
end
end
I went the route of adding --drb to the spec.opts file. This works with textmate and autospec. If you forget to run spork it'll run locally without the drb.
If you want something more (or actually) distributed for your tests take a look at testjour, or even some of the cloud computing services (which I've forgotten the names of!).
