dm-is-slug 0.10.2 Now on GemCutter

Posted on February 08, 2010

I’m so forgetful

I created a datamapper plugin called dm-is-slug in 2009 to ease the pain of handling permalinks or url slugs in my merb project. I have to admit, I have totally forgotten about it until now!

So, I spent some time merging commits from Alex Mankuta whom has fixed many bugs, and now it works much better. Thanks, cheba!

I also added support for unidecoding, which allows you to turn strings like “你好” into “ni-hao”.

Lastly, the gem is pushed to gemcutter for easy gem install. That didn’t take too long! :)

Find out how to use dm-is-slug on github!

Updates on Inspec - Javascript BDD Framework

Posted on April 24, 2009

For the past two weeks, a lot of improvements has been done for Inspec, here is the list:

  • Better scoping / sandboxing
  • Support for Rhino, SpiderMonkey, Johnson and WSCript
  • Tested to work with IE7, Firefox 3, Chrome and Safari 3
  • Added a lot more specs to test Inspec
  • Fixed a bug where cascading before / after blocks not getting the correct scoping / sandboxing
  • Changed BDD syntax a bit to be compatible with Screw.Unit
  • Shamelessly stole all matchers from Screw.Unit
  • Added the following matchers:
    • beA – instanceof test
    • throwError – takes an function, and see if it throws an error
    • respondTo – test if an object has a function
    • have – see if an object or array contains something

I’m working on some advanced features that requires some pretty big structural changes right now. They are:

  • Support for multiple definition of same behaviors.
  • Support for multiple definition of before / after blocks.
  • Redo shared example groups ( Allows for sharing local scope variables inside shared example groups)

I plan to finish this feature while I’m taking a business trip to Boston this coming Sunday.

For future, the plan follows:

  • Spec, spec spec, 100% coverage require!
  • Extract and improve rendering logic from HTMLReporter to HTMLReporter.FlatFormatter
  • Implement HTMLReporter.NestedFormater
  • Implement HTMLReporter.CompactFormater
  • Implement ConsoleReporter.FlatFormatter
  • Implement ConsoleReporter.NestedFormater
  • Implement ConsoleReporter.CompactFormater
  • Implement options for choose formatters, need to consider extending
  • Add statistics functionality to Reporter Class
  • Test on different browsers
  • Selective Behavior Execution support
  • Prioritize object printing with toString() if object has customized toString
  • Documentation
  • Make a wiki

That’s a lot of stuff to complete! If anyone interested please fork Inspec

Inspec - Yet Another Javascript BDD Test Framework

Posted on April 13, 2009

The “Why” Question

Why? You ask, we already have BDD Frameworks such as Screw.Unit, jSpec, and JSSepc, you want to make another Javascript BDD Test Framework?

To answer your question, you can take a look at my previous article comparing strengthes and weaknesses of the above frameworks. So, please read it if you haven’t done so.

Now, if you are still with me after finish reading my article, allow me to introduce you a new BDD Test Framework that doesn’t suck.

Introducing Inspec

While coding up Inspec, I was trying to fulfill the following features:

  • Nested behaviors
  • Shared behaviors (aka. it_should_behave_like in RSepc)
  • Framework agnostic ( You can use it with jQuery, Prototype, Mootools, YUI, or ExtJS. it’s your choice. )
  • An elegent DSL
  • No namespace pollution
  • Able to run in browser, command-line, and server side
  • A cystal clear API that is easy to understand and extend

Sound awesome! But how does it work?

Here is a small example:

describe("Inspec", function(){

  it("should work", function(){
    expect(true).toBeTrue();
  })

  it("should fail", function(){
    expect(true).not().toBeTrue();
  })

  it("should be pending")

  describe("with a nested example group", function(){    
    it("should work as a nested example group", function(){
      expect(false).toBe(false);
    })
  })

  // W00t?? It's nesting a shared example group
  itShouldBehaveLike("a shared example group");
})

sharedExamplesFor("a shared example group", function(){
  it("should work as shared example", function(){
    expect(true).toBeTrue();
  })

  // Yes! Shared nested Example Groups!
  describe("with nested example groups in shared", function(){
    it("should work as a nested example group in shared", function(){
      expect(true).toBeTrue();
    })
  })
})

Here is another example that uses more matchers:

describe("Matchers", function(){
  describe("TypeMatcher", function(){
    it("should work with String", function(){
      var aString = "abc";
      expect(aString).toBeType("string");
    })
    
    it("should work with Number", function(){
      var aNumber = 123;
      expect(aNumber).toBeType("number");
    })
    
    it("should work with Object", function(){
      var anObject = {};
      expect(anObject).toBeType("object");
    })
 
    it("should work with Boolean", function(){
      var aBoolean = false;
      expect(aBoolean).toBeType("boolean");
    })
    
    it("should work with undefined", function(){
      var undefinedValue;
      expect(undefinedValue).toBeType("undefined");
    })
 
    it("should work with function", function(){
      var aFunction = function(){};
      expect(aFunction).toBeType("function");
    })
  })
  
  describe("InstanceMatcher", function(){
    it("should work with String", function(){
      var aString = new String("abc");
      expect(aString).toBeA(String);
    })
    
    it("should work with Number", function(){
      var aNumber = new Number(123);
      expect(aNumber).toBeA(Number);
    })
    
    it("should work with a class", function(){
      var Foo = function(){};
      var foo = new Foo();
      expect(foo).toBeA(Foo);
    })
 
    it("should work with a sub-class", function(){
      var Foo = Inspec.Class.extend({});
      var foo = new Foo();
      expect(foo).toBeA(Foo);
      expect(foo).toBeA(Inspec.Class);
      expect(foo).toBeA(Object);
    })
  })
  
  describe("ComparisonMatcher", function(){
    it("should work with toBeAtLeast", function(){
      expect(5).toBeAtLeast(5);
      expect(6).toBeAtLeast(5);
    })
    
    it("should work with toBeAtMost", function(){
      expect(4).toBeAtMost(5);
      expect(5).toBeAtMost(5);
    })
    
    it("should work with toBeGreaterThan", function(){
      expect(6).toBeGreaterThan(5);
      expect(5).not().toBeGreaterThan(5);
    })
    
    it("should work with toBeLessThan", function(){
      expect(4).toBeLessThan(5);
      expect(5).not().toBeLessThan(5);
    })
  })
  
  describe("RegexMatcher", function(){
    it("should match correct string", function(){
      var emailRegex = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
      var email = "abc@efg.com";
      expect(email).toMatch(emailRegex);
    })
    
    it("should not match incorrect string", function(){
      var emailRegex = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
      var email = "abc_efg.com";
      expect(email).not().toMatch(emailRegex);
    })
  })
})

What’s working so far

As this is still an early release (Let’s see, It is about 3 weeks old so far. Let’s call it version 0.0.1??), most of the core features are already working. Here is the list:

  • Basic Matchers
  • Nested describes
  • Shared describes
  • Sandboxed Example Scope
  • Tested to work in FireFox
  • Basic HTML Reporter
  • Works with Rhino and Johnson
  • Basic Console Reporter for Rhino and Johnson

In The Near Future…

While Inspec is now working with basic matchers, here are a few things I’d like to add:

  • Better syntax and organization of matchers for easier extensions. (Tempted to steal from Screw.Unit)
  • More Matchers. (Makes everyone happy.)
  • Work on WScript environment.
  • Make sure compatibility with all major browsers. (Helps appricated)
  • Allow selective execution of Example groups / Examples.
  • Make a better HTML Reporter, that hooks into selective executions.
  • Better Documentations. (Helps appricated)
  • Better Error messages on Failure and Exception.
  • Package and maybe minify(why not?).
  • A LOT more rigid and concrete tests to reach 100% coverage. (Also serve as uage examples, helps appricated)

For Developers

I have been very busy with my date job lately, and never have enough time to work on my own projects. Any help is very much appricated. So if you are interested in developing Inspec together, just fork me, make some improvements, rebase, push, and shoot me a pull request. If you are a regular contributor, your name will be in the co-author’s list as well.

Suggestions? Comments?

While I primarily developed this for my own need. I hope this will benefit everyone who has similiar needs. So your suggestions and critics are very welcome. Tell me what you like about it, what you don’t like about it, and how Inspec can be improved. Sorry that there is nothing like google group or irc or mailing list setup yet. You can leave a comment here, and I will be notified automatically through email. If this project grows bigger, I will setup a google group and an irc channel. But for now, you can either leave a comment, or scroll down to the bottom of the page, and my contact information is on the lower right.

Javascript BDD Test Frameworks Compared

Posted on April 12, 2009

Lately, I’ve been trying to find a good JavaScript BDD style test framework, and I have come across a few of them such as Screw.Unit, jSpec, and JSSepc. They all have their own unique set of features, and are all very innovative. But I couldn’t find a exact fit for my requirements. While they are all unique in their own ways, and provide some rather innovative approach to the BDD problem domain, they all have some drawbacks that I find either not acceptable or not easy to use.

Let’s have a little analysis on the strength and weakness of each frameworks listed above. Ok, you must note that the strength and weakness I describe is obviously a subjective opinion of my own, that entirely pertains to my own need. You may find the weakness I mentioned to be a strength in your case. Don’t flame me about it!

Screw.Unit

Screw.Unit is the one I found to be the closest to my needs, and I believe it is the most popular BDD JavaScript test framework at the momenent of this writing.

Things I like about Screw.Unit

A key feature of Screw.Unit is the support for nested describes and the cascading before (and after) behavior. For presentation, it has a good HTML runner that generates good looking HTML pages to present the test results. You can also create custom matchers in a easy and declaritive manner to extend Screw.Unit. Because adding member functions to Object is consider a bad practice, the use of foo.should be_true cannot be done easily without polluting the Object prototype. However they came up with an alternative DSL that looks like this: expect(foo).to(equal, true)

Things I don’t like about Screw.Unit

However, there is a few things I don’t like about it.

  1. No support for shared specs. (aka it_should_behave_like in RSpec)
  2. Does not support commandline (due to dependcy on jQuery, DOM, and concrete Javascript)
  3. Does not support server-side javascript (Same reason above)

jSpec

jSpec is probably the most innovative JavaScript BDD, and sometimes I feel that it might be a bit too innovative…

Things I like about jSpec

In jSpec, you don’t write true JavaScript, but a higher level DSL, which later being parsed and converted to JavaScript and executed. It also supports nested describes and before, after blocks. It has a wealth of matchers, and has formatters that supports DOM, console, and terminal. The size of the script is very small as well.

Things I don’t like about jSpec

First, doesn’t support shared behaviors.

The DSL looks nice at first sight. In fact I almost mistook it as rSpec test suits. But after careful analysis, I have a few doubts about jSpec’s DSL. First, from the source code, the DSL to JavaScript transformation is done using a few lines of Regex only. I’m afraid that it might not work on edge cases. Next, I looked at the tests for the Regex transformation, and I found that the tests are not very strict either. Also, I think this makes error tracking rather difficult, since the DSL is transformed, it is hard to figure out where the error is if you run into some edge cases. I’d rather write JavaScript and be at ease, instead of write poorly supported FrankensteinScript, and have no clue where went wrong.

Another part I don’t like about jSpec is the source code is rather cryptic. I have to say the author of jSpec is a very smart person. To me, his code is 50% recursive functional rocket science and 50% regex dark magic. It took me a long time to decrypt how the code is working under the hood, and I can’t say I understood it 100%. This makes contributing and extending very difficult for most busy programmers (including me) that just want to get the things done.

JSSpec

JSSepc is probably the oldest Framework that started to tackle the BDD domain in JavaScript. The initial release is dated July 16, 2007. Its features are relatively simple compare to above two frameworks.

Things I like about jSpec

JSSepc’s source code is simple and clean, and relatively easy to extend. It has very original syntax as well, Instead of using expect(foo).to(equal, true), its format is value_of(foo).should().be_true(), a bit less sweet… However, it is the first (I think) to tackle BDD in JavaScript, it is nice that they first invented this approach, and paved way for newer frameworks to learn from. The HTML report is very nice too. You can selectively run a set of suit right in the browser.

Things I don’t like about jSpec

  • It doesn’t support nested describe blocks.
  • It doesn’t support shared behaviors.
  • Not in active development. (Last commit was Dec. 2008)

Redcloth Ate My notextile Tag

Posted on April 07, 2009

While playing with textile and UltraViolet in Webby, I found textile is re-rendering my UltraViolet generated HTML contents disregarding tags. The problem is with UltraVilet versions 4.1.1 to 4.1.9 has ignored this tag somehow. There is even a bug ticket about it.

The solution?

sudo gem uninstall RedCloth -a
sudo gem install RedCloth -v=4.1.0

This installs RedCloth version 4.1.0 which doesn’t eat your <notextile> tags and behave correctly for me.
Next I just did a webby rebuild and everything worked out for me!

Cheers!

Posted in ruby | View Comments

Adding Blog Tags using Webby

Posted on April 06, 2009

The blog now looks better and better, but it is still missing a key feature — tags.

Let’s bust it out! Here is my plan:

  • Adding a tags attribute under each blog’s meta data
  • Make a helper that reads each blog and count the occurance of each tag
  • Make a partial that links to each tags
  • Make a rake task that auto generates tags folder

Adding a tags attribute under each blog’s meta data

This is easy, just open up a post and add a tags attribute to the meta data:

title         :   Adding Blog Tags using Webby
created_at    :   2009-04-06 19:12:00.343030 +08:00
blog_post     :   true
filter:
  - erb
  - textile
