The RunCodeRun Blog

Nov 13 2009

The Basic Plan, New Signups, and the Holiday Season

As RunCodeRun matures and as we have continued to gain users, we have reached our current capacity level for the Basic Plan. With the holidays approaching, we are taking the step of temporarily disabling new signups for the Basic Plan. This will allow us to reconfigure our resources for the new year. In the meantime, our Premium and Walk Among the Gods plans are still available and will continue to be. And all of our current users, regardless of plan, will see no changes to the service.

Comments (View)
Sep 23 2009

Getting Your RunCodeRun on with Geektool

geektool screenshot

Are you using GeekTool? If not, download it! It is a very cool tool to help you keep track of what’s going on with your Mac. Now you can combine the power of Geektool with the RunCodeRun API. Head over to Github and checkout Aaron Bedra’s clj-runcoderun-radiator. Give it a shot on the command line by running

./geektool

Notice that you get a list of the Relevance open source projects. There’s an easy remedy for this. Simply open up src/runcoderun/api.clj and change the url to match your RunCodeRun username. Give the command line tool a shot again and make sure that your changes worked.

Now that you have the tools you need it’s time to wire them together. Open up System Preferences and select the GeekTool preference pane. Select the shell icon and drag it onto your desktop. Once you see the preferences appear, select ... next to the Command window to expand the view. Simply copy and paste the following:

cd ~/src/opensource/clj-runcoderun-radiator/
echo "RunCodeRun Status for Relevance"
echo "-------------------------------"
./geektool

and make the necessary changes match your system. Save the changes and watch the magic happen. Set the refresh rate to your liking (60 seconds seems to work well). Make sure to set the font to your liking as well. The screenshot above is using Courier bold 14pt. Enjoy your new RunCodeRun goodies!

Comments (View)
Sep 15 2009

Get to Green on Ruby 1.9

These projects have passing test suites on Ruby 1.9. Come and see how your code fares.

Ruby 1.9 is a terrific step forward from 1.8, and it is high time to start looking at moving your code there. (If you’re a Rails developer, you’ve probably heard that Rails 3 won’t just work on Ruby 1.9; it will prefer Ruby 1.9.) Of course, it isn’t just about your own code. What about all those gems and plugins you depend on? Will they work on 1.9? Community feedback, such as that organized at isitruby19.com, is one great way to see what’s working on 1.9.

Another great way is a passing test suite. To that end, we are launching Green on Ruby 1.9: a select listing of projects whose test suites are passing CI builds on Ruby 1.9. If you have a Ruby library that you want to see featured as green on Ruby 1.9, drop us an email.

Behind the scenes of our Green on Ruby 1.9 is a new RunCodeRun enhancement: selectable target platforms for your Ruby builds. When you add a project to RunCodeRun, you can request that the project build on either Ruby 1.8.x, Ruby 1.9.x, or both! Simply edit your project, and check which Ruby runtimes should be used to run your tests.

Building on multiple platforms demonstrates advantages both of continuous integration and of a hosted solution:

  • CI takes the pain out of configuration management for testing. It is a Good Idea to run your tests locally before committing, but there are diminishing returns to having a whole development team keep multiple platforms running on their own boxes. Continuous integration provides an easy way to detect regressions on secondary platforms, without headaches@localhost.
  • Hosted solutions get better over time by adding new featuers. Homegrown solutions, meanwhile, either bitrot in place or require regular infusions of sysadmin time just to keep them current. Spend your precious time on your passion: writing code, not administering tools.

Remember, RunCodeRun is free for open source projects. Get your code green on Ruby 1.9 today. It has never been easier.

Comments (View)
Sep 02 2009

Blue Ridge Pro Tip: Trust the Wiring, Test the Behavior

A Common Problem: Testing jQuery Event Handling

The prevailing style in jQuery is to inline your event handling like:

$(function(){
  $("#some-id").click(function{
    $(this).attr("some-attribute", "some new value");
  });
});

And so, most new users of Screw.Unit (and Blue Ridge) try to write specs like:

//do NOT do this!
it("does something", function(){
  // setup HTML fixture here

  $('#some-id').click();
  expect($('#some-id').attr("some-attribute")).to(equal, "some new value");
});

However, manually invoking the event usually doesn’t work as expected. It often doesn’t work at all. (More on that later.) Most important, though, is that this inline style is not reusable and is difficult to test.

The Solution: Trust the Wiring, Test the Behavior

Because I trust jQuery to handle events properly, I don’t test “wiring” code like the click() function. Instead I do something like this:

var SomeNamespace = {
  doSomething: function(element){
    $(element).attr("some-attribute", "some new value");
  }
};

$(function(){
  $("#some-id").click(function(){ SomeNamespace.doSomething(this) });
});

Now the spec can test the doSomething() function directly. I’d write a spec for doSomething() like:

it("does something", function(){
  // setup HTML fixture here

  SomeNamespace.doSomething("#some-id");
  expect($('#some-id').attr("some-attribute")).to(equal, "some new value");
});

Why Is This Better?

Clearer Intent

The code’s intent is clearer because it separates application-level logic from the event wiring. We focus on the essential logic, and we trust jQuery to do the rest.

Increased Reusability

The doSomething() function is more reusable because it can now work on any element. Note that the #some-id is hard-coded only in the wiring setup, not the function itself. Also, because we’re calling $(element), this function could be passed a selector string, a DOM element, or a jQuery object (that could potentially represent dozens of DOM elements). This style is very jQuery-idiomatic.

Greater Testability

Because the function is now properly named, you don’t have to go through any DOM/event contortions to test it. Also, you can set up several specs with different “fixtures” each highlighting a different aspect of the behavior under test.

Extra Credit: Why doesn’t the click() work?

Okay, technically it does work — if you get the timing of the event setup correctly. Which most folks don’t. It’s non-trivial, and so most developers either unnecessarily use the live() function as a crutch, or, in Blue Ridge, fall back to using the HTML fixture file which is undesirable.

Extra Extra Credit: Setting up HTML fixtures?

In a future blog entry I’ll cover setting up Factory Girl-style HTML fixtures inside your tests. For a few quick examples, though, check out the spec files and spec_helper.js file in the Blue Ridge sample app.

The Big Finish

Manually invoking events is one of the biggest problems new Screw.Unit and Blue Ridge testers face, and they just don’t have to. It’s unnecessary complexity. Trust that jQuery will do the right thing and get the event to your application function, and then all you need to do is test your own JavaScript behavior.

Comments (View)
Sep 01 2009

Announcing the RunCodeRun Basic Plan

We are pleased to announce that the RunCodeRun Basic Plan is now available. Targeted at solo developers, the Basic Plan costs $19 per month and supports up to three private projects. Unlike the Premium and Walk Among the Gods plans that provide a dedicated server for each account, Basic Plan private builds run on shared RunCodeRun build resources.

So drop by our list of plans and sign up for the Basic Plan today. Let RunCodeRun manage your continuous integration services, so you can focus on keeping your projects clean and green!

Comments (View)
Aug 24 2009

Now, with PostgreSQL support

We’ve been supporting builds on SQLite and MySQL since launch, but we’ve now added support for PostgreSQL (version 8.3) as your build-time data repository. Switching is dead simple: edit your project, and choose PostgreSQL from the “Database” dropdown:

That’s it — no other craziness needed. PostgreSQL at your disposal. Also, check out our knowledgebase article on database configuration for RunCodeRun to learn how we deal with database.yml at build-time.

Comments (View)
Aug 17 2009

Now Supporting Campfire Notifications

Because builds can’t fail loudly enough or embarrass you in enough places, RunCodeRun now supports politely alerting you to your FAIL through Campfire. No need to install anything into your build, just tell RunCodeRun “Yes, ma’am, can I have another!”

First, log in and edit your account profile:

Then, click on the “Notifications” tab and fill in your Campfire credentials:

After that, you’ll see notifications like this interrupting your otherwise pleasant Campfire chatting:

Good luck avoiding the Build Bot! It can’t be bargained with, it can’t be reasoned with. It doesn’t feel pity, or remorse, or fear, and it absolutely will not stop. Ever. Until you go green.

Comments (View)
Aug 04 2009

RunCodeRun now supports private builds

We are pleased to announce that RunCodeRun is now accepting private builds. This means that you can now connect your private repositories on GitHub to RunCodeRun for your continuous integration needs. You can drop by our list of plans to see which best suits your situation.

We feel it important to note that RunCodeRun remains, as always, free for open source developers. If you are already an open source customer and want to upgrade, just sign in and head to the plans page and pick the option that works for you. You can keep all your open source projects active, now and forever, regardless of which plan you are on. And if you are just interested in getting started with an open source project? That’s easy: just sign up for an open source account. You can always upgrade later if you want to add private builds.

We look forward to seeing your projects clean and green!

Comments (View)
Jul 20 2009

TDD in a functional language: Uncle Bob's Bowling

Want to see what TDD is like in a functional language? In this blog I will convert the Bowling Game example, as TDD’ed by Uncle Bob, to a more functional approach in Clojure.

Uncle Bob Martin, well-known OO and agile guy, has used the Bowling Game to explore TDD in a variety of different languages. Most recently, he has been learning Clojure, and experiencing a disconnect from the idioms he would use in an OO language. I felt this same disconnect when I started using Clojure, and I think I have finally bent my brain into the shape needed to TDD functional code.

I have taken Uncle Bob’s example, and converted it to a more functional approach while keeping tests passing at each step. This blog summarizes the key elements of my thinking, but of course you can also follow it step by step in the commit history of the clojure-bowling repository.

A starting point

The initial commit of the project simply imports Uncle Bob’s code, and adds some supporting infrastructure (shell scripts to launch a REPL with all the code available, etc.)

In addition, I chose to use the development edge of Clojure and clojure-contrib to take advantage of the new syntax for the are macro (more on that later). The repository includes compatible versions of these JAR files so you don’t have to download anything else.

Data, not objects

In OO, it is customary to invest a lot in how objects get made. So, the code includes functions like new-game that creates a game. This starts to get ugly with the functions that make test data. For example, the roll-many function creates many identical rolls of a bowling ball, and the roll-list takes an arbitrary list of rolls and adds them to the game. Using these functions leads to some pretty hard-to-read tests. For example, here is one that tests scoring a game that starts with a spare, followed by all gutterballs:

(deftest one-spare
  (is (= 16 (score
    (roll-many
      (roll-list (new-game) [5 5 3])
      17 0)))))

Ouch. I can hear the parenthesis-haters sharpening their pitchforks in the background. But what happens if we think of the game as a simple sequence of data?

"one spare" 16 (concat [5 5 3] (repeat 0))

In this tabular-looking expression, the "one spare" names the case being tested, the 16 is the expected score, and the concat builds the list of rolls: 5, 5, 3, 0, 0, 0 … Note that we are taking advantage of Clojure’s lazy collections to ignore exactly how many zeroes are needed.

The tabular, FIT-like style of listing values is enabled by the are macro. There are tests for several different possible games, and it is easy to add more:

(deftest test-various-games
  (are [description expected-score game] (= expected-score (score game))
       "gutter game" 0 (repeat 0)
       "all ones" 20 (repeat 1)
       "one spare" 16 (concat [5 5 3] (repeat 0))
       "one strike" 24 (concat [10 3 4] (repeat 0))
       "perfect game" 300 (repeat 10)
       ))

Recursion: a misstep

Scoring bowling is simple: “iterate over the frames of the game, adding the score for each.” Since we are using functional style, we will use recursion instead of iteration. Furthermore, since we are on the JVM, we will use Clojure’s explicit recur to trigger Tail-Call Optimization (TCO). Here is the original:

(defn score [game]
  (loop [frame 1 rolls game score 0]
    (if (> frame 10)
      score
      (let [frame-score (score-next-frame rolls)]
        (recur (inc frame) (subvec rolls (frame-score 0)) 
               (+ score (frame-score 1)))))))

That works, but I think I hear the parenthesis-bashers giggling again. The score function is pretty tough to read, especially the loop with five positional arguments. What is more troubling is that this function relies on a supporting infrastructure of five other functions, most of which don’t make much sense alone. Here is score-spare:

(defn score-spare [rolls]
  [2 (+ 10 (rolls 2))])

After puzzling a minute, it becomes clear: score-spare returns a pair:

  • the number of balls consumed by a spare frame
  • the score for this specific spare frame (ten plus the extra ball in the next frame).

Now I can hear the OO crowd sharpening their spears: “With objects it would be clear what was being returned here: the FrameStat bean or some such.”

Sequence transformation!

Instead of thinking about iterating over the rolls, think about transforming the rolls into a sequence of the thing you really want: the frames. So, for example:

; balls        => frames
[10 1 4 5 5 3] => [[10 1 4] [1 4] [5 5 3]]

The new sequence includes in each frame the balls needed to score that frame. Here is an implementation:

(defn frames
  "Converts a sequence of rolls to a sequence of frames"
  [rolls]
  (when-let [rolls (seq rolls)]
    (lazy-seq (cons (take (balls-to-score rolls) rolls)
                    (frames (drop (frame-advance rolls) rolls))))))

This function grabs (balls-to-score rolls) to make a frame, and then drops (frame-advance rolls) balls to advance to the next frame. Unlike the previous score-spare, these new helper functions cleanly express domain knowledge.

(defn balls-to-score
  "How many balls contribute to this frame's score?"
  [rolls]
  (cond
   (strike? rolls) 3
   (spare? rolls) 3
   :else 2))

Helper functions like strike and spare are also simple expressions of domain knowledge:

(defn strike? [rolls]
  (= 10 (first rolls)))

Keeping score

With the toolkit of frames and its various helpers in place, it is simple to score an entire game. Just convert rolls to frames, score the frames, and sum the score. The function reads like a definition, once you are accustomed to the notions of map and reduce:

(defn score-game
  "Score a bowling game, passed as a sequence of rolls."
  [rolls]
  (reduce + (map score-frame (take 10 (frames rolls)))))    

Build a toolkit, not a tool

Because all of the functions that support score-game are individually valuable tools, it is easy to implement new domain concepts. If you wanted to get the individual frame scores of a game in progress:

(map score-frame (frames [10 10 10 10 10]))
-> (30 30 30 20 10)

Or the running score:

; uses clojure.contrib.seq-utils.reductions
(reductions + (map score-frame (frames [10 10 10 10 10])))
-> (30 60 90 110 120)

Or the number of strikes:

(count (filter strike? (frames [10 0 10 0 10])))
-> 1    ; think about it

Parting shots

There is a lot going on here, but the single most important step is transforming sequences. Because the code now transforms sequences of balls to sequences of frames, it can be used to do all kinds of things other than just scoring the entire game. Moreover, the code is now shorter (in lines of code) and also more readable. Ditto the tests.

If you can think of some way to decompose a problem, TDD will help you build the individual pieces. But TDD does not help you choose the best decomposition. Functional decomposition is generally superior to object-oriented decomposition using mutable state.

Note that the use of laziness in the scoring is slightly gratuitous in this example, since bowling games are of a fixed size. However, laziness is a very useful part of solving real-world sized problems, and it is almost as easy to write as non-lazy code. So I tend to write laziness-preserving transformations even when I know (famous last words) that domain entities will never get large.

Resources

Comments (View)
Jul 17 2009

It's Okay to Break the Build; It's Not Okay to Forget About It

When should your Continuous Integration service notify you about the results of a build?

When we originally implemented email notifications for RunCodeRun, we thought to ourselves, “We get too much email as it is. Let’s not send an email after every build; let’s just send notifications when the build status changes. You know, when the build breaks, we’ll obviously want to know. And when when it goes back to green, we’ll want to know that as well.”

That seemed like a reasonable approach at the time. Then along came reality. You see, we do get too much email as it is. And as a result, sometimes when the build goes red, that status change notification might get lost in the noise. A few days go by – or even worse, a few weeks go by – and all the while, the dev team is committing away in WorksOnMyBox Land, none the wiser. Maybe the team introduced a dependency that happens to reside on the development machines, but they forgot to declare that dependency in the project. Maybe they unknowingly implemented a feature that only works on their development machine’s operating system or architecture.

If your deployment environment looks even the slightest bit different than your development environment (and who’s doesn’t?), these are things that you want to know about. And if you make another change to the code, and these problems still exist, you want to know.

With the changes we pushed out today, RunCodeRun will now remind you of your ill-fated builds after each build failure. And then when you fix the build, RunCodeRun will notify that you’re back to green.

Build Notifications in Your Inbox

If you’re not getting any build notifications at all, you can enable them in your account preferences. (You may also want to double check your spam folders, and be sure that you have bot@runcoderun.com on your email whitelist.)

Build Notification Options

Remember: it’s okay to break the build, but it’s not okay to forget about it.

Comments (View)
Page 1 of 3