I recently (NOTE: this article was written months ago but not published due to time constraints working on the patches) had a long discussion about the nature of DataMapper validations, specifically: validate_present. We determined that there are issues in two areas:

  • auto validation of not-nullable columns
  • validation of properties given a validate_present

ActiveRecord shares similar behaviour regarding blank values.

This post is an attempt to explain the nature of these issues, and to explain the crude patches I prepared to make the behaviour more logical.

Read the rest of this entry

New Year Resolutions 2009

January 1st, 2009

I (foolishly?) tweeted that I'd blog my new year resolutions, so here they are. Anyone that knows me is welcome to shame me into sticking to them. I've decided to make every resolution a discrete, verifiable task, that is, this is test-driven new year resolutions :) Oh, and they start from Jan 5th, as I'm still recovering from the interruption of the new year.

If I don't make it through 2009 it may be because of the resolutions... Just as I was writing this, I saw an article from the BBC saying that deciding to turn over a new leaf in the new year could do more harm than good. Apparently, "focussing on problems or insecurities can lead to feelings of hopelessness, low self-esteem and even mild depression". Yep that's right folks - if your life sucks, it's better to keep it that way than try to improve.

The article ends with the wonderful advice to avoid "easily broken resolutions" and, instead:

  • Be active
  • Go green
  • Learn something new
  • Give back to the community

Because, of course, all these things are really easy!

I score 2 out of a possible 4, as my list of resolutions includes being active and learning, but not being green or giving.

Anyway here goes...

Read the rest of this entry

Just spent about 15 minutes trying to work out why a Cucumber feature step wasn't failing when it should. Eventually I tracked down the issue to a matcher I wrote myself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

class HavePreviousUserStatus
  class ErrorPreviousStatus
    def inspect
      "<User did not have a previous status>"
    end
  end
  
  def initialize(expected_previous_status)
    @expected_previous_status = expected_previous_status
  end
  
  def matches?(twitter)
    timeline = twitter.timeline(:user)      
    @actual_previous_status = timeline[1] ?
                              timeline[1].text : ErrorPreviousStatus.new
    status_matches?
  end
  
  def status_matches?
    @actual_status == @expected_status
  end
  
  def failure_message
    "expected user to have previous status " <<
    @expected_previous_status.inspect <<
    " but got #{@actual_previous_status.inspect}"
  end

  def negative_failure_message
    "expected user to not have previous status " <<
    "#{@expected_previous_status.inspect} but did"
  end
  
end

def have_previous_user_status(status)
  HavePreviousUserStatus.new(status)
end

Spot the error? My matcher was always comparing nil == nil, so it could never fail. Lesson: either use private attributes, or write specs for your matchers :)

RSpec group on LinkedIn

December 5th, 2008

I forgot to publicise this. A little while ago I created an RSpec group on LinkedIn. If you use RSpec or Cucumber for fun or profit, make sure to add yourself!

Cucumber learns lolspeak

December 1st, 2008

There I was just looking for a ticket on the RSpec Lighthouse page when I stumbled across this unusual changeset. Next step... RSpec in JRuby for Lolcode on the JVM?

An easy one I just needed because I got sick of (a) waiting for long running features and (b) typing cucumber args by hand. Put this in your Rakefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

require 'cucumber/rake/task'
 
Cucumber::Rake::Task.new do |t|
  t.cucumber_opts = "--format pretty"
end

Dir["features/**/*.feature"].each do |f|
  task_name = f.gsub("/descriptions/", "/").gsub("/", ":").gsub(".feature", "")
  Cucumber::Rake::Task.new(task_name) do |t|
    t.feature_pattern = f
    t.cucumber_opts = "--format pretty"
  end
end

Note: I keep my features in features/descriptions rather than straight in features, but the tasks generate sensibly in either case.

It won't scale to many files, at which point a per-directory task generator would be more useful.

BarCamp Sheffield II(.1)

November 4th, 2008

I'm involved in organising the second BarCamp unconference in Sheffield. That is, the second one to actually happen, rather than the second one that was planned. There's a site dedicated to BarCamp Sheffield, which includes info on how to get involved. The event will be at the Showroom Cinema/Café-bar, opposite Sheffield Station.

I've suggested three session ideas:

If you like the any of the ideas, please sign up for the forum (and for a ticket) and give some feedback.

BarCamp Bar Sponsorship Deal

We have a special micro-sponsorship deal that will get your name in front of anyone getting drinks from the bar. Which means pretty much everyone :)

More details >>>here<<<