MicroTest just got smaller

Posted over 7 years back at Wood for the Trees

My little library (the smallest ever?) for bootstrapping and lightning-fast testing has just become smaller. I changed the interface a little: now everything is dependent on method name! So you still have two tests, one which expects true and the other false, and which one is determined by using ‘def should_’ or ‘def should_not_’. Oh happy days!


# A super-small testing suite based on method names.
# It has only two types of expectations: should and should_not.
# These two expectations begin the method name, after which you can
# place anything you like. A 'should_...' method will expect true as
# the result of calling the method. A 'should_not_...' method will,
# conversely, expect false.
#
# This is MicroTest's self-test:
#
#   TEST_ROOT = File.dirname(__FILE__) + '/..'
#   require TEST_ROOT + '/lib/microtest.rb'
#
#   class TestMicroTest < MicroTest
#     def should_expect_true
#       true
#     end
#
#     def should_not_expect_false
#       false
#     end
#   end
#
# An example:
#
#   class BinaryMicroTest < MicroTest
#     def should_exit_cleanly
#       `ruby #{MYEXEC}`; $? == 0
#     end
#     def should_not_exit_cleanly
#       `ruby #{MYEXEC} -garbage`; $? == 0
#     end
#   end
#
class MicroTest

  class MicroFailure < StandardError; end

  class << self

    attr_accessor :passed, :failed, :executed, :planned, :plan, :failures

    def run
      init
      execute
      report
    end

    def init
      self.passed, self.failed, self.executed = 0, 0, 0
      self.planned, self.plan = harvest
      self.failures = []
    end

    def harvest
      plan = []
      ObjectSpace.each_object(Class) do |k|
        plan << [k, k.instance_methods(false).grep(/^should_/)] if k < MicroTest
      end
      planned = plan.inject(0) { |c, ary| c += ary[1].size; c }
      [planned, plan]
    end

    def execute
      puts "Running #{self.planned} test(s)..."
      self.plan.each do |klass, tests|
        tests.each do |test|
          expectation = (test =~ /^should_not/ ? false : true)
          instance = klass.new
          r = catch_failures(klass, test) { expect(expectation) { instance.send(test) } }
          if r
            self.passed += 1
            print "."
            STDOUT.flush
          else
            self.failed += 1
            print "F"
            STDOUT.flush
          end
          self.executed += 1
        end
      end
    end

    def expect(expected, &block)
      raise MicroFailure, "should be #{expected}" unless block.call == expected
    end

    def catch_failures(klass, test)
      begin
        yield
        true
      rescue Exception => e
        self.failures << [klass, test, e]
        false
      end
    end

    def report
      puts "\n\n"
      puts "%d planned, %d executed, %d passed, %d failed." %
        [self.planned, self.executed, self.passed, self.failed]
      unless self.failures.empty?
        puts "\nFAILURE REPORT\n"
        self.failures.each { |f| report_failure(f) }
      end
    end

    def report_failure(f)
      puts "Suite: #{f[0]}\nTest: #{f[1]}\nException: #{f[2].class}\nMessage: #{f[2].message}"
      puts ("\t" << f[2].backtrace.join("\n\t"))
    end

  end

end

at_exit do
  MicroTest.run
end

MicroTest just got smaller

Posted over 7 years back at Wood for the Trees

My little library (the smallest ever?) for bootstrapping and lightning-fast testing has just become smaller. I changed the interface a little: now everything is dependent on method name! So you still have two tests, one which expects true and the other false, and which one is determined by using ‘def should_’ or ‘def should_not_’. Oh happy days!


# A super-small testing suite based on method names.
# It has only two types of expectations: should and should_not.
# These two expectations begin the method name, after which you can
# place anything you like. A 'should_...' method will expect true as
# the result of calling the method. A 'should_not_...' method will,
# conversely, expect false.
#
# This is MicroTest's self-test:
#
#   TEST_ROOT = File.dirname(__FILE__) + '/..'
#   require TEST_ROOT + '/lib/microtest.rb'
#
#   class TestMicroTest < MicroTest
#     def should_expect_true
#       true
#     end
#
#     def should_not_expect_false
#       false
#     end
#   end
#
# An example:
#
#   class BinaryMicroTest < MicroTest
#     def should_exit_cleanly
#       `ruby #{MYEXEC}`; $? == 0
#     end
#     def should_not_exit_cleanly
#       `ruby #{MYEXEC} -garbage`; $? == 0
#     end
#   end
#
class MicroTest

  class MicroFailure < StandardError; end

  class << self

    attr_accessor :passed, :failed, :executed, :planned, :plan, :failures

    def run
      init
      execute
      report
    end

    def init
      self.passed, self.failed, self.executed = 0, 0, 0
      self.planned, self.plan = harvest
      self.failures = []
    end

    def harvest
      plan = []
      ObjectSpace.each_object(Class) do |k|
        plan << [k, k.instance_methods(false).grep(/^should_/)] if k < MicroTest
      end
      planned = plan.inject(0) { |c, ary| c += ary[1].size; c }
      [planned, plan]
    end

    def execute
      puts "Running #{self.planned} test(s)..."
      self.plan.each do |klass, tests|
        tests.each do |test|
          expectation = (test =~ /^should_not/ ? false : true)
          instance = klass.new
          r = catch_failures(klass, test) { expect(expectation) { instance.send(test) } }
          if r
            self.passed += 1
            print "."
            STDOUT.flush
          else
            self.failed += 1
            print "F"
            STDOUT.flush
          end
          self.executed += 1
        end
      end
    end

    def expect(expected, &block)
      raise MicroFailure, "should be #{expected}" unless block.call == expected
    end

    def catch_failures(klass, test)
      begin
        yield
        true
      rescue Exception => e
        self.failures << [klass, test, e]
        false
      end
    end

    def report
      puts "\n\n"
      puts "%d planned, %d executed, %d passed, %d failed." %
        [self.planned, self.executed, self.passed, self.failed]
      unless self.failures.empty?
        puts "\nFAILURE REPORT\n"
        self.failures.each { |f| report_failure(f) }
      end
    end

    def report_failure(f)
      puts "Suite: #{f[0]}\nTest: #{f[1]}\nException: #{f[2].class}\nMessage: #{f[2].message}"
      puts ("\t" << f[2].backtrace.join("\n\t"))
    end

  end

end

at_exit do
  MicroTest.run
end

Rails 1.2.1, Prototype 1.5, Other Goodies...

Posted over 7 years back at zerosum dirt(nap) - Home

Wow what a big day. Immediately after the release of Rails 1.2.0, we get a quickie bugfix bump to 1.2.1 and a great post by DHH summarizing the features in the release. On top of this, we get Prototype 1.5.0, complete with a new web presence and some surprisingly good documentation.

This word - "Web" - I do not think it means what you think it means.

Posted over 7 years back at Ryan Tomayko's Writings

Bill Gates on Microsoft’s commitment to Web Standards in a recent interview by Molly E. Holzschlag (the question was on things like HTML and CSS and why they are so horribly implemented in IE):

But every year for 13, 14 years now we’ve not just followed and implemented standards, we’ve contributed. This WS stuff, … we contributed more Web standards than anyone!

That’s so sad.

Roy Fielding, almost five years ago, on “this WS stuff”:

If this thing is going to be called Web Services, then I insist that it actually have something to do with the Web. If not, I'd rather have the WS-I group responsible for abusing the marketplace with yet another CORBA/DCOM than have the W3C waste its effort pandering to the whims of marketing consultants. I am not here to accommodate the requirements of mass hysteria.

Naturally, Microsoft’s Chris Wilson will chair the new W3C HTML working group. If that’s not a slap in the face to web developers and designers everywhere, I don’t know what is.

I said good day sir!

Rails 1.2 Released

Posted over 7 years back at zerosum dirt(nap) - Home

Looks like 1.2 has been officially released. I’m sure that I’m not the first to notice :-p. To update your gems:

