Jan 27 2008

Source from TDD: A Practical Guide

dastels @ 1:27 pm

Several people have asked me for the source from my last book “TDD: A Practical Guide”. A lot has happened since that book, and the files from it that were once posted on the Saorsa & Adaption sites were lost. Unfortunately I’ve had to tell people that the source was now longer in existence.

Well, today I was doing some routine housekeeping and… Huzah!!! I found a zip of those very source files. For anyone who has been looking for them… I’m pleased to say that I’m making them available at long last. You can download it here

Tags: 

Oct 29 2006

RSpec On Rails

admin @ 4:58 pm

Nice post by Defiler on RSpec:

RSpec On Rails:

RSpec is mere days away from a new release with greatly improved Rails support.

Since people are currently paying me to write Rails code, rather than plain old standalone Ruby (hint hint), I’ve been waiting for these features before making serious use of RSpec.

As an exercise, I ‘ported’ the acts_as_authenticated controller tests to RSpec. The results were fairly interesting. Subjectively, I find it more readable than the test/unit version. Objectively, one of the test/unit test cases doesn’t get run because there are two methods with the same name.

So far, so good. Anyone who thinks that RSpec is ‘only’ about a different set of terminology should give it a serious try first.

(Via ~:caboose.)

Tags: 

Oct 29 2006

Using TinyMCE with Rails/AJAX

admin @ 11:56 am

Our current project is basically a very structured (i.e. niche/focused/custom) content management system. There are a few places where we want to give the client the ability to edit some HTML page content. The client is tech-savvy, but not in the “I enjoy slinging HTML” way. Ergo, we needed WYSIWYG HTML editing capability. After some research we decided that TinyMCE was the way to go. We just had to make it work the way we wanted it to.

Here are my notes on getting TinyMCE working nicely in a Rails/AJAX environment.

Start by grabbing the rails plugin (and read the material) from here and install it as per the instructions.

Allowable options to uses_tiny_mce are documented here… there are lots of them

I figured that having followed the directions in the above, my work was over. In fact it was just beginning. The above will work fine if you have a page, with a textarea that you want to be WYSIWYG. Our requirements were a bit more involved. The textarea in question was in a partial that was rendered via a remote updater call (via a link_to_remote in a list on the page). The main issue here is that the textarea didn’t exist when the page was rendered… so TinyMCE had to be hooked up to it later… when it was injected into the DOM tree. Some digging through support forums and I found what I needed. This required a bit of java script in the partial… after the textarea:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>
  <b>Page Content:</b><br />
  <%= text_area :page, :content, :rows => 15, :cols => 150 %>
  <br /><br />
  <%= submit_tag "Update" %>
  <script type="text/javascript">
  //<![CDATA[
    tinyMCE.execCommand('mceAddControl', true, 'page_content');
  //]]>
  </script>
<%= end_form_tag %>

The next issue was getting the contents out of TinyMCE and accessible to the parameter construction for the remote call. After a bit of research I ended up with the following:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>

Normally the save is trigger by a page unload, I needed to force it to happen before the remote call happened. Putting the call to force (aka trigger) the save in the :before script of the form submission remote call worked great. So now I had a bigger problem. TinyMCE was getting hooked up to the textarea. If the user picked another page item from the list, the div would be refilled with a different rendering of the partial… with a different textarea node. The old textarea would be gone… out from under TinyMCE. I needed a way to reconnect to the new textarea. More digging turned up this example. It gave me the final bit of the puzzle. My final solution includes the following in application.js:

bTextareaWasTinyfied = false; //this should be global, could be stored in a cookie...

function setTextareaToTinyMCE(sEditorID) {
	var oEditor = document.getElementById(sEditorID);
	if(oEditor && !bTextareaWasTinyfied) {
		tinyMCE.execCommand('mceAddControl', true, sEditorID);
		bTextareaWasTinyfied = true;
	}
	return;
}

function unsetTextareaToTinyMCE(sEditorID) {
	var oEditor = document.getElementById(sEditorID);
	if(oEditor && bTextareaWasTinyfied) {
		tinyMCE.execCommand('mceRemoveControl', true, sEditorID);
		bTextareaWasTinyfied = false;
	}
	return;
}

These two functions are used to disconnect from an existing textarea and reconnect to the newly rendered one. In the list item that causes the rendering:

<%= link_to_remote "<span class=\"listTitle\">#{page.title}</span>",
                   {:update => "editPage",
                    :url => {:action => :get_page, :id => page},
                    :before => "Effect.Fade('editPage',
                                            {duration: 0.25,
                                             queue: 'end',
                                             afterFinish: function(effect) {
                                               unsetTextareaToTinyMCE('page_content')}})",
                    :complete => "Effect.Appear('editPage', {duration: 0.5, queue: 'end'})"},
                    :title => "Edit #{page.title}"  %>

To avoid visual weirdness the disconnect is delayed until the fade has completed. Once the new version of the partial has been loaded, it’s faded back in. The relavant bit of the partial is here:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>
  <b>Page Content:</b><br />
  <%= text_area :page, :content, :rows => 15, :cols => 150 %>
  <br /><br />
  <%= submit_tag "Update" %>
  <script type="text/javascript">
  //<![CDATA[
    setTextareaToTinyMCE('page_content');
  //]]>
  </script>
<%= end_form_tag %>

The last thing was to add a Done/Cancel button to the form:

<input type="button"
       value="Done"
       onclick="Effect.Fade('editPage',
                            {duration: 0.25,
                             queue: 'end',
                             afterFinish: function(effect) {
                               unsetTextareaToTinyMCE('page_content')
                             }})" />

Now I have a WYSIWYG textarea in a partial that’s rendered via a remote call.. and it all works smoothly and exactly as required.

Tags: 

Oct 14 2006

A great post by Ralph Johnson on what Design Patterns are & aren’t

admin @ 6:58 pm

misconceptions about patterns:

“I just read something called ‘Design Patterns’ aren’t by Mark Dominus.

He says that ‘ Everyone already knows that Design Patterns means a library of C++ code templates’. Yes, some people think that. They are wrong. A design patttern is not a library of code templates in any language. If you use Design Patterns by copying code from the book then you are stupid and missing the point. The point of the book is to teach you to think. If you learn how to think about code then you will program better.”

(Via Ralph Johnson.)

Design Patterns came out over 10 years ago. What amazes me is how many “programmers” I’ve met haven’t heard of the book or the topic.

Tags: 

Sep 01 2006

A Tale of two codebases

admin @ 2:10 am

I just finished working on notes for a Java5/jUnit4/TDD tutorial. This is a version of a Ruby/rSpec/BDD tutorial that I recently wrote. The app is a simple “guess the secret code” game. The contexts of the two are the same other than where language differences make themselves known. Primarily this is the in code. So, two codebases, same set of tests/specs, same functionallity.. 100% same. Both written by me… which, IMO, means pretty clean, tight code.

I’ll be looking over the code in the next few days, and probably blogging anything interesting that I find. But I’ll start off with this comparison… just how much difference is there in the amount of code?

Ruby Java % difference
Lines 396 551 39%
Characters 11479 16641 45%

So, in Java there is almost 50% more code. In this case.. a simple app… that’s only about 5000 characters… but what about a bigger app? That will add up fast. I can’t help but wonder if that comparison will be linear with the size of the app. Somehow I doubt it.

Tags: 

Aug 30 2006

BDD-style JavaScript testing

admin @ 3:53 pm

BDD-style JavaScript testing:

“Borrowing from Behaviour Driven Development techniques, especially the RSpec framework I’ve added some new features to script.aculo.us™ testing library.”

(Via mir.aculo.us.)

Check it out!

Tags: 

Aug 29 2006

Role Based Authentication from Rails Recipes. Part 2

admin @ 11:19 pm

Once I had the user roles code in place, working, and cleaned up, I decided to extend it by allowing regular expressions in the rights instead of literal strings (for controller & action names). Whether I stick with this going forward, who knows… but it’s convenient for development. Instead of separate rights for each action on a controller I can specify .* as the action to have the right apply to all actions for a controller.

