Development Tools

RSpec and HAML Helpers

Today I faced a problem with specing a helper where I use the haml_tag/puts methods (haml_tag was previously open).

Here’s a solution working with Rails 2.0.2, RSpec 1.0.3 and HAML 1.8.2 :

in spec_helper.rb add :

Spec::Runner.configure do |config|
  ...
  
  # Activate haml to spec helpers
  config.with_options(:behaviour_type => :helpers) do |config|  
    config.include Haml::Helpers  
    config.include ActionView::Helpers  
    config.prepend_before :all do  
       # Update from Evgeny comment, with HAML >= 1.8.2, you can call
       init_haml_helpers

       # Old way for HAML <= 1.8.2
       # @haml_is_haml = true  
       # @haml_stack = [Haml::Buffer.new]  
    end  
  end

  ...
end

then you can write your helper spec like this :

describe ApplicationHelper do
  describe "#top_navigation_menu when logged in" do
    it "returns the menu" do
      @user = mock_model(User)
      capture_haml {
        top_navigation_menu(@user)
      }.should_not be_empty
    end
end

The interesting method is capture_haml, which does the same as Rails builtin capture but for HAML.
haml_tag/puts methods write output directly to the buffer and does not return the generated content as a String, thus we cannot just test on the method output.

Published on Wed, 21 May 2008 21:35

Hosts aliases in Leopard

Back in Tiger days, I used to love having aliases pointing to localhost or other servers saving me some typing and allowing me to use Apache vhosts locally. To achieve this without restarting the whole system, I used NetInfo to add a new Machine entry, this works great, no restart needed only NetInfo reload.

With Leopard, NetInfo is gone (for the best) and it has been replaced by a folder hierarchy full of flat .plist files. No more NetInfo Manager, but a new dscl command and a bunch of related one : dscacheutil (lookupd replacement), dseditgroup, dsmemberutil, etc.

For today, we’ll use dscl and dscacheutil, let’s create a new Host entry to map myvhost.loc to 127.0.0.1 (I like adding .loc to distinguish my added hosts, but you’re free to use anything else) :

sudo dscl localhost -create /Local/Default/Hosts/myvhost.loc IPAddress 127.0.0.1

Then to be sure it’s looked up correctly by software (in fact it’s only needed if you tried to access the myvhost.loc before adding it) :

sudo dscacheutil -flushcache

A little handy feature of the new dscacheutil when we’re at it :

sudo dscacheutil -cachedump -entries Host

This will list all entries cached by Leopard, it can comes in handy when trying to solve a name resolution problem.

And finally if you want to get ride of your entry later on :

sudo dscl localhost -delete /Local/Default/Hosts/myvhost.loc

[Update 2008/01/07]
Benjamin Stiglitz wrote a comment to say /etc/hosts is now automatically watched for changes on Leopard, so there’s no more need to play with dscl to add simple host. Thanks again Benjamin.

Published on Sat, 05 Jan 2008 18:36

RSpec 1.1

David Chelimsky anounced this morning the release of RSpec 1.1 (as of now the website is not up to date) RSpec 1.1 and just now the brand new website hosting.

What’s in this release ?

  • Nested Example Groups : allows you to nest your describe blocks resulting in group sharing common specifications.
  • Support for Rails 2.0.1
  • Test::Unit interoperability : switch smoothly from Test::Unit to RSpec by allowing you to run your Test::Unit tests with RSpec. The goal here is to provide a way to progressively transition your tests to RSpec syntax.

More infos on David blog post about the RSpec 1.1 release

Congratulation and many thanks to everyone involved in this release !

Published on Fri, 14 Dec 2007 09:55

RubyGems mirror update

My RubyGems mirror just got an update :

  • switch to rubygems 1.9.5 0.9.5
  • index generation

If all goes well, it should be compatible with older rubygems versions and give a significantly boost to those using rubygems >= 1.9.5. 0.9.5

Published on Sun, 02 Dec 2007 11:28

RSpec and Inline RJS

Rails give us the ability to write inline RJS via render :update syntax, as in :

render :update do |page|
  page['addressPreviewStatus'].update 'Address Not Found'
end

Previous code will update the content of tag with “addressPreviewStatus” id with ‘Address Not Found’.

But how can we spec that out ? I needed to search a little as there seems to be very little examples.

First in rails there is a special assertion assert_select_rjs, merged from the assert_select plugin, it let you test your RJS with a syntax similar to RJS itself.
RSpecOnRails has a special matcher wrapping assert_select_rjs : has_rjs.

You can use it on response to specify what should be generated, for exemple you can :

# Specify response should contains an update or insert of some kind
response.should have_rjs

# Specify response should contains an update or insert for the tag with given id
response.should have_rjs('id')

# Specify response should contains a specific update, insert, etc. for the given tag
response.should have_rjs(:replace, 'id')

You get the point. Now, a nice syntax allows you to write RJS this way :

render :update do |page|
  page['id'].update('replacement text')
end

So my first try was to use :

response.should have_rjs(:update, 'id', 'replacement text')

but this fail miserably with an error Unknown RJS statement type update. I tried different syntax but none worked.

Finally browsing through source of assert_select_rjs I found what I was looking for. When using this syntax you should use one of :chained_replace or :chained_replace_html depending what you want to test :replace or :update.

Now here is the solution :

response.should have_rjs(:chained_replace_html, 'id', 'replacement text')
Published on Sat, 24 Nov 2007 16:17

Javascript BDD (2)

Just a quick add-on on my previous post, I found there was already a nice BDD framework for javascript : JSSpec.

Go see the demo page, it looks really nice.

Published on Fri, 19 Oct 2007 14:57

Javascript BDD

It was a long time since I delved into Scriptaculous subversion repository. This morning I was browsing it to find out what’s coming for next versions (seems 2.0 is not so far away) and had a good surprise : it seems they add BDD to their test framework.

I must admit my last try to use TDD for my Javascripts do not last long and this is a great reason to try again but this time BDD-Style.

To give you a little overview of what it looks like here’s a snippet extracted from the specs for the BDD framework itself :

Test.context("BDD-style testing",{
  
  setup: function() {
    ...
  },
  
  teardown: function() {
    ...
  },
  
  'should provide extensions to tie in isSomething and respondsTo object methods': function(){
    ...

    testObj.shouldBe('nice');
    testObj.shouldNotBe('broken');
    
    testObj.shouldRespondTo('isNice');
    testObj.shouldRespondTo('isBroken');
  },
  
  'should automatically add extensions to strings': function(){
    'a'.shouldEqual('a');
    'a'.shouldNotEqual('b');
    'a'.shouldNotBeNull();
    'a'.shouldBeA(String);
  }
}

If you’re using RSpec it should (woot!) looks familiar.

Published on Sun, 07 Oct 2007 13:57

Git 1.5.3 : submodule

Here’s another new functionality introduce in Git 1.5.3 : submodule.

Submodules allows you to manage subparts of a project in different git repositories and reference them in a “superproject” repository.

You can see it as an equivalent to Subversion “externals”.

A simple usage exemple (in your “superproject” root) :

git submodule add http://mygitdomain.tld/my_sub_project
git submodule init
git submodule update
  1. This will add the remote my_sub_project as an entry in .gitmodules and a directory named my_sub_project in your “superproject”.
  2. Then initialize all modules added, this means add them to .git/config
  3. And finally clone and checkout the different modules in their respective directories (created by the git submodule add command)

[Update – 2007/12/05]

I forgot to add you should not work directly with the “superproject” git repository besides adding more submodules.

You should clone the “superproject” git repository first and then the submodule part will be usable.

git clone superproject superprojectcloned
cd superprojectcloned
git submodule init
git submodule update

and work from “superprojectcloned” repository.

Then when you want to include the last versions of the submodules, issue :

git submodule status
git submodule update
  1. status, gives you an overview of the submodules state.
  2. update, fetch the latest version and reference the sha1 associated.
Published on Sat, 15 Sep 2007 21:31

Git 1.5.3 : stash

I installed this monday Git 1.5.3 and discovered a new functionality I find worth sharing : stash.

Basically, stash grab your current uncommitted changes and put them away until you want to reapply them. Git documentation for git-stash lists two examples where this comes in handy :

  1. Pulling into a dirty tree
I’m sure you already had the nightmare it is that you started working on a new functionality when a change you need appears in the upstream repository. Your current changes conflicting with the upstream’s ones git pull does not work. Here come the stash, simply issue a git stash (or git-stash, with an optional description message as you can have multiple stashes), then git pull to include the upstream changes and finally git stash apply to re-integrate your latest stashed modifications.
  1. Interrupted workflow (this one talk to me so much)
You’re working hard on some new kick-ass features when someone (your boss / client) come in and want this immediate fix in what it call a critical bug. One solution is to commit your changes to a new branch, correct the fix, commit it, rebase the new branch to the head with the fix, and then merge back the changes. I’m sure you already see the power of stash in such cases. No more in a hurry branches and commits, simply stash your changes, correct the bug, and reapply the stashed changes.
Published on Tue, 04 Sep 2007 16:57

(t)csh and dircolors problem

I encountered a little problem today, I use macports version of coreutils which gives me access to gnu versions of some commands (for full list : sudo port contents coreutils | grep /bin). My problem is related to one of those I’m using in my bashrc to color my shell : dircolors (gdircolors in macports).

This little commands allows you to generate LS_COLORS values (as the name seems to imply, it’s used by ls command) from a config file (~/.dir_colors in my case). I confidently modified this file today and was welcomed by a nice csh: Unknown colorls variable `su'.
It turns out there are an incompatibility between LS_COLORS generated by current version of dircolors in coreutils and (t)csh : tcsh treat LS_COLORS as a magic environment variable, which means it is parsed for its own use in ls builtin command.

The culprits in my .dir_colors file was :

#SETUID 37;41 # file that is setuid (u+s)
#SETGID 30;43 # file that is setgid (g+s)
#STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w)
#OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky
#STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable

As you can see a simple fix is to comment them out.

In fact I’m not sure why I see those errors poping up, as I’m using bash ans it’s now the default in MacOSX.

Published on Tue, 04 Sep 2007 15:10

RSS