I still reading The RSpec Book, which is amazing! I´m doing a little review of what i´ve been reading about.

1.1 Creating Expectations

There are two methods available for checking expectations: should() and should_not().

1.2 Built-in Matchers

There are several matchers that can be used with should and should_not, which are divided into well-separated categories.

1.2.1 Equality: Equivalence and Identity

 cow.should == twin_cow
 cow.should === twin_cow
 cow.should eql(cow)
 cow.should equal(cow)

The == method is used to express equivalence and equal is used when you want the receiver and the argument to be the same object.

Note: Instead of using !=, you should use the should_not method!

1.2.2 Floating Point Calculations

 result.should be_close(3.14, 0.005)
 

When dealing with floating points, sometimes you expect 3.14 but 3.1415 is returned, which would be a pain to express on expectations if it wasn´t for the built in matcher be_close(), which takes two arguments: the floating point number you are expecting and the precision you require.

1.2.3 Regular Expressions

 result.should match(/this regexp/)

result.should =~ /this regexp/
 

This can be very useful when dealing with multiple-line expectations, instead of using the open file technique to compare contents.

1.2.4 Changes

 lambda {

User.create!(:role => "admin" )

}.should change{ User.admins.count }
 ## OR

 lambda {

User.create!(:role => "admin" )

}.should change{ User.admins.count }.to(1)

 ## OR

 lambda {

User.create!(:role => "admin" )

}.should change{ User.admins.count }.from(0).to(1)
 

This is really useful when working with database changes or changes to objects. Another way of writing this is by using the before_state -> change -> after_state technique, as follows:

 total.price.should == 0

buyer.inserts Product.new(:price => 250)

total.price.should == 250
 

The matcher is change(), which takes a block with the object attribute/method and accepts the from(), to() or by() modifiers.

1.2.5 Errors

 field = SoccerField.new(:players => 20)

lambda {

field.remove(:players, 25)

}.should raise_error(NotEnoughPlayers,“attempted to remove more players than there is on field”)
 

Useful when needed to check for Exceptions. The matcher is raise_error and takes an ExceptionObject and/or a String/Regexp.

1.2.6 Throw

 speech = Speech.new(:seats => 100)

100.times { speech.register Person.new }
 lambda {

speech.register Person.new

}.should throw_symbol(:speech_full, 100)
 

When dealing with “errors that are not really exceptions”, you use catch and throw. Rspec can check if a throw has been called by using the throw_symbol matcher. It accepts 0,1 or 2 arguments. The first argument needs to be a Symbol and the second can be any Object that is thrown along.

1.3 Predicate Matchers

A Ruby predicate method is a method that ends with a “?” and returns a boolean value, like string.empty? or regexp.match? methods. Rspec allows us to write expectations to these methods in a beautiful, understandable way, instead of writing:

 a_string.empty?.should == true
 

We can write:

 a_string.should be_empty
 

1.3.1 The be_something method

When using a be_something matcher, RSpec removes the “be_”, appends a “?” and calls the resulting method in the receiver.

A very common construct of this method is be_true, which checks if the receiver is true (any object except false or nil) or false (false or nil).

1.4 Checking ownership

Sometimes you will want to check not the object itself, but something the object owns. In this case, RSpec allows you to write some beautiful sentences to check for owned objects.

1.4.1 The have_something method

 request_parameters.has_key?(:id).should == true
 # is the same as

request_parameters.should have_key(:id)
 

RSpec uses method_missing to convert anything that begins with have_something to has_something? and performs the checking.

1.4.2 The have() method

 field.players.select {|p| p.team == home_team }.length.should == 9

# is the same as

home_team.should have(9).players_on(field)
 

As have() does not respond to players_on(), it delegates to the receiver (home_team). It encourages the home_team object to have useful methods like players_on.

You can get a NoMethodError if the players_on method doesn´t exist, you can get another NoMethodError if the result of the players_on method doesn´t respond to size() or length() and if the size of the collection doesn´t match the expected size, you will get a failed expectation.

1.5 Checking Collections Themselves

Sometimes we create expectations about a collection itself and not about an owned collection. RSpec lets us use the have() method to express this as well, as in:

 a_collection.should have(10).items
 

items is just providing some meaning to the expectation.

1.5.1 Strings

Strings are not collections by definition but they respond to a lot of methods that collections do, like length() and size(). This allow us to use have() to expect a string of a specific length.

 “lucas”.should have(5).characters
 

characters is just providing meaning to the expectation as well.

1.5.2 Have() modifiers for precision

The have() method has some relatives that allow us to check for upper and lower conditions.

 work.should have_exactly(8).hours

basket.should have_at_least(5).items

auditorium.should have_at_most(100).people
 

1.6 Operator Expressions

There may be sometimes when you want to expect a value to be not an exact amount but something like greater than or less than. RSpec allows you to do this by using the regular operators from Ruby!

 number.should == 3

number.should be >= 2

number.should be <= 4

number should be > 0
 

1.7 Generated Descriptions

Sometimes the code within a expectation looks the same as the string used to describe it. In this cases, you can omit the string by using the specify() method, which is an alias of the it() method but reads better when there is no documentation string.

 describe “A new user” do
 specify { User.new().should be_confused }
 end

 #is the same as:
 describe “A new user” do
 it “should be confused” do
 User.new.should be_confused
 end
 end
 

This should be used carefully and only in cases where the docstring and the code look exactly the same.

1.8 Subjects

Sometimes within an example group we want to use a subject on which we will develop the expectations. To create a subject you have to use the subject() method, which takes a code block creating the subject. Once you specify a subject, all the should() and should_not() methods can be called without a receiver as it will point to the subject in question.

 describe Rabbit
 subject { Rabbit.new(:age => 1) }
 specify { subject.should be_aged(1) }
 end
 # or even better
 describe Rabbit
 subject { Rabbit.new(:age => 1) }
 it { should be_aged(1) }
 end
 

You can also use implicit subjects when describing a class. RSpec will automatically create an instance of the described object, allowing us to write expectations like this:

 describe Rabbit
 it { should eat_carrots }
 end
 

This should be used with caution though! You should not coerce your objects to fit into this model instead of writing it as you should really have written!

1.9 Matchers Table and Thoughts

Matcher Used to expect
==, ===, eql, equal (other) Equality between objects
be_close(other, precision) Floating Points
match, =~ (other) Regular Expressions
CodeBlock.should Change(&attribute)[.by(num)][.from(num).to(num)] Changes in attributes
CodeBlock.should raise_error([ErrorClass,[Error String/Regexp]]) Exceptions
CodeBlock.should throw_symbol([Symbol,[Object]]) Throws
be_xxx (like be_empty) Predicate methods (ending on ?)
have_xxx (like have_key) has_xxx? Methods
have(number)[.receiver_method] Number informations
be (==,>=,>,<=,<) Operators
  • The specify() method can be used when a docstring looks like the code within the expectation.
  • The subject() method takes a code block and can be used to specify a subject. Once specified, the subject becomes the receiver for every should and should_not.
  • Subjects can be automatically created when describing a class. RSpec calls the new() method to the object and use it as the subject to the following expectations.
Advertisements

RSpec Example Building

January 26, 2010

Some stuff I´ve learned while reading the RSpec book, which is very good as the latest beta version.

  • describe and context are synonyms. Describe is better for actions and Context is better for hm.. well.. contexts! They work by supplying a string that describe the behavior you are trying to test (or a reference to a class or a Module) and a code block where the expectations should be placed.
    # some google code...
    describe User do
    describe "should not be chinese" do
    [...]
    
  • RSpec supports “nesting” to give context to your tests!
  • The it() method takes a string, an optional hash and an optional code block.
  • it() called with no block is marked as pending. Experienced developers recommend writing down everything you want the application to do, even when developing some other code if you remember something you missed, and leave it as pending until you get to it. Very easy to do, isn´t it?
  • Other ways to set a description to pending is by calling the pending() method inside of it. It even supports a code block that gets executed even with the description pending. If the code block succeeds, RSpec alerts you that it has been implemented (actually, it says it is fixed).
  • RSpec provides a before() method that takes supplied code block to be executed before all of the examples inside the context or before each of them. The only argument it takes is :all or :each. It´s highly recommended that you use :each as it starts a new context when checking an example.
  • The counterpart of the before method is the.. Hmm.. you guessed! The after method. It´s basically the same thing with the same arguments, except it runs after the examples have been executed, even if errors or exceptions are raised.
  • You can create helper methods that are methods defined inside the context that can be used by all the examples inside that context. It´s useful to keep things clean and DRY-compliant (Don´t Repeat Yourself). However, the goal is to make things clean but without loosing the readability. Keep things consistent!
  • To share helper methods across contexts, you can create a module with the methods and then include the module within the context.
  • You can share examples too! just start the example with shared_examples_for “name” do […] end and then call it within the context by using the it_should_behave_like “name” method.
  • Another way to share examples is by creating example modules, with the share_as :Name do […] end method. When needed, just include the created module inside the context by calling include Name.

I´m gonna keep it simple: Ruby has an excellent native debugger, that runs when you insert the -r debug parameter when calling the interpreter, such as this:


ruby -r debug [debug options] [program file] [program arguments]

Debugger commands are:

b[reak] [file:]line Set breakpoint at given line in file (default current file).
b[reak] [file:]name Set breakpoint at method in file.
b[reak] Display breakpoints and watchpoints.
wat[ch] expr Break when expression becomes true.
del[ete] [nnn] Delete breakpoint nnn (default all).
disp[lay] expr Display value of nnn every time debugger gets control.
disp[lay] Show current displays.
undisp[lay] [nnn] Remove display (default all).
c[ont] Continue execution.
s[tep] nnn=1 Execute next nnn lines, stepping into methods.
n[ext] nnn=1 Execute next nnn lines, stepping over methods.
fi[nish] Finish execution of the current function.
q[uit] Exit the debugger.
w[here] Display current stack frame.
f[rame] Synonym for where.
l[ist] [start–end] List source lines from start to end.
up nnn=1 Move up nnn levels in the stack frame.
down nnn=1 Move down nnn levels in the stack frame.
v[ar] g[lobal] Display global variables.
v[ar] l[ocal] Display local variables.
v[ar] i[stance] obj Display instance variables of obj.
v[ar] c[onst] Name Display constants in class or module name.
m[ethod] i[nstance] obj Display instance methods of obj.
m[ethod] Name Display instance methods of the class or module name.
th[read] l[ist] List all threads.
th[read] [c[ur[rent]]] Display status of current thread.
th[read] [c[ur[rent]]] nnn Make thread nnn current and stop it.
th[read] stop nnn Make thread nnn current and stop it.
th[read] resume nnn Resume thread nnn.
[p] expr Evaluate expr in the current context. expr may include assignment to variables and method invocations.
empty A null command repeats the last command.

Source: PickAxe

When searching for bottlenecks, your best bet is to use the benchmark module to check the execution of code chunks. The best thing to learn how to deal with the benchmark module is checking its documentation here.

There´s also an easy way to track your code execution: The profiler. To run it, you should just put the -r profile parameter when calling the interpreter.


ruby -r profile [program file] [program arguments]

Seems like an easy way to track down those nasty bottlenecks! Still, the best way to ensure great performance is to keep your code clean and avoid creating unnecessary crap!

Hope I remember this when running after my slow applications cemeteries!

Today i was reading the chapter 10 of my Programming Ruby book, about Ruby Exception Handling, Catch and Throw. Found some really interesting stuff, as usual, and i´m gonna write it all down here.

Exception Objects

Ruby lets you insert exception/error information into an object of class Exception (or its children). This object is passed to the preceding code, searching for a declaration that some code is capable of handling that exception. You can create your own Exception classes. To do this, all you need is to make your class children of StandardError or one of its children. It´s as simple as it gets:

class SomeVeryNastyError < StandardError
end

Error Handling

Things useful to know when dealing with error handling:

  • To cast an exception, just use the raise or Kernel.raise method. Arguments can be: raise [Exception class, [Message, [Callback array]]]
  • The code that is gonna have exception handling should be wrapped inside a begin/rescue/end block if it´s multilined or you can use rescue as a statement modifier for single-lines. The arguments to rescue clause are the exception classes it can handle (comma-separated) and an optional local variable to store a reference to the Exception object.
    begin
    # some code...
    rescue MyError, BadError, StandardError => err_reference
    #rescue stuff...
    end
    
  • Along with rescue, there are the else clause and the ensure clause:
    Code inside the else clause will execute if no exceptions happen;
    Code inside the ensure clause is always executed when the block terminates.

    begin
      # some code is executing and..
      raise SomeVeryNastyError, "Very nasty error occurred!"
    rescue SomeVeryNastyError => err_reference
      # here comes the rescue!
      puts "An error ocurred: #{err_reference.inspect}"
      # rescue code ...
    else
      puts "No error occurred!"
    ensure
      # having an error or not ...
      puts "execution ended!"
    end
    
  • There can be multiple rescue clauses within a block.
    begin
    #some code
    rescue ForcedError
    puts "Forced Error occurred!"
    rescue StandardError
    puts "Standard Error occurred!"
    end
    
  • A reference to the associated raised Exception object is placed into the global variable $!
  • Within a rescue clause, you can call the retry method, so that the code block begins its execution again.
  • You can add your own attributes and methods to your Exception classes.
    class MyError < StandardError
    attr_reader :ok_to_retry
    def initialize(retry)
    @ok_to_retry = retry
    end
    end
    begin
    #some code ...
    raise MyError(true)
    rescue MyError
    if $1.ok_to_retry
        puts "Retrying..."
        retry
      else
        puts "Not retrying!"
      end
    end
    

Catch and Throw

If you ever need to get a signal to terminate execution of some code, you will be in good hands when using catch and throw.

Firstly, you specify what to “catch”: it can be a Symbol or a String. A code block comes after and will be executed until it runs to the end or until the specified catch argument is thrown with the throw method. The throw method supports two arguments: a Symbol/String and a return value.

a = catch(:fire) do
  puts "Catching fire now!"
  throw(:fire,"fireee!")
end
puts a
# => fireee!

And that´s it for today! I´m heading towards chapter 11 of Programming Ruby tonight!
Feel free to post comments and examples in order to help me and the other fellas!

Other references: Programming RubySkorks post on exceptionsGoogle

Hello world!

January 18, 2010

Hello everyone!

My name is Lucas d’Acampora Prim and i´m a Ruby Noobie!

After spending about ten years programming PHP and playing with some low-level C++, i´ve decided to make programming as fun as it gets, and Ruby seems to be the gemstone that is gonna provide me that. Equipped with my Programming Ruby 1.9 by Dave Thomas (Amazon it!) i´m starting to get what this language has to offer and, believe me, i´m wowing.

Every time i´m learning something, i do it better by playing with it: writing it down, trying some examples, creating exercices, among other weird stuff so, as i want to learn to program in Ruby by the only best way i know, i´ve decided to create a place to write down every single nuance of the language and, not being a greedy selfish world-dominator nerd, i thought: – Oh! Why not creating a blog where everything learned get documented and publicated?

That´s what i am doing right now! Ruby Noobie is my way to document the things i´m learning and to make this content publicly-available, helping other people along their way to learn this astonishing programming language!

So welcome to Ruby Noobie! I´d love to see this blog as a space to learn with other beginners and as a way to learn Ruby (and Rails, of course!) while having fun!