DeepTest 2.0 in the works
June 24th, 2009
I’ve started on a significant overhaul of DeepTest which will be released as version 2.0 when it’s finished. I thought I’d share some of my plans for what 2.0 will include and some thoughts about what might come versions after. I don’t have a timetable for yet, but work so far is going fairly quickly.
Plans for DeepTest 2.0
- A revamped distributed DeepTest architecture that will help ease setup and maintenance.
- A new console user interface that will provide much more information about what is going on during the test run
- Much better error handling & reporting (no more “Maybe an error was printed above?”!)
- RSpec integration that doesn’t break with every new release of rspec.
- Automatic configuration for Rails projects
What comes after 2.0? The next big feature I’d like to implement is support for cloud testing with deep test on EC2. Other than that, the features coming after 2.0 will likely be driven be requests. Is there a feature you’d like to see in DeepTest? Comment here or message me (qxjit) on github and we’ll get it rolling!
30 Days of Tech: Day 30 - Haskell Decompose
June 30th, 2008
Some time ago Tom, a friend, presented a math programming challenge to a me and a few others. The challenge was to create a function that when given a positive number would return a set of all the sets of positive numbers whose sum was the original number. He wasn’t so much interested in the result itself as he was in what sort of techniques were used in the implementation—memoization of course being a choice candidate for this problem. I was toying a lot with Haskell at the time, and since this was fundamentally a math problem, Haskell seemed well suited to the problem too.
Read the rest of this entry30 Days of Tech: Day 29 - C, Ruby, & Threads, Oh My!
June 29th, 2008
When Philippe and I worked on SystemTimer together we went back and forth about how much to write in Ruby and how much to write in C. Writing purely at the C level gave us more control over what was happening in the Ruby process as we installed and cleared signal handlers and such, but working in Ruby produced far more readable code.
Read the rest of this entry30 Days of Tech: Day 28 - lambda args
June 28th, 2008
The Ruby documentation for the lambda method (a.k.a. proc) says “Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.” This is almost exactly right. There are, however, at least two cases where this turns out to be false.
30 Days of Tech: Day 27 - Short Circuited Timeout
June 27th, 2008
Ruby’s timeout method operates by raising a exception, Timeout::Error. Timeout::Error inherits from Interrupt, SignalException, and finally Exception. In particular, it doesn’t inherit from StandardError, which means it isn’t caught by a default rescue clause with no exception class specified. When I first encountered this, I was annoyed that I had to explicitly catch timeout errors anytime I wanted to recover from errors in general, whether they were timeout errors or not. I realized something the other day that changed my opinion on this however.
30 Days of Tech: Day 26 - Fixnum#object_id
June 26th, 2008
In Ruby every object has an object_id that uniquely identifies that object in that particular instance of the Ruby process. Ruby also treats integers as objects—they are instances of Fixnum. For efficiency reasons, though, Ruby implements integers internally as simple values. That is, it doesn’t allocate heap memory for every integer you use, it just passes the value around instead. So how does Ruby generate object ids for all these integers?
30 Days of Tech: Day 25 - Gem dependency version
June 25th, 2008
RubyGems and I had a fight. It was about what version of net-ssh we wanted to have installed on my machine. RubyGems wanted the latest (2.0.2) and I wanted a 1.x version (1.1.4). Apparently net-ssh 2 has an issue with sshing into Fedora Core 4, which I needed it to do. Specifically I needed to use capistrano 1.4.1 to deploy an app to Fedora Core 4
30 Days of Tech: Day 24 - drubyall
June 24th, 2008
When we first started trying to use distributed DeepTest, we quickly ran into an issue with DRb servers not binding to the correct addresses. DRb does provide a way to bind to 0.0.0.0 to listen to all addresses, but there’s a downside to the way it does it. The url you provide to DRb to accomplish this must omit the hostname (e.g. druby://:0/). DRb then determines what hostname to report to clients by calling getaddrinfo with the empty hostname. Unfortunately for us getaddrinfo didn’t provide a hostname that could be used by our developer machines to connect to the DeepTest servers. For a brief moment we thought we were stuck.
30 Days of Tech: Day 23 - DearSoul
June 23rd, 2008
class DearSoul
def self.new(first, last)
ObjectSpace.define_finalizer(allocate, proc {|id|
puts "Goodbye, #{first}. We'll miss you."
})
end
end
DearSoul.new("George", "Carlin")
30 Days of Tech: Day 22 - Class#to_proc
June 22nd, 2008
Here’s a little hack for Ruby classes that comes from a project.
class Class
def to_proc
method(:new).to_proc
end
end
If you’ve ever used map (a.k.a. collect) to create a bunch of objects you might be familiar with code that looks something like this.
value_list.map {|v| Something.new(v)}
With Class#to_proc this can be simplified to
value_list.map(&Something)
This works very well for map, but I haven’t seen Class#to_proc become useful in any other situation to date. Even changing map to collect changes my opinion of it’s expressiveness. I don’t know that Class#to_proc is pulls its weight in our situation, but I just like the map statement above too much to give it up.
30 Days of Tech: Day 21 - Object Literals
June 21st, 2008
You can do object oriented programming in both Ruby and Javascript. I think most people would agree that Ruby is “more” object oriented than Javascript, whatever subjective judgement they’re using. One thing that’s interesting to me, though, is that Javascript has a syntax for literal objects built in where as Ruby does not.
Read the rest of this entry30 Days of Tech: Day 20 - Unmixed Methods
June 20th, 2008
mixology is a Ruby extension implemented by some of the Something Nimble collaborators. In short, it allows you to add modules to Objects (much like Ruby’s extend), but in such a way that they can also be removed. Mixology refers to these operations as mixin and unmix. If you want to know more about Mixology and the people behind it, here is a good resource. For the purposes of our discussion, here’s a simple example:
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def foo; puts "bar"; end
irb(main):004:1> end
=> nil
irb(main):005:0> o = Object.new
=> #<Object:0x4f2b8>
irb(main):006:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4f2b8>
from (irb):6
irb(main):007:0> o.mixin A
=> #<Object:0x4f2b8>
irb(main):008:0> o.foo
bar
=> nil
irb(main):009:0> o.unmix A
=> #<Object:0x4f2b8>
irb(main):010:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4f2b8>
from (irb):10
We can see that after o.unmix A the foo method is no longer accessible on the object o. But is there any way we could end up executing the foo method anyhow? It turns out there is. Let’s look at this example:
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def foo; puts self.inspect; end
irb(main):004:1> end
=> nil
irb(main):005:0> o = Object.new
=> #<Object:0x4d1ac>
irb(main):006:0> o.mixin A
=> #<Object:0x4d1ac>
irb(main):007:0> o.foo
#<Object:0x4d1ac>
=> nil
irb(main):008:0> foo = o.method(:foo)
=> #<Method: Object(A)#foo>
irb(main):009:0> o.unmix(A)
=> #<Object:0x4d1ac>
irb(main):010:0> o.foo
NoMethodError: undefined method `foo' for #<Object:0x4d1ac>
from (irb):10
irb(main):011:0> foo.call
#<Object:0x4d1ac>
=> nil
In this second example we can see that even though foo can’t be invoked through the object (since module A is no longer mixed in), Ruby has no problem invoking the method using the Method object that was grabbed before unmixing A. So yes, we can access foo if we should absolutely need to. There is one gotcha with this technique, however—even though we are in foo, no other methods from A are available!
irb(main):001:0> require 'rubygems'; require 'mixology'
=> true
irb(main):002:0> module A
irb(main):003:1> def called_as_method_object
irb(main):004:2> puts "got in, executing method_no_longer_available"
irb(main):005:2> method_no_longer_available
irb(main):006:2> end
irb(main):007:1>
irb(main):008:1* def method_no_longer_available
irb(main):009:2> raise "Will never make it"
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> o = Object.new
=> #<Object:0x366dc>
irb(main):013:0> o.mixin A
=> #<Object:0x366dc>
irb(main):014:0> method = o.method(:called_as_method_object)
=> #<Method: Object(A)#called_as_method_object>
irb(main):015:0> o.unmix A
=> #<Object:0x366dc>
irb(main):016:0> method.call
got in, executing method_no_longer_available
NameError: undefined local variable or method `method_no_longer_available' for #<Object:0x366dc>
from (irb):5:in `called_as_method_object'
from (irb):16:in `call'
from (irb):16
from :0
The implication of this is significant. If the code in called_as_method_object becomes complicated, you can’t even perform extract method to refactor it! Given that this technique is obscure to begin with and has this major limitation, I recommend you not use it if at all possible. That being said, you may find yourself in a situation where it’s the best option available, at least for the moment. I mean, how else would I come up with this stuff?
30 Days of Tech: Day 19 - instance_eval & Method#to_proc
June 19th, 2008
Ruby has instance_eval that accepts a block and executes it with self set to the receiver of instance_eval. Ruby also has a method called method that returns a Method object representing a callable method on an object. Method objects, in turn, have a method called to_proc which allows them to be converted to blocks. These are all facts I knew when the day began, but never before had this question occurred to me: what happens when you pass the result of Method#to_proc into instance_eval? What is self? The answer surprised me actually…
30 Days of Tech: Day 18 - Ajax Defined JS
June 18th, 2008
If you’re using prototype.js for Ajax and updating your page with HTML that defines new javascript functions, you’re likely to encounter issues. One solution is to pull the function definitions out of the HTML to a javascript file that is loaded when the page first loads. More often than not this is the correct solution. However, understanding the problem is quite instructive and leads to another solution that can be used in a pinch when pulling the function out is not an option. ...
Read the rest of this entry30 Days of Tech: Day 17 - Nesting
June 17th, 2008
ruby-doc.org describes Module.nesting as “the list of Modules nested at the point of call.” What does this really mean? ...