# Add some tags for this post
tags:
  - ruby
  - webby

Make tags helper

All I need to do is to make a tags helper module that does the counting for me, and register it with Webby. Here is the code:

# lib/tags_helper.rbS
module TagsHelper

  # find all blog posts
  def posts(limit=:all, find_options=nil)
    options = { :in_directory => 'articles', 
                :recursive => true,
                :blog_post => true,
                :sort_by => "created_at",
                :reverse => true}
    options.merge!(find_options) if find_options
    ::Webby::Resources.pages.find(limit, options)
  end
  
  def tags_hash
    return @tags_hash if @tags_hash
    @tags_hash = {}
    posts.each do |post|
      post.tags.each do |tag|
        @tags_hash[tag] ||=0
        @tags_hash[tag] += 1
      end if post.tags
    end
    @tags_hash
  end
  
  def posts_with_tag(tag, limit=:all, find_options=nil)
    posts(limit, find_options) do |post|
      post.tags && post.tags.include?(tag)
    end
  end
end

Webby::Helpers.register(TagsHelper)

posts is a handy little short cut for getting all blog posts, much shorter to type. You can also pass in the limit, and find_options to customize your find. Example:

# finding first 10 posts in blogs dir, and sorted in descending chronological order
posts(10, :in_directory => 'blogs', :sort_by => "created_at", :reverse => true)

tags_hash returns a hash with tag name and occurance as the key and value.

posts_with_tag finds all the blog posts related to a tag.

Make a partial

Now that we have the helper, we can make a partial that displays the tags. I made it in HAML:

%ul
  / sort tags in alphabetical order, and then generate links for each tag
  -tags_hash.keys.sort.each do |tag|
    %li
      %a{:href=>"/tags/#{tag}"}= tag
      ==(#{tags_hash[tag]})

You can see the partial in effect on the lower right side of the page in footer. This is basic and nothing fancy…

Make a Rake Task

Now the tags are in place, we want actually display the tags pages. We make a new rake task to generate all the tags page for us.

#tags.rake

require 'lib/tags.rb'
include TagsHelper
namespace :tags do
  desc "auto generate all tags page"
  task :generate do
    ::Webby.load_files
    tags_hash.keys.each do |tag|
      dir = Webby.site.tags_dir
      page = File.join(dir, File.basename(tag))
      page = Webby::Builder.create(page, :from => "#{Webby.site.template_dir}/tags/generate.erb",
                 :locals => {:tag => tag, :directory => dir})
    end
  end
  
  desc "remove all tags page"
  task :remove do
    rm_r Webby.site.content_dir + "/" + Webby.site.tags_dir
  end
  
  desc "regenerate all tags page"
  task :regenerate => [:remove, :generate]
end

You will also need the corresponding templates/tags/generate.erb, which you can find in my github account

This Blog is Made using Webby

Posted on April 06, 2009

After a few days of work, I finally finished the layout for my blog. During the construction of this blog, I wanted to use a very light framework. Being mainly a Ruby On Rails developer I found a ruby framework called Webby that works perfectly with my requirements.

From the Webby describes itself as:

“Webby is a fantastic little website management system. It would be called a content management system if it were a bigger kid. But, it’s just a runt with a special knack for transforming text. And that’s really all it does – manages the legwork of turning text into something else, an ASCII Alchemist if you will.”

Sounds nice?

It supports ERB, haml, sass, Textile, Markdown and a set of other arsenels you can use at your disposal. Another reason I choose Webby is because it supports UltraViolet which comes in handy when you need to demonstrate a few lines of code. Even though it also supports CodeRay , but I much perfer UltraViolet as it supports a lot more css hightlighting templates and languages.

Another highlight of Webby is that it uses A CSS framework called BluePrint This little CSS framework makes website layout a breeze. Plus it has a powerful customization utility that can generate custom sized grid with meaningful class names.

What about commenting?

As Maxime once commented about my idea of using Webby to generate a static Blog:

“A blog without comments aint a blog!”

Sure, you’ve got a point! My answer to this problem is Disqus. It provides a JavaScript Widget that handles all the blog comments for you. No more custom coding for comments, wrestling with SPAM, etc. Just drop in their code, and sit and relax. You’ve got a powerful commenting system on your blog already! Sweet…

Lastly, a Gift if you care

if the idea of making a blog with Webby sounds nice to you, maybe you can give it a try as well!

The source of this blog is hosted on GitHub.

Anyways, it was a lot of fun playing around using this little powerful framework, and through fun experiments, a blog is actually born! Life is beautiful…