Permalink
Browse files

fivemat 1.0.0

  • Loading branch information...
0 parents commit 88d66871ef18fa4afe9cad63e233593b7fe71094 @tpope committed Apr 11, 2012
Showing with 259 additions and 0 deletions.
  1. +17 −0 .gitignore
  2. +2 −0 Gemfile
  3. +22 −0 LICENSE
  4. +20 −0 MIT-LICENSE
  5. +64 −0 README.md
  6. +2 −0 Rakefile
  7. +16 −0 fivemat.gemspec
  8. +15 −0 lib/fivemat.rb
  9. +29 −0 lib/fivemat/cucumber.rb
  10. +3 −0 lib/fivemat/minitest.rb
  11. +2 −0 lib/fivemat/minitest/autorun.rb
  12. +26 −0 lib/fivemat/minitest/unit.rb
  13. +41 −0 lib/fivemat/rspec.rb
@@ -0,0 +1,17 @@
+*.gem
+*.rbc
+.bundle
+.config
+.yardoc
+Gemfile.lock
+InstalledFiles
+_yardoc
+coverage
+doc/
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
@@ -0,0 +1,2 @@
+source 'https://rubygems.org'
+gemspec
22 LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Tim Pope
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
+Copyright (c) Tim Pope
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
+# Fivemat
+
+Why settle for a test output *format* when you can have a test output
+*fivemat*?
+
+I'm tired of the two *de facto* standards for test output:
+
+1. Bunch of dots — Wait till the end to see what failed, and
+ guess the dot count to estimate progress.
+2. Extreme verbosity — See failures as they happen if you pay very,
+ very close attention.
+
+In other words, you can choose between "too little" or "too much."
+
+I've looked at third party alternatives, but none of them did much for
+me. What I want is the middle ground: dots grouped by file. Thus,
+I give you Fivemat:
+
+ DoohickeyTest ....
+ KajiggerTest .........................F...........
+ 1) Failure:
+ test_isnt_actually_nil(KajiggerTest) [test/kajigger_test.rb:17]:
+ Expected nil to not be nil.
+ WhatchamacallitTest ................................................
+ WidgetTest ...E......
+ 2) Error:
+ ZeroDivisionError: divided by 0
+ test/widget_test.rb:20:in `/'
+ test/widget_test.rb:20:in `test_dividing_by_1'
+
+MiniTest, RSpec, and Cucumber are supported. Here, have some sample
+Cucumber output:
+
+ features/sign_in.feature ......F--........
+ no button with value or id or text 'Go' found (Capybara::ElementNotFound)
+ ./features/step_definitions/web_steps.rb:53:in `/^I press "([^"]*)"$/'
+ ./features/sign_in.feature:10:in `When I press "Log In"'
+ features/sign_out.feature .......
+ features/sign_up.feature ...............................................
+
+## Usage
+
+Start by adding `gem 'fivemat'` to your `Gemfile`.
+
+### MiniTest
+
+Change `require 'minitest/autorun'` to `require 'fivemat/minitest/autorun'`.
+
+### RSpec
+
+Add `--format Fivemat` to `.rspec`.
+
+### Cucumber
+
+Add `--format Fivemat` to `cucumber.yml`.
+
+## Contributing
+
+Don't forget to include test coverage for any changes you introduce.
+(Ha! I kid! Everybody knows it's impossible to test a test library.)
+
+## License
+
+Copyright © Tim Pope. MIT License.
@@ -0,0 +1,2 @@
+#!/usr/bin/env rake
+require "bundler/gem_tasks"
@@ -0,0 +1,16 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |gem|
+ gem.authors = ["Tim Pope"]
+ gem.email = ["code@tp" + 'ope.net']
+ gem.description = %q{MiniTest/RSpec/Cucumber formatter that gives each test file its own line of dots}
+ gem.summary = %q{Why settle for a test output format when you could have a test output fivemat?}
+ gem.homepage = "https://github.com/tpope/fivemat"
+
+ gem.files = `git ls-files`.split($\)
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
+ gem.name = "fivemat"
+ gem.require_paths = ["lib"]
+ gem.version = '1.0.0'
+end
@@ -0,0 +1,15 @@
+module Fivemat
+ autoload :Cucumber, 'fivemat/cucumber'
+ autoload :MiniTest, 'fivemat/minitest/unit'
+ autoload :RSpec, 'fivemat/rspec'
+
+ def self.new(*args)
+ case args.size
+ when 0 then MiniTest::Unit
+ when 1 then RSpec
+ when 3 then Cucumber
+ else
+ raise ArgumentError
+ end.new(*args)
+ end
+end
@@ -0,0 +1,29 @@
+require 'cucumber/formatter/progress'
+
+module Fivemat
+ class Cucumber < ::Cucumber::Formatter::Progress
+ def before_feature(feature)
+ @io.print "#{feature.file} "
+ @io.flush
+ @exceptions = []
+ end
+
+ def after_feature(feature)
+ @io.puts
+ @exceptions.each do |(exception, status)|
+ print_exception(exception, status, 2)
+ end
+ end
+
+ def exception(exception, status)
+ @exceptions << [exception, status]
+ super
+ end
+
+ def after_features(features)
+ @io.puts
+ print_stats(features, @options)
+ print_passing_wip(@options)
+ end
+ end
+end
@@ -0,0 +1,3 @@
+require 'fivemat/minitest/unit'
+
+MiniTest::Unit.runner = Fivemat::MiniTest::Unit.new
@@ -0,0 +1,2 @@
+require 'minitest/autorun'
+require 'fivemat/minitest'
@@ -0,0 +1,26 @@
+require 'minitest/unit'
+
+module Fivemat
+ module MiniTest
+ class Unit < ::MiniTest::Unit
+ def _run_suites(suites, type)
+ offset = 0
+ suites.reject do |suite|
+ filter = options[:filter] || '/./'
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
+ suite.send("#{type}_methods").grep(filter).empty?
+ end.map do |suite|
+ print "#{suite} "
+ result = _run_suite suite, type
+ puts
+ report.each_with_index do |msg, i|
+ puts "%3d) %s" % [offset + i + 1, msg.gsub(/\n/, "\n ")]
+ end
+ offset += report.size
+ report.clear
+ result
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,41 @@
+require 'rspec/core/formatters/progress_formatter'
+
+module Fivemat
+ class RSpec < ::RSpec::Core::Formatters::ProgressFormatter
+ def initialize(*)
+ super
+ @group_level = 0
+ @index_offset = 0
+ end
+
+ def example_group_started(group)
+ if @group_level.zero?
+ output.print "#{group.description} "
+ @failure_output = []
+ end
+ @group_level += 1
+ end
+
+ def example_group_finished(group)
+ @group_level -= 1
+ if @group_level.zero?
+ output.puts
+ failed_examples.each_with_index do |example, index|
+ if pending_fixed?(example)
+ dump_pending_fixed(example, @index_offset + index)
+ else
+ dump_failure(example, @index_offset + index)
+ end
+ dump_backtrace(example)
+ end
+ @index_offset += failed_examples.size
+ failed_examples.clear
+ end
+ end
+
+ def start_dump
+ # Skip the call to output.puts in the messiest way possible.
+ self.class.superclass.superclass.instance_method(:start_dump).bind(self).call
+ end
+ end
+end

0 comments on commit 88d6687

Please sign in to comment.