respec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /*.gem
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ == 0.0.1 2012-05-17
2
+
3
+ * Hi.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) George Ogata
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,63 @@
1
+ ## Respec
2
+
3
+ Provides a command, `respec`, which wraps `rspec`, and records your
4
+ failing examples for easy rerunning.
5
+
6
+ ## How?
7
+
8
+ Run your specs:
9
+
10
+ respec
11
+
12
+ 3 fail. Rerun just the 3 failures like this:
13
+
14
+ respec f
15
+
16
+ Need to debug failure #1? Pop a `debugger` in your code, and rerun it
17
+ like this:
18
+
19
+ respec 1
20
+
21
+ This will just rerun failure 1. Once it's passing, rerun the 3 failing
22
+ examples again:
23
+
24
+ respec f
25
+
26
+ 1 is now fixed, but 2 and 3 are still failing - `respec f` will now
27
+ only run failures 2 and 3 again.
28
+
29
+ ## How it works
30
+
31
+ All that's happening is the list of failed examples is being recorded
32
+ in a file (`.respec_failures`). The `f` argument means "run these
33
+ recorded failures only." A numeric argument like `1` means "just run
34
+ that failure."
35
+
36
+ The list of failed examples is always updated _except_ when selecting
37
+ which failures to rerun with a number (more than one number can also
38
+ be given, incidentally).
39
+
40
+ ## Other tricks
41
+
42
+ You can pass `respec` file or directory names, just like
43
+ `rspec`. However, you can also just specify example names on the
44
+ command line:
45
+
46
+ respec 'My example name'
47
+
48
+ If the argument doesn't name an existing file, it's assumed to be an
49
+ example name.
50
+
51
+ There are a few other shortcuts. Do `respec --help` to see them all.
52
+
53
+ ## Contributing
54
+
55
+ * [Bug reports](https://github.com/oggy/respec/issues)
56
+ * [Source](https://github.com/oggy/respec)
57
+ * Patches: Fork on Github, send pull request.
58
+ * Include tests where practical.
59
+ * Leave the version alone, or bump it in a separate commit.
60
+
61
+ ## Copyright
62
+
63
+ Copyright (c) George Ogata. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'ritual'
data/bin/respec ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'respec'
4
+
5
+ app = Respec::App.new(*ARGV)
6
+ if app.help_only?
7
+ STDERR.puts app.help
8
+ else
9
+ STDERR.puts "++ #{app.command.join(' ')}"
10
+ exec *app.command
11
+ end
data/lib/respec.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Respec
2
+ autoload :VERSION, 'respec/version'
3
+ autoload :App, 'respec/app'
4
+ autoload :Formatter, 'respec/formatter'
5
+ end
data/lib/respec/app.rb ADDED
@@ -0,0 +1,117 @@
1
+ module Respec
2
+ class App
3
+ def initialize(*args)
4
+ if (i = args.index('--'))
5
+ @args = args.slice!(0...i)
6
+ @raw_args = args[1..-1]
7
+ else
8
+ @args = args
9
+ @raw_args = []
10
+ end
11
+ @formatter = 'progress'
12
+ @output_failures = true
13
+ process_args
14
+ end
15
+
16
+ def command
17
+ @command ||= ['rspec'] + formatter_args + generated_args + raw_args
18
+ end
19
+
20
+ def formatter_args
21
+ if @output_failures
22
+ formatter_path = File.expand_path('formatter.rb', File.dirname(__FILE__))
23
+ ['--require', formatter_path, '--format', 'Respec::Formatter', '--out', failures_path, '--format', @formatter]
24
+ else
25
+ []
26
+ end
27
+ end
28
+
29
+ attr_reader :generated_args, :raw_args
30
+
31
+ class << self
32
+ attr_accessor :failures_path
33
+ end
34
+ self.failures_path = ENV['RESPEC_FAILURES'] || File.expand_path("~/.respec_failures")
35
+
36
+ def help_only?
37
+ @help_only
38
+ end
39
+
40
+ def help
41
+ <<-EOS.gsub(/^ *\|/, '')
42
+ |USAGE: respec RESPEC-ARGS ... [ -- RSPEC-ARGS ... ]
43
+ |
44
+ |Run rspec recording failed examples for easy rerunning later.
45
+ |
46
+ |RESPEC-ARGS may consist of:
47
+ |
48
+ | f Rerun all failed examples
49
+ | <integer> Rerun only the n-th failure
50
+ | s Output specdoc format, instead of progress
51
+ | c Output context diffs
52
+ | <file name> Run specs in these files
53
+ | <other> Run only examples matching this pattern
54
+ | --help This! (Also 'help'.)
55
+ |
56
+ |RSPEC-ARGS may follow a '--' argument, and are passed
57
+ |directly to rspec.
58
+ |
59
+ |More info: http://github.com/oggy/respec
60
+ EOS
61
+ end
62
+
63
+ private
64
+
65
+ def process_args
66
+ args = []
67
+ files = []
68
+ @args.each do |arg|
69
+ if File.exist?(arg)
70
+ files << arg
71
+ elsif arg =~ /\A(--)?help\z/
72
+ @help_only = true
73
+ elsif arg == 'f'
74
+ if File.exist?(failures_path)
75
+ if failures.empty?
76
+ abort "No specs failed!"
77
+ else
78
+ failures.each do |line|
79
+ args << line.strip
80
+ end
81
+ end
82
+ else
83
+ warn "no fail file - ignoring 'f' argument"
84
+ end
85
+ elsif arg == 's'
86
+ @formatter = 'specdoc'
87
+ elsif arg == 'c'
88
+ args << '--diff' << 'context'
89
+ elsif arg =~ /\A\d+\z/
90
+ i = Integer(arg)
91
+ if (failure = failures[i - 1])
92
+ args << failure
93
+ @output_failures = false
94
+ else
95
+ warn "invalid failure: #{i} for (1..#{failures.size})"
96
+ end
97
+ else
98
+ args << '--example' << arg.gsub(/[$]/, '\\\\\\0')
99
+ end
100
+ end
101
+ @generated_args = args + files
102
+ end
103
+
104
+ def failures_path
105
+ self.class.failures_path
106
+ end
107
+
108
+ def failures
109
+ @failures ||=
110
+ if File.exist?(failures_path)
111
+ File.read(failures_path).split(/\n/)
112
+ else
113
+ []
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+
3
+ module Respec
4
+ class Formatter < RSpec::Core::Formatters::BaseFormatter
5
+ def start_dump
6
+ @failed_examples.each do |example|
7
+ output.puts example.metadata[:location]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Respec
2
+ VERSION = [0, 0, 1]
3
+
4
+ class << VERSION
5
+ include Comparable
6
+
7
+ def to_s
8
+ join('.')
9
+ end
10
+ end
11
+ end
data/respec.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ $:.unshift File.expand_path('lib', File.dirname(__FILE__))
2
+ require 'respec/version'
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'respec'
6
+ gem.version = Respec::VERSION
7
+ gem.authors = ['George Ogata']
8
+ gem.email = ['george.ogata@gmail.com']
9
+ gem.summary = "Rerun failing RSpec examples easily."
10
+ gem.homepage = 'http://github.com/oggy/respec'
11
+
12
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+
16
+ gem.add_development_dependency 'ritual', '~> 0.4.0'
17
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'spec_helper'
2
+ require 'rbconfig'
3
+
4
+ describe Respec do
5
+ CONFIG = (Object.const_defined?(:RbConfig) ? RbConfig : Config)::CONFIG
6
+ def respec(args)
7
+ ruby = File.join(CONFIG['bindir'], CONFIG['ruby_install_name'])
8
+ respec = "#{ROOT}/bin/respec"
9
+ output = `RESPEC_FAILURES=#{TMP}/failures.txt #{ruby} -I #{ROOT}/lib #{respec} #{args} 2>&1`
10
+ [$?, output]
11
+ end
12
+
13
+ def make_spec(params)
14
+ num_failures = params[:num_failures] or
15
+ raise ArgumentError, "expected :num_failures parameter"
16
+
17
+ source = "describe 'test' do\n"
18
+ (0...2).map do |i|
19
+ if i < num_failures
20
+ source << " it('#{i}') { 1.should == 2 }\n"
21
+ else
22
+ source << " it('#{i}') {}\n"
23
+ end
24
+ end
25
+ source << "end"
26
+ open(spec_path, 'w') { |f| f.puts source }
27
+ end
28
+
29
+ def spec_path
30
+ "#{TMP}/test_spec.rb"
31
+ end
32
+
33
+ it "should let you rerun failing specs until they all pass" do
34
+ make_spec(num_failures: 2)
35
+ status, output = respec(spec_path)
36
+ status.should_not be_success
37
+ output.should include('2 examples, 2 failures')
38
+
39
+ make_spec(num_failures: 1)
40
+ status, output = respec("#{spec_path} f")
41
+ status.should_not be_success
42
+ output.should include('2 examples, 1 failure')
43
+
44
+ make_spec(num_failures: 0)
45
+ status, output = respec("#{spec_path} f")
46
+ status.should be_success
47
+ output.should include('1 example, 0 failures')
48
+ end
49
+ end
@@ -0,0 +1,91 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'fileutils'
4
+
5
+ describe Respec::App do
6
+ FORMATTER_PATH = File.expand_path("#{ROOT}/lib/respec/formatter.rb", File.dirname(__FILE__))
7
+ FAIL_PATH = "#{TMP}/failures.txt"
8
+
9
+ Respec::App.failures_path = FAIL_PATH
10
+
11
+ def make_failures_file(*examples)
12
+ open Respec::App.failures_path, 'w' do |file|
13
+ examples.each do |example|
14
+ file.puts example
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "#generated_args" do
20
+ it "should run with --context if 'c' is given" do
21
+ app = Respec::App.new('c')
22
+ app.generated_args.should == ['--diff', 'context']
23
+ end
24
+
25
+ it "should run all failures if 'f' is given" do
26
+ make_failures_file 'a.rb:1', 'b.rb:2'
27
+ app = Respec::App.new('f')
28
+ app.generated_args.should == ['a.rb:1', 'b.rb:2']
29
+ end
30
+
31
+ it "should run the n-th failure if a numeric argument 'n' is given" do
32
+ make_failures_file 'a.rb:1', 'b.rb:2'
33
+ app = Respec::App.new('2')
34
+ app.generated_args.should == ['b.rb:2']
35
+ end
36
+
37
+ it "should interpret existing file names as file name arguments" do
38
+ FileUtils.touch "#{TMP}/existing.rb"
39
+ app = Respec::App.new("#{TMP}/existing.rb")
40
+ app.generated_args.should == ["#{TMP}/existing.rb"]
41
+ end
42
+
43
+ it "should treat other arguments as example names" do
44
+ FileUtils.touch "#{TMP}/FILE"
45
+ app = Respec::App.new("#{TMP}/FILE")
46
+ app.generated_args.should == ["#{TMP}/FILE"]
47
+ end
48
+ end
49
+
50
+ describe "#formatter_args" do
51
+ it "should include the respec and progress formatters by default" do
52
+ app = Respec::App.new
53
+ app.formatter_args.should == ['--require', FORMATTER_PATH, '--format', 'Respec::Formatter', '--out', FAIL_PATH, '--format', 'progress']
54
+ end
55
+
56
+ it "should include '--format specdoc' if an 's' argument is given" do
57
+ app = Respec::App.new('s')
58
+ app.formatter_args.should == ['--require', FORMATTER_PATH, '--format', 'Respec::Formatter', '--out', FAIL_PATH, '--format', 'specdoc']
59
+ end
60
+
61
+ it "should update the stored failures if no args are given" do
62
+ app = Respec::App.new
63
+ app.formatter_args.should == ['--require', FORMATTER_PATH, '--format', 'Respec::Formatter', '--out', FAIL_PATH, '--format', 'progress']
64
+ end
65
+
66
+ it "should update the stored failures if 'f' is used" do
67
+ app = Respec::App.new('f')
68
+ app.formatter_args.should == ['--require', FORMATTER_PATH, '--format', 'Respec::Formatter', '--out', FAIL_PATH, '--format', 'progress']
69
+ end
70
+
71
+ it "should not update the stored failures if a numeric argument is given" do
72
+ app = Respec::App.new('1')
73
+ app.formatter_args.should == []
74
+ end
75
+ end
76
+
77
+ describe "#raw_args" do
78
+ it "should pass arguments after '--' directly to rspec" do
79
+ app = Respec::App.new('--', '--blah')
80
+ app.raw_args.should == ['--blah']
81
+ end
82
+ end
83
+
84
+ describe "#command" do
85
+ it "should combine all the args" do
86
+ make_failures_file 'a.rb:1'
87
+ app = Respec::App.new('f', '--', '-t', 'TAG')
88
+ app.command.should == ['rspec', '--require', FORMATTER_PATH, '--format', 'Respec::Formatter', '--out', FAIL_PATH, '--format', 'progress', 'a.rb:1', '-t', 'TAG']
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,6 @@
1
+ $:.unshift File.expand_path('../lib', File.dirname(__FILE__))
2
+ require 'respec'
3
+ require 'tmpdir'
4
+
5
+ ROOT = File.expand_path('..', File.dirname(__FILE__))
6
+ TMP = Dir.tmpdir
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: respec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - George Ogata
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ritual
16
+ requirement: &70131397136780 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.4.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70131397136780
25
+ description:
26
+ email:
27
+ - george.ogata@gmail.com
28
+ executables:
29
+ - respec
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - CHANGELOG
35
+ - Gemfile
36
+ - LICENSE
37
+ - README.markdown
38
+ - Rakefile
39
+ - bin/respec
40
+ - lib/respec.rb
41
+ - lib/respec/app.rb
42
+ - lib/respec/formatter.rb
43
+ - lib/respec/version.rb
44
+ - respec.gemspec
45
+ - spec/integration_spec.rb
46
+ - spec/respec/app_spec.rb
47
+ - spec/spec_helper.rb
48
+ homepage: http://github.com/oggy/respec
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.10
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Rerun failing RSpec examples easily.
72
+ test_files:
73
+ - spec/integration_spec.rb
74
+ - spec/respec/app_spec.rb
75
+ - spec/spec_helper.rb
76
+ has_rdoc: