Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Ruby tests are stupid. Use shell.

  • Loading branch information...
commit 28a3a2f1143af3a3ab63e032df9aa53f9d64b6f1 1 parent 651db77
@holman authored
View
8 Rakefile
@@ -45,11 +45,9 @@ end
task :default => :test
-require 'rake/testtask'
-Rake::TestTask.new(:test) do |test|
- test.libs << 'lib' << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
+desc "Run tests for boom"
+task :test do
+ exec "test/run"
end
desc "Open an irb session preloaded with this library"
View
13 test/cli.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env roundup
+
+describe "cli: tests around boom the binary — help, version, and so on"
+
+boom="./bin/boom"
+
+it_shows_help() {
+ $boom help | grep "boom: help"
+}
+
+it_shows_a_version() {
+ $boom --version | grep "running boom"
+}
View
24 test/helper.rb
@@ -1,24 +0,0 @@
-# coding: utf-8
-
-require 'test/unit'
-
-begin
- require 'rubygems'
- require 'redgreen'
-rescue LoadError
-end
-
-require 'mocha'
-
-$LOAD_PATH.unshift(File.dirname(__FILE__))
-$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-
-require 'boom'
-
-def boom_json(name)
- root = File.expand_path(File.dirname(__FILE__))
- Boom::Storage::Json.any_instance.stubs(:save).returns(true)
- Boom::Storage::Json.any_instance.stubs(:json_file).
- returns("#{root}/examples/#{name}.json")
- Boom.stubs(:storage).returns(Boom::Storage::Json.new)
-end
View
307 test/roundup
@@ -0,0 +1,307 @@
+#!/bin/sh
+# [r5]: roundup.5.html
+# [r1t]: roundup-1-test.sh.html
+# [r5t]: roundup-5-test.sh.html
+#
+# _(c) 2010 Blake Mizerany - MIT License_
+#
+# Spray **roundup** on your shells to eliminate weeds and bugs. If your shells
+# survive **roundup**'s deathly toxic properties, they are considered
+# roundup-ready.
+#
+# **roundup** reads shell scripts to form test plans. Each
+# test plan is sourced into a sandbox where each test is executed.
+#
+# See [roundup-1-test.sh.html][r1t] or [roundup-5-test.sh.html][r5t] for example
+# test plans.
+#
+# __Install__
+#
+# git clone http://github.com/bmizerany/roundup.git
+# cd roundup
+# make
+# sudo make install
+# # Alternatively, copy `roundup` wherever you like.
+#
+# __NOTE__: Because test plans are sourced into roundup, roundup prefixes its
+# variable and function names with `roundup_` to avoid name collisions. See
+# "Sandbox Test Runs" below for more insight.
+
+# Usage and Prerequisites
+# -----------------------
+
+# Exit if any following command exits with a non-zero status.
+set -e
+
+# The current version is set during `make version`. Do not modify this line in
+# anyway unless you know what you're doing.
+ROUNDUP_VERSION="0.0.5"
+export ROUNDUP_VERSION
+
+# Usage is defined in a specific comment syntax. It is `grep`ed out of this file
+# when needed (i.e. The Tomayko Method). See
+# [shocco](http://rtomayko.heroku.com/shocco) for more detail.
+#/ usage: roundup [--help|-h] [--version|-v] [plan ...]
+
+roundup_usage() {
+ grep '^#/' <"$0" | cut -c4-
+}
+
+while test "$#" -gt 0
+do
+ case "$1" in
+ --help|-h)
+ roundup_usage
+ exit 0
+ ;;
+ --version|-v)
+ echo "roundup version $ROUNDUP_VERSION"
+ exit 0
+ ;;
+ --color)
+ color=always
+ shift
+ ;;
+ -)
+ echo >&2 "roundup: unknown switch $1"
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+# Consider all scripts with names matching `*-test.sh` the plans to run unless
+# otherwise specified as arguments.
+if [ "$#" -gt "0" ]
+then
+ roundup_plans="$@"
+else
+ roundup_plans="$(ls *-test.sh)"
+fi
+
+: ${color:="auto"}
+
+# Create a temporary storage place for test output to be retrieved for display
+# after failing tests.
+roundup_tmp="$PWD/.roundup.$$"
+mkdir -p "$roundup_tmp"
+
+trap "rm -rf \"$roundup_tmp\"" EXIT INT
+
+# __Tracing failures__
+roundup_trace() {
+ # Delete the first two lines that represent roundups execution of the
+ # test function. They are useless to the user.
+ sed '1d' |
+ # Delete the last line which is the "set +x" of the error trap
+ sed '$d' |
+ # Replace the rc=$? of the error trap with an verbose string appended
+ # to the failing command trace line.
+ sed '$s/.*rc=/exit code /' |
+ # Trim the two left most `+` signs. They represent the depth at which
+ # roundup executed the function. They also, are useless and confusing.
+ sed 's/^++//' |
+ # Indent the output by 4 spaces to align under the test name in the
+ # summary.
+ sed 's/^/ /' |
+ # Highlight the last line in front of the exit code to bring notice to
+ # where the error occurred.
+ #
+ # The sed magic puts every line into the hold buffer first, then
+ # substitutes in the previous hold buffer content, prints that and starts
+ # with the next cycle. At the end the last line (in the hold buffer)
+ # is printed without substitution.
+ sed -n "x;1!{ \$s/\(.*\)/$mag\1$clr/; };1!p;\$x;\$p"
+}
+
+# __Other helpers__
+
+# Track the test stats while outputting a real-time report. This takes input on
+# **stdin**. Each input line must come in the format of:
+#
+# # The plan description to be displayed
+# d <plan description>
+#
+# # A passing test
+# p <test name>
+#
+# # A failed test
+# f <test name>
+roundup_summarize() {
+ set -e
+
+ # __Colors for output__
+
+ # Use colors if we are writing to a tty device.
+ if (test -t 1) || (test $color = always)
+ then
+ red=$(printf "\033[31m")
+ grn=$(printf "\033[32m")
+ mag=$(printf "\033[35m")
+ clr=$(printf "\033[m")
+ cols=$(tput cols)
+ fi
+
+ # Make these available to `roundup_trace`.
+ export red grn mag clr
+
+ ntests=0
+ passed=0
+ failed=0
+
+ : ${cols:=10}
+
+ while read status name
+ do
+ case $status in
+ p)
+ ntests=$(expr $ntests + 1)
+ passed=$(expr $passed + 1)
+ printf " %-48s " "$name:"
+ printf "$grn[PASS]$clr\n"
+ ;;
+ f)
+ ntests=$(expr $ntests + 1)
+ failed=$(expr $failed + 1)
+ printf " %-48s " "$name:"
+ printf "$red[FAIL]$clr\n"
+ roundup_trace < "$roundup_tmp/$name"
+ ;;
+ d)
+ printf "%s\n" "$name"
+ ;;
+ esac
+ done
+ # __Test Summary__
+ #
+ # Display the summary now that all tests are finished.
+ yes = | head -n 57 | tr -d '\n'
+ printf "\n"
+ printf "Tests: %3d | " $ntests
+ printf "Passed: %3d | " $passed
+ printf "Failed: %3d" $failed
+ printf "\n"
+
+ # Exit with an error if any tests failed
+ test $failed -eq 0 || exit 2
+}
+
+# Sandbox Test Runs
+# -----------------
+
+# The above checks guarantee we have at least one test. We can now move through
+# each specified test plan, determine its test plan, and administer each test
+# listed in a isolated sandbox.
+for roundup_p in $roundup_plans
+do
+ # Create a sandbox, source the test plan, run the tests, then leave
+ # without a trace.
+ (
+ # Consider the description to be the `basename` of the plan minus the
+ # tailing -test.sh.
+ roundup_desc=$(basename "$roundup_p" -test.sh)
+
+ # Define functions for
+ # [roundup(5)][r5]
+
+ # A custom description is recommended, but optional. Use `describe` to
+ # set the description to something more meaningful.
+ # TODO: reimplement this.
+ describe() {
+ roundup_desc="$*"
+ }
+
+ # Provide default `before` and `after` functions that run only `:`, a
+ # no-op. They may or may not be redefined by the test plan.
+ before() { :; }
+ after() { :; }
+
+ # Seek test methods and aggregate their names, forming a test plan.
+ # This is done before populating the sandbox with tests to avoid odd
+ # conflicts.
+
+ # TODO: I want to do this with sed only. Please send a patch if you
+ # know a cleaner way.
+ roundup_plan=$(
+ grep "^it_.*()" $roundup_p |
+ sed "s/\(it_[a-zA-Z0-9_]*\).*$/\1/g"
+ )
+
+ # We have the test plan and are in our sandbox with [roundup(5)][r5]
+ # defined. Now we source the plan to bring its tests into scope.
+ . ./$roundup_p
+
+ # Output the description signal
+ printf "d %s" "$roundup_desc" | tr "\n" " "
+ printf "\n"
+
+ for roundup_test_name in $roundup_plan
+ do
+ # Any number of things are possible in `before`, `after`, and the
+ # test. Drop into an subshell to contain operations that may throw
+ # off roundup; such as `cd`.
+ (
+ # Output `before` trace to temporary file. If `before` runs cleanly,
+ # the trace will be overwritten by the actual test case below.
+ {
+ # redirect tracing output of `before` into file.
+ {
+ set -x
+ # If `before` wasn't redefined, then this is `:`.
+ before
+ } &>"$roundup_tmp/$roundup_test_name"
+ # disable tracing again. Its trace output goes to /dev/null.
+ set +x
+ } &>/dev/null
+
+ # exit subshell with return code of last failing command. This
+ # is needed to see the return code 253 on failed assumptions.
+ # But, only do this if the error handling is activated.
+ set -E
+ trap 'rc=$?; set +x; set -o | grep "errexit.*on" >/dev/null && exit $rc' ERR
+
+ # If `before` wasn't redefined, then this is `:`.
+ before
+
+ # Momentarily turn off auto-fail to give us access to the tests
+ # exit status in `$?` for capturing.
+ set +e
+ (
+ # Set `-xe` before the test in the subshell. We want the
+ # test to fail fast to allow for more accurate output of
+ # where things went wrong but not in _our_ process because a
+ # failed test should not immediately fail roundup. Each
+ # tests trace output is saved in temporary storage.
+ set -xe
+ $roundup_test_name
+ ) >"$roundup_tmp/$roundup_test_name" 2>&1
+
+ # We need to capture the exit status before returning the `set
+ # -e` mode. Returning with `set -e` before we capture the exit
+ # status will result in `$?` being set with `set`'s status
+ # instead.
+ roundup_result=$?
+
+ # It's safe to return to normal operation.
+ set -e
+
+ # If `after` wasn't redefined, then this runs `:`.
+ after
+
+ # This is the final step of a test. Print its pass/fail signal
+ # and name.
+ if [ "$roundup_result" -ne 0 ]
+ then printf "f"
+ else printf "p"
+ fi
+
+ printf " $roundup_test_name\n"
+ )
+ done
+ )
+done |
+
+# All signals are piped to this for summary.
+roundup_summarize
View
6 test/run
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+# A shim to run our tests in shell. Boom is written for the shell, might as well
+# test it in shell.
+
+./test/roundup test/*.sh
View
30 test/test_color.rb
@@ -1,30 +0,0 @@
-require 'helper'
-
-class TestColor < Test::Unit::TestCase
-
- def test_colorize
- assert_equal "\e[35mBoom!\e[0m",
- Boom::Color.colorize("Boom!", :magenta)
- end
-
- def test_magenta
- assert_equal "\e[35mMagenta!\e[0m",
- Boom::Color.magenta("Magenta!")
- end
-
- def test_red
- assert_equal "\e[31mRed!\e[0m",
- Boom::Color.red("Red!")
- end
-
- def test_yellow
- assert_equal "\e[33mYellow!\e[0m",
- Boom::Color.yellow("Yellow!")
- end
-
- def test_cyan
- assert_equal "\e[36mCyan!\e[0m",
- Boom::Color.cyan("Cyan!")
- end
-
-end
View
238 test/test_command.rb
@@ -1,238 +0,0 @@
-# coding: utf-8
-
-require 'helper'
-
-# Intercept STDOUT and collect it
-class Boom::Command
-
- def self.capture_output
- @output = ''
- end
-
- def self.captured_output
- @output
- end
-
- def self.output(s)
- @output << s
- end
-
- def self.save!
- # no-op
- end
-
-end
-
-class TestCommand < Test::Unit::TestCase
-
- def setup
- boom_json :urls
- end
-
- def command(cmd)
- cmd = cmd.split(' ') if cmd
- Boom::Command.capture_output
- Boom::Command.execute(*cmd)
- output = Boom::Command.captured_output
- output.gsub(/\e\[\d\d?m/, '')
- end
-
- def test_overview_for_empty
- storage = Boom::Storage
- storage.stubs(:lists).returns([])
- Boom::Command.stubs(:storage).returns(storage)
- assert_match /have anything yet!/, command(nil)
- end
-
- def test_overview
- assert_equal ' urls (2)', command(nil)
- end
-
- def test_list_detail
- assert_match /github/, command('urls')
- end
-
- def test_list_all
- cmd = command('all')
- assert_match /urls/, cmd
- assert_match /github/, cmd
- end
-
- def test_list_creation
- assert_match /a new list called newlist/, command('newlist')
- end
-
- def test_list_creation_with_item
- assert_match /a new list called newlist.* item in newlist/, command('newlist item blah')
- end
-
- def test_list_creation_with_item_stdin
- STDIN.stubs(:read).returns('blah')
- STDIN.stubs(:stat)
- STDIN.stat.stubs(:size).returns(4)
-
- assert_match /a new list called newlist.* item in newlist is blah/, command('newlist item')
- end
-
- def test_list_creation_with_existing_items_name
- command('list item foo')
- assert_match /a new list called item.* key in item is bar/, command('item key bar')
- end
-
- def test_item_access
- IO.stubs(:popen)
- assert_match /copied https:\/\/github\.com to your clipboard/,
- command('github')
- end
-
- def test_item_access_scoped_by_list
- IO.stubs(:popen)
- assert_match /copied https:\/\/github\.com to your clipboard/,
- command('urls github')
- end
-
- def test_item_open_item
- Boom::Platform.stubs(:system).returns('')
- assert_match /opened https:\/\/github\.com for you/, command('open github')
- end
-
- def test_item_open_specific_item
- Boom::Platform.stubs(:system).returns('')
- assert_match /opened https:\/\/github\.com for you/, command('open urls github')
- end
-
- def test_item_open_lists
- Boom::Platform.stubs(:system).returns('')
- assert_match /opened all of urls for you/, command('open urls')
- end
-
- def test_item_creation
- assert_match /twitter in urls/,
- command('urls twitter http://twitter.com/holman')
- end
-
- def test_item_creation_long_value
- assert_match /is tanqueray hendricks bombay/,
- command('urls gins tanqueray hendricks bombay')
- end
-
- def test_list_deletion_no
- STDIN.stubs(:gets).returns('n')
- assert_match /Just kidding then/, command('urls delete')
- end
-
- def test_list_deletion_yes
- STDIN.stubs(:gets).returns('y')
- assert_match /Deleted all your urls/, command('urls delete')
- end
-
- def test_item_deletion
- assert_match /github is gone forever/, command('urls github delete')
- end
-
- def test_edit
- Boom::Platform.stubs(:system).returns('')
- assert_match 'Make your edits', command('edit')
- end
-
- def test_help
- assert_match 'boom help', command('help')
- assert_match 'boom help', command('-h')
- assert_match 'boom help', command('--help')
- end
-
- def test_noop_options
- assert_match 'boom help', command('--anything')
- assert_match 'boom help', command('-d')
- end
-
- def test_nonexistent_item_access_scoped_by_list
- assert_match /twitter not found in urls/, command('urls twitter')
- end
-
- def test_echo_item
- assert_match /https:\/\/github\.com/, command('echo github')
- end
-
- def test_echo_item_shorthand
- assert_match /https:\/\/github\.com/, command('e github')
- end
-
- def test_echo_item_does_not_exist
- assert_match /wrong not found/, command('echo wrong')
- end
-
- def test_echo_list_item
- assert_match /https:\/\/github\.com/, command('echo urls github')
- end
-
- def test_echo_list_item_does_not_exist
- assert_match /wrong not found in urls/, command('echo urls wrong')
- end
-
- def test_show_storage
- Boom::Config.any_instance.stubs(:attributes).returns('backend' => 'json')
- assert_match /You're currently using json/, command('storage')
- end
-
- def test_nonexistant_storage_switch
- Boom::Config.any_instance.stubs(:save).returns(true)
- assert_match /couldn't find that storage engine/, command('switch dkdkdk')
- end
-
- def test_storage_switch
- Boom::Config.any_instance.stubs(:save).returns(true)
- assert_match /We've switched you over to redis/, command('switch redis')
- end
-
- def test_version_switch
- assert_match /#{Boom::VERSION}/, command('-v')
- end
-
- def test_version_long
- assert_match /#{Boom::VERSION}/, command('--version')
- end
-
- def test_stdin_pipes
- stub = Object.new
- stub.stubs(:stat).returns([1,2])
- stub.stubs(:read).returns("http://twitter.com")
- Boom::Command.stubs(:stdin).returns(stub)
- assert_match /twitter in urls/, command('urls twitter')
- end
-
- def test_random
- Boom::Platform.stubs(:system).returns('')
- assert_match /opened .+ for you/, command('random')
- end
-
- def test_random_from_list
- Boom::Platform.stubs(:system).returns('')
- assert_match /(github|zachholman)/, command('random urls')
- end
-
- def test_random_list_not_exist
- Boom::Platform.stubs(:system).returns('')
- assert_match /couldn't find that list\./, command('random 39jc02jlskjbbac9')
- end
-
- def test_delete_item_list_not_exist
- assert_match /couldn't find that list\./, command('urlz github delete')
- end
-
- def test_delete_item_wrong_list
- command('urlz twitter https://twitter.com/')
- assert_match /github not found in urlz/, command('urlz github delete')
- end
-
- def test_delete_item_different_name
- command('foo bar baz')
- assert_match /bar is gone forever/, command('foo bar delete')
- end
-
- def test_delete_item_same_name
- command('duck duck goose')
- assert_match /duck is gone forever/, command('duck duck delete')
- end
-
-end
View
25 test/test_config.rb
@@ -1,25 +0,0 @@
-# coding: utf-8
-
-require 'helper'
-
-class TestConfig < Test::Unit::TestCase
-
- def setup
- Boom::Config.any_instance.stubs(:file).
- returns("test/examples/test_json.json")
-
- @config = Boom::Config.new
- @config.stubs(:save).returns(true)
- end
-
- def test_bootstraps_config
- @config.bootstrap
- assert_equal ({:backend => 'json'}), @config.attributes
- end
-
- def test_attributes
- @config.attributes[:wu_tang] = 'clan'
- assert_equal 'clan', @config.attributes[:wu_tang]
- end
-
-end
View
54 test/test_item.rb
@@ -1,54 +0,0 @@
-# coding: utf-8
-
-require 'helper'
-
-class TestItem < Test::Unit::TestCase
-
- def setup
- @item = Boom::Item.new('github','https://github.com')
- end
-
- def test_name
- assert_equal 'github', @item.name
- end
-
- def test_value
- assert_equal 'https://github.com', @item.value
- end
-
- def test_short_name
- assert_equal 'github', @item.short_name
- end
-
- def test_short_name
- @item.name = 'github github github lol lol lol'
- assert_equal 'github github g…', @item.short_name
- end
-
- def test_spacer_none
- @item.name = 'github github github lol lol lol'
- assert_equal '', @item.spacer
- end
-
- def test_spacer_tons
- assert_equal ' ', @item.spacer
- end
-
- def test_to_hash
- assert_equal 1, @item.to_hash.size
- end
-
- def test_url
- assert_equal 'https://github.com', @item.url
- end
-
- def test_url_with_additional_description
- @item = Boom::Item.new('github', 'social coding https://github.com')
- assert_equal 'https://github.com', @item.url
- end
-
- def test_url_without_url
- @item = Boom::Item.new('didum', 'dadam lol omg')
- assert_equal 'dadam lol omg', @item.url
- end
-end
View
79 test/test_list.rb
@@ -1,79 +0,0 @@
-# coding: utf-8
-
-require 'helper'
-
-class TestList < Test::Unit::TestCase
-
- def setup
- @list = Boom::List.new('urls')
- @item = Boom::Item.new('github','https://github.com')
- boom_json :urls
- end
-
- def test_name
- assert_equal 'urls', @list.name
- end
-
- def test_add_items
- assert_equal 0, @list.items.size
- @list.add_item(@item)
- assert_equal 1, @list.items.size
- end
-
- def test_add_item_with_duplicate_name
- @list.add_item(@item)
- assert_equal 1, @list.items.size
- assert_equal 'https://github.com', @list.find_item('github').value
- @diff_item = Boom::Item.new('github', 'https://github.com/home')
- @list.add_item(@diff_item)
- assert_equal 1, @list.items.size
- assert_equal 'https://github.com/home', @list.find_item('github').value
- end
-
- def test_to_hash
- assert_equal 0, @list.to_hash[@list.name].size
- @list.add_item(@item)
- assert_equal 1, @list.to_hash[@list.name].size
- end
-
- def test_find
- assert_equal 'urls', Boom::List.find('urls').name
- end
-
- def test_find_item
- @list.add_item(@item)
- assert_equal 'https://github.com', @list.find_item('github').value
- end
-
- def test_find_item_long_name
- @item = Boom::Item.new('long-long-long-name','longname')
- @list.add_item(@item)
- assert_equal 'longname', @list.find_item('long-long-long-').value
- assert_equal 'longname', @list.find_item('long-long-long-…').value
- end
-
- def test_delete_success
- assert_equal 1, Boom.storage.lists.size
- assert Boom::List.delete('urls')
- assert_equal 0, Boom.storage.lists.size
- end
-
- def test_delete_fail
- assert_equal 1, Boom.storage.lists.size
- assert !Boom::List.delete('robocop')
- assert_equal 1, Boom.storage.lists.size
- end
-
- def test_deletes_scoped_to_list
- @list.add_item(@item)
-
- @list_2 = Boom::List.new('sexy-companies')
- @item_2 = Boom::Item.new(@item.name, @item.value)
- @list_2.add_item(@item_2)
-
- @list.delete_item(@item.name)
- assert_equal 0, @list.items.size
- assert_equal 1, @list_2.items.size
- end
-
-end
View
52 test/test_platform.rb
@@ -1,52 +0,0 @@
-require 'helper'
-
-class TestPlatform < Test::Unit::TestCase
-
- def setup
-
- end
-
- def test_darwin
- assert_equal Boom::Platform.darwin?, RUBY_PLATFORM.include?('darwin')
- end
-
- def test_windows
- assert_equal Boom::Platform.windows?, true if RUBY_PLATFORM =~ /mswin|mingw/
- end
-
- def test_open_command_darwin
- Boom::Platform.stubs(:darwin?).returns(true)
- assert_equal Boom::Platform.open_command, 'open'
- end
-
- def test_open_command_windows
- Boom::Platform.stubs(:darwin?).returns(false)
- Boom::Platform.stubs(:windows?).returns(true)
- assert_equal Boom::Platform.open_command, 'start'
- end
-
- def test_open_command_linux
- Boom::Platform.stubs(:darwin?).returns(false)
- Boom::Platform.stubs(:windows?).returns(false)
- assert_equal Boom::Platform.open_command, 'xdg-open'
- end
-
- def test_copy_command_darwin
- Boom::Platform.stubs(:darwin?).returns(true)
- Boom::Platform.stubs(:windows?).returns(false)
- assert_equal Boom::Platform.copy_command, 'pbcopy'
- end
-
- def test_copy_command_windows
- Boom::Platform.stubs(:darwin?).returns(false)
- Boom::Platform.stubs(:windows?).returns(true)
- assert_equal Boom::Platform.copy_command, 'clip'
- end
-
- def test_copy_command_linux
- Boom::Platform.stubs(:darwin?).returns(false)
- Boom::Platform.stubs(:windows?).returns(false)
- assert_equal Boom::Platform.copy_command, 'xclip -selection clipboard'
- end
-
-end
Please sign in to comment.
Something went wrong with that request. Please try again.