Recall that I ended up with the core of the rights checking code actually in the Right class:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    action == action_name && controller == controller_name
  end
end

My first step was to wrap Rights attributes in a Regexp and do a match with the requested controller/action names:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    get_action_regex.match(action_name) && get_controller_regex.match(controller_name)
  end

  def get_action_regex
    Regexp.new(action)
  end

  def get_controller_regex
    Regexp.new(controller)
  end
end

It might be a case of premature optimization, but the Regexps can easily be cached since they are nicely encapsulated:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    get_action_regex.match(action_name) && get_controller_regex.match(controller_name)
  end

  def get_action_regex
    @action_regex || (@action_regex = Regexp.new(action))
  end

  def get_controller_regex
    @controller_regex || (@controller_regex = Regexp.new(controller))
  end

end

Part of the reason I blogged this was as an example of how much easier and obvious an enhancement can be when the code is cleanly (and extremely) refactored. More importantly, the details of rights can be changed without anything outside of the Right class being aware of it. If this ability is not one of the core benefits of OO, what is?

Tags: 

Aug 29 2006

Role Based Authentication from Rails Recipes. Part 1

admin @ 10:58 pm

First of all.. this is a great book! I’ve already used a variety of Chad’s recipes, either as is or (more often) as the basis of something customized.

That said, I was a bit disappointed when I read through Recipe 32 “Authorizing Users With Roles”. Mind you the solution was fine and worked nicely. My issue was with the code itself. Specifically, the unless condition in:

def check_authorization
  user = User.find(session[:user])
  unless user.roles.detect{|role|
    role.rights.detect{|right|
      right.action == action_name && right.controller == self.class.controller_path
      }
    }
    flash[:notice] = "You are not authorized..."
    request.env["HTTP_REFERER"] ? (redirect_to :back) : (redirect_to home_url)
    return false
  end
end

What’s wrong? Well, if we look at this code we start with a user, get the users roles, get the roles rights, get the rights action & controller. All from code in a controller. That’s a classic example of function objects & data objects. “But,” you say, “this is Rails.” So what. It’s still Object Oriented Programming. Thankfully, this is easy to clean up.

First, we can extract the condition out into a separate method:

def check_authorization
  user = User.find(session[:user])
  unless has_right?(user)
    flash[:notice] = "You are not authorized..."
    request.env["HTTP_REFERER"] ? (redirect_to :back) : (redirect_to home_url)
    return false
  end
end

def has_right?(user)
  user.roles.detect{|role|
    role.rights.detect{|right|
      right.action == action_name && right.controller == self.class.controller_path
    }
  }
end

Now we can push the code that deals with the user into the User class:

class User
  #...
  def has_right_for?(action_name, controller_name)
    roles.detect{|role|
      role.rights.detect{|right|
        right.action == action_name && right.controller == controller_name
      }
    }
  end
end

Leaving this behind:

def has_right?(user)
  user.has_right_for?(action_name, self.class.controller_path)
end

Most of User#has_right_for? can be pushed farther, into Role:

class User
  #...
  def has_right_for?(action_name, controller_name)
    roles.detect{ |role| role.has_right_for?(action_name, controller_name) }
  end
end

class Role
  #...
  def has_right_for?(action_name, controller_name)
    rights.detect{ |right| right.action == action_name && right.controller == controller_name }
  end
end

We can go one step farther:

class Role
  #...
  def has_right_for?(action_name, controller_name)
    rights.detect{ |right| right.has_right_for?(action_name, controller_name) }
  end
end

class Right
  #...
  def has_right_for?(action_name, controller_name)
    action == action_name && controller == controller_name
  end
end

Now.. the controller has a user in hand. It asks that user if it has the right to access the requested page. That user in turn, has some roles.. it asks each role if it has the right for the requested page, each role in turn asks it’s rights. Everyone in the chain talks only to what it has directly in hand. This is the way it should be. Now the controller doesn’t know or care what it means to have the right to access an action… only that the user knows, and how to ask that user.

Tags: 

Aug 26 2006

One Expectation per Example: A Remake of “One Assertion Per Test”

admin @ 10:42 pm

In the fine tradition of Hollywood (who these days is remaking everything from old movies, comic books, and video games in lieu of coming up with original ideas) I am doing a remake of the very first post on my blog (which itself was a repost from my Artima.com blog from Feb 2004). The original post created quite a stir at the time, and lead to many of the ideas that have evolved my understanding of TDD and now BDD.


Once upon a time (early 2004) there was a bit of fuss on the testdrivendevelopment Yahoo group about the idea of limiting yourself to one assertion per test method, which is a guideline that others and I offer for TDD work.

An address parser was the example of a situation where it was argued that multiple assertions per test made sense. Date was formatted with one address per line, each in one of the following formats:

  1. ADDR1$ADDR2$CSP$COUNTRY
  2. ADDR1$ADDR2$CSP
  3. ADDR1$CSP$COUNTRY
  4. ADDR1$CSP

The poster went on to say:

My first inclination is/was to write a test like this (in Java but you get the idea):

a = CreateObject("Address")
a.GetAddressParts("ADDR1$ADDR2$CITY IL 60563$COUNTRY")
AssertEquals("ADDR1", a.Addr1)
AssertEquals("ADDR2", a.Addr2)
AssertEquals("CITY IL 60563", a.CityStatePostalCd)
AssertEquals("Country", a.Country)

They didn’t see how to achieve this with one assertion per test, as there are obviously four things to test in this case. I decided that rather than simply reply, I would write some tests and code to illustrate my view on the matter, and offer a solid response.

For the original post, I chose Squeak Smalltalk and Java. In this remake I’m going to use just Ruby. In the original I said “For the sake of conciseness, I’ll omit any required accessors.” Well.. this time around I’m not going to use any accessors, since I am more & more of the opinion that they are quite simply an idea whose sole purpose is to undermine the very essence of Object-Oriented software. I’ll also be using rSpec rather than an xUnit framework.

So, where to start? Well, it often makes sense to start with something simple to quickly and easily get some code written and working. Then it can be extended and evolved. Here the simplest case is: ADDR1$CSP. There are two requirements in the parsing of this example: that the ADDR1 was recognized, and that the CSP was recognized. Viewed this way, we need two examples.

If we want to avoid accessors (and for this exercise, I do) we need another way to see inside the object were working with. This is an address.. let’s say (for the sake of argument & this exercise) that one of the purposes of having an address is to generate address labels of some sort. We could do that with an address label maker object that would interrogate the address object for it’s contents and use them. A better way is to have an address label builder that the address object gives information to. It would have methods such as street_number=, csp=, etc. This is something that we can use Mocks Objects for in our examples.

So, let’s start with an example for ADDR1:

context "An address with street & csp" do

  specify "should capture street information" do
    builder = mock("builder", null_object => true)
    builder.should_receive(:addr1=).once.with("ADDR1")
    addr = Address.from_string("ADDR1$CITY IL 60563")
    addr.use(builder)
  end

end

To get this to pass we need an Address class, a from_string factory method, and a use method.

class Address
  def self.from_string(address_string)
    Address.new
  end

  def use(a_builder)
  end
end

This lets our spec run and fail:

An address with street & csp
- should capture street information (FAILED - 1)

1)
Spec::Api::MockExpectationError in 'An address with street & csp should capture street information'
Mock 'builder' expected 'street=' once, but received it 0 times
./address_spec.rb:7:in `'

Finished in 0.003395 seconds

1 specification, 1 failure

Now let’s make that work:

class Address
  def self.from_string(address_string)
    addr1, rest = address_string.split('$')
    Address.new(addr1)
  end

  def initialize(addr1)
    @addr1 = addr1
  end

  def use(a_builder)
    a_builder.addr1 = @addr1
  end
end

This makes the example work:

An address with street & csp
- should capture street information

Finished in 0.003003 seconds

1 specification, 0 failures

That’s well & good. The next test is for CSP.

specify "should capture csp information" do
  builder = mock("builder", :null_object => true)
  builder.should_receive(:csp=).once.with("CITY IL 60563")
  addr = Address.from_string("ADDR1$CITY IL 60563")
  addr.use(builder)
end

Resulting in:

An address with street & csp
- should capture street information
- should capture street information (FAILED - 1)

1)
Spec::Api::MockExpectationError in 'An address with street & csp should capture street information'
Mock 'builder' expected 'csp=' once, but received it 0 times
./address_spec.rb:15:in `'

Finished in 0.005866 seconds

2 specifications, 1 failure

Address#from_string will need to be extended (and we need to add csp support):

class Address
  def self.from_string(address_string)
    addr1, csp, rest = address_string.split('$')
    Address.new(addr1, csp)
  end

  def initialize(addr1, csp)
    @addr1 = addr1
    @csp = csp
  end

  def use(a_builder)
    a_builder.addr1 = @addr1
    a_builder.csp = @csp
  end
end

So. We have two tests for this one situation. Notice the duplication in the tests… the creation of builder & address. This is the context. After refactoring, we have:

require 'address'

context "An address with street & csp" do

  setup do
    @builder = mock("builder", :null_object => true)
    @addr = Address.from_string("ADDR1$CITY IL 60563")
  end

  specify "should capture street information" do
    @builder.should_receive(:addr1=).once.with("ADDR1")
    @addr.use(@builder)
  end

  specify "should capture csp information" do
    @builder.should_receive(:csp=).once.with("CITY IL 60563")
    @addr.use(@builder)
  end
end

So, a context that creates the Address instance from the string as well as the mock, and very simple examples that focus on each aspect of that context.

Note that we don’t have any direct expectations in these examples… What’s up? Well, the mock is autoverifying itself at the end of each example, and that is where our expectations are.. on @address’s interaction with the mock.

The next simplest case is the obvious choice for the next context:

context "An address with street, csp, and country" do

  setup do
    @builder = mock("builder", :null_object => true)
    @addr = Address.from_string("ADDR1$CITY IL 60563$COUNTRY")
  end

end

This set of tests will include ones for addr1 and csp as before (since that behaviour is required in this new context) as well as a new test for country:

specify "should capture country information" do
  @builder.should_receive(:country=).once.with("COUNTRY")
  @addr.use(@builder)
end

As before, an instance variable and such need to be added to the Address class.

This drives Address to evolve:

class Address
  def self.from_string(address_string)
    addr1, csp, country, rest = address_string.split('$')
    Address.new(addr1, csp, country)
  end

  def initialize(addr1, csp, country)
    @addr1 = addr1
    @csp = csp
    @country = country
  end

  def use(a_builder)
    a_builder.addr1 = @addr1
    a_builder.csp = @csp
    a_builder.country = @country
  end
end

Now that we are supporting country, we can go back to the first context and add an example specifying that no country information should be provided to the builder:

specify "should not capture country information" do
  @builder.should_not_receive(:country=)
  @addr.use(@builder)
end

A slight tweak to Address#use will make this work:

def use(a_builder)
  a_builder.addr1 = @addr1
  a_builder.csp = @csp
  a_builder.country = @country unless @country.nil?
end

From here on, the evolution gets a bit more complex, as we add the ADDR2 option to the mix.

The final code and output is:

address_spec.rb

require 'address'

context "An address with street & csp" do

  setup do
    @builder = mock("builder", :null_object => true)
    @addr = Address.from_string("ADDR1$CITY IL 60563")
  end

  specify "should capture street information" do
    @builder.should_receive(:addr1=).once.with("ADDR1")
    @addr.use(@builder)
  end

  specify "should capture csp information" do
    @builder.should_receive(:csp=).once.with("CITY IL 60563")
    @addr.use(@builder)
  end

  specify "should not capture country information" do
    @builder.should_not_receive(:country=)
    @addr.use(@builder)
  end
end

context "An address with street, csp, and country" do

  setup do
    @builder = mock("builder", :null_object => true)
    @addr = Address.from_string("ADDR1$CITY IL 60563$COUNTRY")
  end

  specify "should capture street information" do
    @builder.should_receive(:addr1=).once.with("ADDR1")
    @addr.use(@builder)
  end

  specify "should capture csp information" do
    @builder.should_receive(:csp=).once.with("CITY IL 60563")
    @addr.use(@builder)
  end

  specify "should capture country information" do
    @builder.should_receive(:country=).once.with("COUNTRY")
    @addr.use(@builder)
  end
end

address.rb

class Address
  def self.from_string(address_string)
    addr1, csp, country, rest = address_string.split('$')
    Address.new(addr1, csp, country)
  end

  def initialize(addr1, csp, country)
    @addr1 = addr1
    @csp = csp
    @country = country
  end

  def use(a_builder)
    a_builder.addr1 = @addr1
    a_builder.csp = @csp
    a_builder.country = @country unless @country.nil?
  end
end

spec output

An address with street & csp
- should capture street information
- should capture csp information
- should not capture country information

An address with street, csp, and country
- should capture street information
- should capture csp information
- should capture country information

Finished in 0.014 seconds

6 specifications, 0 failures

Conclusion

So we took a situation that was thought to require multiple assertions/expectations in a test/example and did it in such as way as to have only one per.

The key is that instead of using a single context with a complex (i.e. multiple expectation) example for each situation, we made each of those situations into a separate context. Now each example focuses on a very small, specific aspect of the behaviour dealt with by its context.

I’m convinced writing examples like this is a useful approach. One advantage is that the resulting examples are simpler and easier to understand. Just as important, and maybe more so, is that by adding the specification of the behavior one tiny piece at a time, you drive toward evolving the code in small, controllable, understandable steps.

It also fits better into the context centered approach that is the recommended way to organize your examples. We set up the object being worked on in setup, and wrote examples of it’s behaviour in that particular context in individual specify clauses.

As I was writing this back in early 2004, something clicked. I saw these test methods (as they are in jUnit/test::unit) as specifications of tiny facets of the required behavior. Thus, it made sense to me to be as gradual as possible about it, driving the evolution of the code in the smallest steps possible. Striving for one assertion per test is a way to do that. This epiphany was one of the main drivers in my deepening understanding of what has been called Test Driven Development (and which we are now considering an aspect of Behaviour Driven Development)

If, however, you view test methods as strictly performing verification, then I can see how it might be seen to make sense to invoke some code and then test all the postconditions. But this view is not TDD (and certainly not BDD), and doesn’t buy you all of the benefits that are possible. I contend that central to TDD is this notion of working in the smallest steps possible, both for the finest-grained long-term verification, and for the most flexible design evolution. Furthermore, this is best done by striving to keep tests/examples as small, focused and simple as possible.

Aiming for one expectation each is one way to get there.

Tags: 

Aug 22 2006

Turn a decision into a method

admin @ 12:19 am

I was just working on some code that needed to extract some optional data from a hash, using it to set an attribute on a Model object. If it wasn’t present in the hash, a default should be used.

I started with something like:

if hash.has_key?("Genre")
  genre_name = hash["Genre"]
else
  genre_name = "Undefined"
end

Maybe that could be simplified some:

genre_name = hash.has_key?("Genre") ? hash["Genre"] : "Undefined"

Better.. but it still obscures what the intent of this method is.

I ended up extracting the code out into a separate method, and used a guard clause to make the decision:

genre_name = genre_name_or_default(hash)
...
def genre_name_or_default(hash)
  return hash["Genre"] if hash.has_key("Genre")
  "Undefined"
end

Clean, very clear.

I might want to use a default for the hash, but for now that’s YAGNI, and this works nicely for my purposes.

Addendum

As Jens points out in his comment, I can use hash.fetch(key, default) for this. In fact that’s what I’ve ended up doing in tis case. However, it is a generally useful approach to extract troublesome or ugly logic into a method of it’s own. Quite often being in a method (and not being afraid to have multiple return points) can drastically simplify and/or clarify logic.

Addendum 2

Simon points out that the default behaviour that the default behaviour of Hash.[] is to return nil. Which in this case will, indeed, mean that the key wasn’t present. So

hash["Genre"] or "Undefined"

works great.

Tags: 

Next Page »