gem update rails --source http://gems.rubyonrails.org --include-dependencies

Enjoy!

Script Generate

Posted over 7 years back at Sporkmonger

Well, here’s an interesting mistake I just made. Went to generate a model for a Rails application I’m working on, but I made a typo. Instead of entering:

script/generate model ListedParts

I accidentally typed:

script generate model ListedParts

That of course, didn’t work. It just came back with:

Script started, output file is generate

Sadly, I was unaware of the functionality of script, so of course the first thing I did after that was:

cat generate

3 seconds later, my Powerbook was locked hard, and I had a 200 MB file in my directory.

Oops.

Breaking Change

Posted over 7 years back at The Hobo Blog

We do reserve the right to make breaking changes at this stage in the game you know :-)

The login attribute in the default user model has been renamed to username. (a nice easy way to change this has been added too). You might need to rattle off a quick migration to rename that column in your database in order to keep things working.

Breaking Change

Posted over 7 years back at The Hobo Blog

We do reserve the right to make breaking changes at this stage in the game you know :-)

The login attribute in the default user model has been renamed to username. (a nice easy way to change this has been added too). You might need to rattle off a quick migration to rename that column in your database in order to keep things working.

Oops! Hobo 0.4.2 released

Posted over 7 years back at The Hobo Blog

Um - little bit of a bug in 0.4.1. Let’s hope 0.4.3 is a more significant upgrade :-)

Oops! Hobo 0.4.2 released

Posted over 7 years back at The Hobo Blog

Um - little bit of a bug in 0.4.1. Let’s hope 0.4.3 is a more significant upgrade :-)

Hobo 0.4.1 released

Posted over 7 years back at The Hobo Blog

This release contains a variety of fixes and enhancements. One notable feature is support for RPC style “web-methods”. This gives you an easy way to expose methods on your model classes that don’t fit neatly into the REST/CRUD paradigm, e.g. reset_password. For the full low-down, see the change-log

Hobo 0.4.1 released

Posted over 7 years back at The Hobo Blog

This release contains a variety of fixes and enhancements. One notable feature is support for RPC style “web-methods”. This gives you an easy way to expose methods on your model classes that don’t fit neatly into the REST/CRUD paradigm, e.g. reset_password. For the full low-down, see the change-log

Seacoast Ruby UG First Meeting Tonight!

Posted over 7 years back at zerosum dirt(nap) - Home

If you’re in the seacoast NH area (north of Boston), don’t forget to attend the first meeting of the Seacoast Ruby/Rails User Group tonight from 7-9 at the UNH campus. Apparently there was such an overwhelming response that Scott had to move the location to Morse Hall in order to accommodate the additional heads. Wow, cool. More information and directions are on Scott’s blog. See you there!

Tom on Hobo on Ruby on Rails in Canada and London

Posted over 7 years back at The Hobo Blog

Just thought I’d let you know there are going to be a couple of opportunities to see me rambling on about Hobo. One soon and local, the other not so much.

On 9th February, there’s a Rails “mini-conf”, hosted by Skills Matter. Skills Matter are the training company who run the Rails course written by Chad Fowler and delivered by yours truly and others.

I’m also very happy to say I’ve been invited to present on Hobo at the Canada on Rails conference in October in Toronto. A big thank-you to Nathaniel Brown for the invite.

Really looking forward to both of these events!

p.s. Hobo 0.4.1 is just around the corner.

Tom on Hobo on Ruby on Rails in Canada and London

Posted over 7 years back at The Hobo Blog

Just thought I’d let you know there are going to be a couple of opportunities to see me rambling on about Hobo. One soon and local, the other not so much.

On 9th February, there’s a Rails “mini-conf”, hosted by Skills Matter. Skills Matter are the training company who run the Rails course written by Chad Fowler and delivered by yours truly and others.

I’m also very happy to say I’ve been invited to present on Hobo at the Canada on Rails conference in October in Toronto. A big thank-you to Nathaniel Brown for the invite.

Really looking forward to both of these events!

p.s. Hobo 0.4.1 is just around the corner.