Skip to content

Instantly share code, notes, and snippets.

@ericgj
Created January 9, 2012 15:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericgj/1583301 to your computer and use it in GitHub Desktop.
Save ericgj/1583301 to your computer and use it in GitHub Desktop.
Several things I learned this week: 9 Jan
  1. Trollop command-line parser lets you parse any array of tokens, not just ARGV. (todoer)
    1b. Bonus: how to have "plug in" options using Trollop
  2. When refactoring, it's often tricky to know where a particular set of changes are going to go. So it pays to look in detail at the code beforehand and not jump into writing specs when you don't even know the subject of the tests yet. But in looking at the code, it doesn't mean you're going in to make changes to it.
  3. You want to run several implementations, with a different set of fixtures, through the same set of specs. One way. (todoer)
# Trollop command-line parser lets you parse any array of tokens, not just ARGV.
opts = Trollop.options( Shellwords.split(str) ) do
#...
end
# and assuming you _don't_ want to exit, display help, etc. in such cases (you're not at the top level of your app):
p = Trollop::Parser.new do
#...
end
opts = p.parse(Shellwords.split(str))
# Bonus: how to have "plug in" options using Trollop
# where 'Plugin' is a module that provides the implementation of a given CLI option
# and has module-level accessors for :option_name, :option_desc, :option_type
plugins = [ PluginA, PluginB, PluginC ]
# parse the command line
opts = Trollop.options do
plugins.each do |plugin|
opt plugin.option_name, plugin.option_desc, :type => plugin.option_type
end
end
# get the command class
cmd = CLI::Commands.get(ARGV.shift)
# attach the plugin classes
cmd.extend *plugins
# and run command with the options
cmd.run(opts)
# You want to run several implementations, with a different set of fixtures, through the same set of specs. One way.
### test_my_adapter.rb
module Fixtures
def self.adapter_class
Adapters::MyAdapter
end
SIMPLE = #... concrete fixture/dummy/stub for simple case
COMPLEX = #... etc.
end
# run generic tests
require File.expand_path('test_adapter_generic',File.dirname(__FILE__))
### test_adapter_generic.rb
require 'minitest/spec'
MiniTest::Unit.autorun
module Fixtures
# for example - whatever variables you want to test for each input case
Expectation = Struct.new(:count, :categories, :names)
# the concrete fixtures have to be set up to match these specs
Expectations = {
'SIMPLE' => Expectation.new( 6, %w(1 2 3 4 5 6), %w(a b c d e f) ),
'COMPLEX' => Expectation.new #...
}
end
describe 'Adapter#method' do
def self.get_fixture(fixname)
unless fix = Fixtures.const_get(fixname) rescue nil
warn "Note: Fixture not found: '#{fixname}', skipping tests"
end
fix
end
Fixtures::Expectations.each do |(fixname, expects)|
next unless fix = get_fixture(fixname)
describe fixname do
before do
# or however the fixture gets injected into the adapter
@subject = Fixtures.adapter_class.new(fix)
end
# for example, showing how the expectations above are used
it 'must return expected count' do
assert_equal expects.count, @subject.count
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment