Not sure if this falls into the useful or into the weird category, but I’m beginning to do code generation in my behavior specifications…

Take a look at the behavior specification:

1
2
3
4
5
6
7
8
9
10
11
12
require File.dirname(__FILE__) + '/../test_helper'

class TransactionStateOrderingTest < Test::Unit::TestCase
  TransactionState::StatusNames.each do |status|
    define_method("test_#{status}_query_method") do
      assert TransactionState.send(status).send("#{status}?"), status
      (TransactionState::StatusNames - [status]).each do |inner_status|
        assert !TransactionState.send(status).send("#{inner_status}?"), inner_status
      end
    end
  end
end

And the corresponding implementation:

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
class TransactionState
  StatusNames = %w(started approved processed completed cancelled).freeze

  attr_reader :name, :index
  alias_method :to_s, :name

  def initialize(name)
    @name, @index = name.to_s, StatusNames.index(name.to_s)
    raise "Unknown status name: #{name.inspect}" unless @index
  end

  # Generate instance methods to query the state of this instance.
  # Generates #started? and #completed?, among others.
  StatusNames.each do |status|
    define_method("#{status}?") do
      self.name == TransactionState.send(status).name
    end
  end

  # Generate class methods to return pre-instantiated
  # TransactionState objects, one per status name.
  class << self
    @@states_cache = Hash.new
    StatusNames.each do |status|
      @@states_cache[status.to_sym] = TransactionState.new(status)
      define_method(status) do
        @@states_cache[status.to_sym]
      end
    end
  end

  Statuses = StatusNames.map {|status| TransactionState.send(status)}
end

Nothing too earth shattering, except for the specs. How do I ensure the specs were properly generated ? I didn’t, except for confirming that the number of tests and assertions went up as expected.

 

Search

A picture of me

I am François Beausoleil, a Ruby on Rails coder. During the day, I work on XLsuite. At night, I am interested many things. Read my biography

Tags

(3) (1) (0) (2) (1) (1) (2) (2) (1) (2) (1) (2) (1) (2) (1) (1) (1) (1) (2) (14) (1) (1) (1) (1) (2) (1) (1) (2) (0) (1) (2) (1) (3) (1) (1) (1) (1) (1) (1) (0) (3) (2) (1) (2) (2) (1) (3) (2) (8) (8) (9) (12) (1) (1) (3) (1) (1) (1) (1) (1) (1) (2) (2) (2) (1) (1) (3) (1) (3) (1) (0) (21) (1) (1) (0) (1) (1) (1) (21) (23) (1) (1) (13) (1) (1) (2) (3) (1) (1) (4) (1) (2) (3) (0) (1) (7) (3) (1) (5) (5) (2) (2) (2) (4) (6) (7) (1) (0) (1) (1) (2) (2) (1) (4) (12) (2) (1) (2) (4) (1) (1) (1) (2) (8) (2) (3) (2) (2) (1) (3) (1) (1)

Links

Projects I work on

Categories

Archives