How I Learned To Love Testing by Gregg Polack from Levy Carneiro Jr. on Vimeo.
A computer science website with some additional odds and ends as well as my favorite programming language Ruby and the popular Ruby web framework Ruby on Rails(RoR).
Wednesday, July 7, 2010
Saturday, June 26, 2010
Using Object#tap
Object#tap is new to Ruby 1.9. This new method will allow us to modify the object its called upon and, after the block finishes, will return to us the original object.
We can use this feature to make our specs a bit more concise.
Here is an example using this spec...
describe Array do before(:all) do @array = Array.new @array << 1 end it "should have a length of 1" do @array.should have(1).element end end
We change it so.
describe Array do before(:all) {@array = Array.new.tap{|me| me << 1}} it "should have a length of 1" do @array.should have(1).element end end
This code says "create a new instance of class Array, pass it to the 'tap' block, modify it, and return the original now modified object."
@array = Array.new.tap{|me| me << 1}
Some Ruby Built In Global Variables
These maybe helpful to know:
$0 --- Returns the name of the file that ruby is executing $: --- Returns the directories Ruby searches to load external files $$ --- Returns the process id of the Ruby process
Friday, June 25, 2010
let, its, and subject
We're going to refactor a spec to a more concise size.
First here is our starting point:
describe Foobar do before(:each) do @foobar = Foobar.new end it "should not be nil" @foobar.should_not be_nil end describe "#length" do before(:each) do @length = @foobar.length end it "should == 10" do @length.should == 10 end end end
The above example uses 15 lines of code. Lets see if we can do better.
First we're going to replace the 'before' blocks with 'let' blocks.
The 'let' block returns an evaluated block. It really helps you define
players in your spec.
describe Foobar do let(:foobar) {Foobar.new} it "should not be nil" foobar.should_not be_nil end describe "#length" do let(:length) {foobar.length} it "should == 10" do length.should == 10 end end end
That's a bit better. We are now at 11 lines of code.
But, we can do better.
We're going to use 'subject' block. This allows us to call
'should' right within the block. We're also going to use an 'its' block.
The 'its' block will return to us the value of the message retrieved represented
by the symbol we passed to it.
describe Foobar do subject {Foobar.new} it {should_not be_nil} its(:length) {should == 10} end
Very good. We have brought it down to 5 lines.
What does the specdoc output look like?
Here it is:
Foobar - should not be nil Foobar length - should == 10
Modifying an Existing Ruby Class
First example is reopening the class and adding methods to it.
First, the original class:
class OriginalGangsta def shoot puts 'bang!' end def flee puts 'run muther###' end end
Now, we modify the class:
#load the original class require 'original_gangsta' #add some new methods class OriginalGangsta def lie puts "he dunnit" end def dance puts "I'm a dancin' fool" end end
We can also just modify an instance of the class:
og = OriginalGangsta.new class << og def cry puts "I never had a good home!" end end
or we can do it this way:
og = OriginalGangsta.new def og.cry puts "I never had a good home!" end
Sunday, May 16, 2010
Redirecting Console Output: File
f = File::open('console.log', 'w') begin temp_std_out = STDOUT.clone STDOUT.reopen(f) puts 'this will go to the file' ensure STDOUT.reopen(temp_std_out) puts 'this will go to the screen' end
Friday, May 14, 2010
Suppressing Console Output
describe NoisyClass do before :all do @noisy = NoisyClass.new silence_stream(STDOUT) do #The console output in this block #will never be seen @noisy.generate_console_output end end end
The 'silence_stream' method is defined in 'vendor/rails/activesupport/lib/active_support/core_ext/kernel/reporting.rb' and is used to silence any stream for the duration of the block.
Monday, March 29, 2010
Better Looking Console Output
We start by looking at what the default output looks like.
jleal@ubuntu-ruby:~/swapme$ ruby script/console Loading development environment (Rails 2.3.2) >> User.find(:first, :select => "id, email, created_at, updated_at") => #<User id: 1, email: "sell@gmail.com", created_at: "2010-03-29 04:51:37", updated_at: "2010-03-29 04:51:37">
Now lets see if we can improve things a bit. In order to accomplish this we're going to do the following things:
- Install and enable the 'hirb' ruby gem.
- Redirect the ActiveRecord logging to display on the console.
Hirb gem
Hirb is described on github as:
First we install the gem.
jleal@ubuntu-ruby:~$ sudo gem install hirb Successfully installed hirb-0.3.1 1 gem installed
Next we load the gem in the console.
jleal@ubuntu-ruby:~/swapme$ ruby script/console Loading development environment (Rails 2.3.2) >> require 'hirb' => [] >> Hirb.enable => true >>
Our output looks allot nicer.
>> User.find(:first, :select => "id, email, created_at, updated_at") +----+---------------------------+-------------------------+--------------+ | id | email | created_at | updated_at | +----+---------------------------+-------------------------+--------------+ | 1 | sell@gmail.com | 2010-03-29 04:51:37 UTC | 2010-03-29 04:51:37 UTC | +----+---------------------------+-------------------------+--------------+ 1 row in set >>
Redirecting ActiveRecord Logging.
Finally, we'll redirect ActiveRecord logging to display on the console. This is done with one line of code. Remember to reload so it takes effect.
>> ActiveRecord::Base.logger = Logger.new(STDOUT) => #<Logger:0xb6fb2b04 @formatter=nil, @level=0, @default_formatter=#<Logger::Formatter:0xb6fb2adc @datetime_format=nil>, @progname=nil, @logdev=#<Logger::LogDevice:0xb6fb2ab4 @mutex=#<Logger::LogDevice::LogDeviceMutex:0xb6fb2a8c @mon_waiting_queue=[], @mon_entering_queue=[], @mon_count=0, @mon_owner=nil>, @dev=#<IO:0xb7807570>, @shift_size=nil, @shift_age=nil, @filename=nil>> >> reload! Reloading... => true
Now let's see how things look.
>> User.find(:first, :select => "id, email, created_at, updated_at") User Load (15.7ms) SELECT id, email, created_at, updated_at FROM "users" LIMIT 1 +----+---------------------------+-------------------------+--------------+ | id | email | created_at | updated_at | +----+---------------------------+-------------------------+--------------+ | 1 | sell@gmail.com | 2010-03-29 04:51:37 UTC | 2010-03-29 04:51:37 UTC | +----+---------------------------+-------------------------+--------------+ 1 row in set
Very nice. We now have a more readable output plus we can see the actual SQL that was generated.
Hope you enjoyed this!