quick thoughts on testing

I am trying to make Rubypond as universal an option as possible, and to that end, I am using Wayne E. Seguin’s excellent RVM to test across a number of ruby installations. For test suites using test/unit or something similar, RVM has the handy command

~$ rvm ruby your_test_suite.rb

but this has been giving me problems when trying to run a test suite written in rspec. I don’t know whether it’s something I’m doing wrong, or something anyone else has run into, but I decided I’d just go ahead and write my own quick solution. So here’s what I ended up with:

require ‘spec’

begin
  require ‘crayon’
rescue
  module Crayon
    def method_missing(m, *a, &b)
      a.first
    end
  end
end

module RVM
  def self.use(version)
    system("rvm use #{version.to_s}")
  end

  def self.rubies
    `rvm list | ack -o "32m[^\s]+"`.
      split("\n").map{|r| r.gsub(/(32m|\e\(B\e\[m)/, "")}
  end
end

RVM.rubies.each do |version|
  if RVM.use(version)
    if system("spec -fl rubypond_spec.rb")
      puts Crayon.green("fine")
    else
      puts Crayon.red("less fine")
    end
  end
end
RVM.use(:system)

Crayon is my own library for colored terminal output. If it’s not installed, you get a ‘mock’ module that will print non-colored text, but saves you having to worry about requirement errors.

I created a small module RVM to hold wrappers for a couple command line methods because, well

RVM.rubies.each do |version|
  if RVM.use(version)
    …code
  end
end

is cleaner Ruby than having a bunch of `command line method` mixed in there.

The output in the event of failure is not particularly helpful in tracking down exact errors, but I like the concision of being able to keep the results on a single screen. And, of course, you can always change the spec command to provide more detailed output (the -fl option runs the ‘silent’ RSpec formatter).

Again, it’s entirely possible there’s a simpler way to do this, but given that this took about 10 minutes to throw together, and that about 5 of those were figuring out the ack and gsub commands to get a clean array of installed rubies, I feel the experimentation was worth it.

modularization

Something’s been bothering me about the code I’ve had up to this point, and that is instance variables. All those @’s, not to mention the fact that two methods, score and part both reference them. Furthermore, having to pass @parts to two methods within the context of the score method…it just feels wrong.

The best solution is to use accessors, instead of instance variables. Which means that the time has come to make Rubypond a module. Like so:

Old version (the relevant parts):

def part(name, &block)
  @enums[name] ||= part_name_enumerator
  @parts << [name + @enums[name].next, block]
end

def score(&block)
  @enums = {}
  @parts = []
  if block_given?
    yield
    @parts << ["music", block] if @parts.empty?
  end
  [
    version_and_language,
    music_content(@parts),
    score_block(@parts.map(&:first))
  ].compact.join("\n\n")
end

New version (again, the relevant parts):

module Rubypond
  attr_accessor :parts, :enums

  def clear_vars; @parts, @enums = [], {}; end

  def part(name, &block)
    enums[name] ||= part_name_enumerator
    parts << [name + enums[name].next, block]
  end

  def score(&block)
    clear_vars
    if block_given?
      yield
      parts << ["music", block] if parts.empty?
    end
    [
      version_and_language,
      music_content,
      score_block
    ].compact.join("\n\n")
  end
end

Nothing complicated at all, but the code feels much cleaner for the small refactoring.

some basic iteration

As I suspected, the Enumerator module was exactly what I wanted in Ruby 1.9. But, of course, since that module doesn’t exist in earlier versions of Ruby, I had to find a different option. What I found is the Generator module.

The first change I made to prepare for this implementation was to the part method:

def part(name, &block)
  @enums[name] ||= part_name_enumerator
  @parts << [name + @enums[name].next, block]
end

I planned for part_name_enumerator to look something like this:

def part_name_enumerator
  if RUBY_VERSION =~ /1.9/
    Enumerator.new do |yielder|
      …handle iteration…
    end
  else
    require ‘generator’
    Generator.new do |yielder|
      …handle iteration…
    end
  end
end

After looking into how Enumerators and Generators work, I discovered that, actually, I could pass the same block to both of them and get the results I wanted. Given the Ruby principle of “Things are Things,”* I was able to simply write this code:

def part_name_enumerator
  if RUBY_VERSION =~ /1.9/
    klass = Enumerator
  else
    require ‘generator’ unless ObjectSpace.each_object(Class).find {|o| o.name == "Generator"}
    klass = Generator
  end
  klass.new do |y|
    abc = Array(‘a’..‘z’).unshift("")
    count = 0
    loop do
      y.yield abc[count % abc.size]
      count += 1
    end
  end
end

The one limitation of this method is that, should you want a 28th of any instrument, you’re out of luck. I think the solution would be to modify the iteration block to somehow recurse on the iterator, so after ‘z’ you could get ‘aa,’ ‘ab,’ etc. However, since none of my immediate plans involve writing for a 30-piece violin section, I’m putting this in the “TODO eventually as an interesting exercise” pile.

- – - – - – - – - -
*) I believe the technical term is “Everything is an Object”

in which we give ourselves an orchestra

…providing there is no instrument doubling.

This code, which may be familiar from last time, now works:

score do
  part "violin" do
    "c d e f"
  end
  part "cello" do
    "g a b c"
  end
end

and it looks like this:

Multi-staff proof of concept

Pretty? Not really. Does it sound good? Well, parallel 4ths are certainly pleasant enough, but it’s probably not especially interesting. The important thing is that it works.

For those of you interested, here’s what the Lilypond code looks like:

\version "2.13.16"
\include "english.ly"

violin = {
  c d e f
}

cello = {
  g a b c
}

\score {
  <<
    \new Staff \violin
    \new Staff \cello
  >>
}

We’ve got the staff contents defined for violin and cello, and they are both added to the output down in the score block. All fine. But say you’re writing a string quartet, and you need two violin staves. They can’t both be named violin, or Lilypond won’t know which music to render in the score. One solution is something like this:

score do
  part "violin" do
    …music
  end
  part "violina" do
    …music
  end
end

but I’m not really a fan. I want the arguments passed to part to simply define which instrument is playing, without have to worry about obscuring that by needing to give each part a unique name. What I think I’d like to do is work out a way that all the user has to do is write

score do
  part "violin" do
    …music
  end
  part "violin" do
    …music
  end
end

and the program will know to write a Lilypond file that looks like this:

….
violin = {
  …first violin music…
}

violina = {
  …second violin music…
}

\score {
  <<
    \new Staff \violin
    \new Staff \violina
  >>
}

In Ruby 1.9, I think the Enumerator module will make something like this fairly trivial. In earlier versions of Ruby, I’m not so sure. But I do know that I’d like this to be Ruby 1.8 compatible, so there will need to be a way to check for that and load the correct mechanism for unique-ifying staff names. I’ve got some ideas. Stay tuned.

day one

I had two goals for today: generate Lilypond code for a single staff, and generate a PDF from that code, both of which I accomplished. There was nothing particularly new here. Much of the code is similar to some of the later code I wrote for Rubypond, so there wasn’t a whole lot of innovation on my part today.

I decided not to start this project off by creating a full gem directory structure. Instead, I went with the approach of writing as little code as possible, a technique I’ve wanted to try for a while and got to play with at bit at BohConf a few weeks ago. The idea is write your tests, then write the absolute minimum amount of code needed to make those tests pass. So all I created were two files: one for code, one for tests. Using test/unit I could have kept it all in a single file, but RSpec is currently my test framework of choice, and it does require a separate test file.

So I wrote 3 tests: one to check the contents of an empty score, one to check the contents of a score with a single staff, and one to make sure that the .ly and .pdf files were created. To get them passing, here’s the code I ended up writing:

def version_and_language; ["\\version \"2.13.16\"", "\\include \"english.ly\""]; end

def music_content(music); ["music = {", "  #{music}", "}"]; end

def score_block(music_given=false); ["\\score {", (music_given ? "  \\new Staff \\music" : ""), "}"]; end

def score
  [
    version_and_language,
    (block_given? ? music_content(yield) : nil),
    score_block(block_given?)
  ].compact.map{|s| s.join("\n")}.join("\n\n")
end

def build(score_obj)
  File.open(Dir.pwd + "/test.ly", "w") do |f|
    f << score_obj
  end
  system "lilypond test.ly"
end

For the most part I’m pretty happy with this, for what it does, and the extent to which I managed to keep myself writing minimal code.

To be fair, I could have left score as a single, large method, but the refactoring seemed like too straightforward a task not to just do it. I’m not thrilled with having to call block_given? twice in such close succession, but score is likely to change significantly, and rapidly, so I’m not sweating it too much right now.

The next step, I think, is to work out the API for having more than one staff in a score. I’d love to have it look more or less like:

score do
  part "part_name" do
    …music
  end
  part "second_part_name" do
    …music
  end
end

and I have some thoughts about how to do so. There are a few features of Lilypond that potentially add some difficulty, but those, I think, I’ll talk about when I have my solution to present.

let’s give this a try, shall we?

Inspired by Chris Strom, I have decided that the best way to get this blog off to a good start would be to start my own chain. That way, I can strive for regular (read: daily) posting, and, assuming anyone’s watching, I can feel the deepest of shame should I fail.

For those of you who don’t like following links, here’s what Chris has to say:

Don’t break the chain“, in case you are not already aware, is a motivational tool attributed to Jerry Seinfeld. The concept is that every day you produce something related to your craft. Each day you do this, you put an “X” through the day. After a little while, you have a chain of X’s and you begin to be offended at the idea of breaking the chain.

The end result is not the chain. Rather it is the skills acquired and honed by building up that chain.

So, my first chain is going to be a reimplementation of my library Rubypond.

In the previous version I had built the library from the inside out, starting with notes and working up to the score itself. It has occurred to me that, in writing a wrapper for a language whose goal is to produce scores, this is probably a very backwards way to go about it. So, the new plan is to start with the score itself, and work back down to the actual contents. My goal is to create a DSL that is as close to Lilypond’s own syntax as possible, while still allowing for all the usual nifty Ruby goodness: blocks, enumerables, and the like.

I’m not 100% sure how this is going to work, but the whole point here is just to make progress each day, and keep track of that progress here, and see what happens.