zaphod 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ require "spec_helper"
2
+
3
+ require 'simplecov/formatter/zaphod_formatter'
4
+
5
+ describe SimpleCov::Formatter::ZaphodFormatter do
6
+ let( :result ) do
7
+ SimpleCov::Result.new(
8
+ File.expand_path( "./lib/zaphod/spike.rb" ) => [1, 1, 1, 0, nil, nil, nil]
9
+ )
10
+ end
11
+
12
+ let!( :source_control ) { Object.new }
13
+
14
+ before :each do
15
+ stub( Zaphod::SourceControl ).git { source_control }
16
+ stub( source_control ).changes { Zaphod::ChangeSet.new([]) }
17
+ end
18
+
19
+ describe "#format( result )" do
20
+ it "gets the current changes from source control" do
21
+ mock( Zaphod::SourceControl ).git( Dir.pwd ) { source_control }
22
+ subject.format result
23
+ end
24
+
25
+ context "when the uncovered lines include the current changes" do
26
+ let( :source_changes ) do
27
+ Zaphod::ChangeSet.new([
28
+ Zaphod::CodeChange.new( "./lib/zaphod/spike.rb", [" @var = \"foo\"\n"] )
29
+ ])
30
+ end
31
+
32
+ before :each do
33
+ stub( source_control ).changes { source_changes }
34
+ end
35
+
36
+ it "runs the configured on_failure action, passing uncovered changes" do
37
+ failed = false
38
+ Zaphod.configure do |config|
39
+ config.on_failure { |diff| failed = diff }
40
+ end
41
+
42
+ subject.format result
43
+
44
+ expect( failed ).to eq( source_changes.changes )
45
+ end
46
+ end
47
+
48
+ context "when the uncovered lines do not include the current changes" do
49
+ before :each do
50
+ stub( source_control ).changes { Hash.new }
51
+ end
52
+
53
+ it "proceeds normally" do
54
+ subject.format result
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#uncovered( result )" do
60
+ subject { described_class.new.uncovered result }
61
+
62
+ it { should_not be_empty }
63
+
64
+ it "includes a code set for the file in the result" do
65
+ subject.first.path.should eq File.expand_path("./lib/zaphod/spike.rb")
66
+ end
67
+
68
+ it "provides the uncovered source lines to the code set" do
69
+ code_change = subject.first
70
+ code_change.source.first.should =~ /@var/
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,18 @@
1
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
2
+
3
+ require 'zaphod'
4
+ Zaphod.setup
5
+
6
+ RSpec.configure do |config|
7
+ config.treat_symbols_as_metadata_keys_with_true_values = true
8
+ config.run_all_when_everything_filtered = true
9
+ config.filter_run :focus
10
+
11
+ config.mock_with :rr
12
+
13
+ # Run specs in random order to surface order dependencies. If you find an
14
+ # order dependency and want to debug it, you can fix the order by providing
15
+ # the seed, which is printed after each run.
16
+ # --seed 1234
17
+ config.order = 'random'
18
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ require 'zaphod/code_change'
4
+ require 'zaphod/change_set'
5
+
6
+ module Zaphod
7
+ describe ChangeSet do
8
+ let( :changes ) do
9
+ [
10
+ Zaphod::CodeChange.new( "/dev/null", ["stuff"] ),
11
+ Zaphod::CodeChange.new( "/dev/null", ["stuff"] ),
12
+ ]
13
+ end
14
+
15
+ describe "construction" do
16
+ it "accepts a list of CodeChanges" do
17
+ described_class.new changes
18
+ end
19
+
20
+ it "rejects duplicates" do
21
+ expect( described_class.new( changes ) ).to have( 1 ).item
22
+ end
23
+ end
24
+
25
+ describe "iteration" do
26
+ subject do
27
+ described_class.new changes
28
+ end
29
+
30
+ it "yields each change to a given block" do
31
+ subject.map { |c| c.class }.uniq.should == [Zaphod::CodeChange]
32
+ end
33
+
34
+ it "returns an iterator if no block is given" do
35
+ i = subject.map
36
+ i.should be_an_instance_of Enumerator
37
+ end
38
+ end
39
+
40
+ describe "#intersection" do
41
+ let( :set1 ) do
42
+ described_class.new([
43
+ CodeChange.new( "/dev/null", ["baz"] ),
44
+ CodeChange.new( "./lib/zaphod/spike.rb", ["+ foo"] )
45
+ ])
46
+ end
47
+ let( :set2 ) do
48
+ described_class.new([
49
+ CodeChange.new( "/dev/null", ["baz"] )
50
+ ])
51
+ end
52
+
53
+ it do
54
+ expect( set1.intersection( set2 ) ).
55
+ to eq( Set.new([ CodeChange.new( "/dev/null", ["baz"] ) ]) )
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'zaphod/code_change'
3
+ module Zaphod
4
+ describe CodeChange do
5
+ describe "construction" do
6
+ it "accepts a list of source lines" do
7
+ source = ["require 'foo'", "puts 'bar'"]
8
+ set = Zaphod::CodeChange.new "./lib/zaphod/spike.rb", source
9
+ set.source.should == source
10
+ end
11
+
12
+ it "expands the given path" do
13
+ path = "./lib/zaphod/spike.rb"
14
+ expect( CodeChange.new( path ).path ).
15
+ to eq( File.expand_path( path ) )
16
+ end
17
+ end
18
+
19
+ describe "#eql?" do
20
+ context "when the paths and source are equal" do
21
+ let( :change1 ) { CodeChange.new ".lib/zaphod/spike.rb", ["foo"] }
22
+ let( :change2 ) { CodeChange.new ".lib/zaphod/spike.rb", ["foo"] }
23
+
24
+ it( "is true" ) { expect( change1 ).to eql( change2 ) }
25
+ end
26
+
27
+ context "when the source list is empty" do
28
+ let( :change1 ) { CodeChange.new ".lib/zaphod/spike.rb" }
29
+ let( :change2 ) { CodeChange.new ".lib/zaphod/spike.rb" }
30
+
31
+ it( "is not true" ) { expect( change1 ).to_not eql( change2 ) }
32
+ end
33
+
34
+ context "when the sources differ" do
35
+ let( :change1 ) { CodeChange.new ".lib/zaphod/spike.rb", ["bar"] }
36
+ let( :change3 ) { CodeChange.new ".lib/zaphod/spike.rb", ["foo"] }
37
+
38
+ it( "is not true" ) { expect( change1 ).to_not eql( change3 ) }
39
+ end
40
+
41
+ context "when the sources overlap" do
42
+ let( :change1 ) do
43
+ CodeChange.new "./lib/zaphod/spike.rb", [
44
+ "require 'foo'",
45
+ "Foo.bar!"
46
+ ]
47
+ end
48
+
49
+ let( :change2 ) do
50
+ CodeChange.new "./lib/zaphod/spike.rb", [
51
+ "require 'foo'",
52
+ "Foo.bar!",
53
+ "Bar.baz"
54
+ ]
55
+ end
56
+
57
+ it( "is true" ) { expect( change1 ).to eql( change2 ) }
58
+ end
59
+ end
60
+
61
+ describe "#hash" do
62
+ let( :change1 ) { CodeChange.new ".lib/zaphod/spike.rb" }
63
+ let( :change2 ) { CodeChange.new ".lib/zaphod/spike.rb" }
64
+ let( :change3 ) { CodeChange.new ".lib/zaphod/spike.rb", ["+foo"] }
65
+
66
+ it "is the same for two changes that are eql" do
67
+ expect( change1.hash ).to eq( change2.hash )
68
+ end
69
+
70
+ it "differs for two changes that have inequal sources" do
71
+ expect( change2.hash ).to_not eq( change3.hash )
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+ require "zaphod/configuration"
3
+
4
+ describe Zaphod::Configuration do
5
+ subject( :config ) { described_class.new }
6
+
7
+ describe "#on_failure" do
8
+ it "stores a proc, if given" do
9
+ proc = Proc.new { :foo }
10
+ config.on_failure( &proc )
11
+ expect( config.on_failure ).to eq( proc )
12
+ end
13
+
14
+ it "defaults to a SystemExit" do
15
+ expect do
16
+ config.on_failure.call
17
+ end.to raise_error( SystemExit )
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'zaphod/git'
3
+
4
+ describe Zaphod::Git do
5
+ let( :git ) { stub!.diff_index { DIFF }.subject }
6
+ let( :grit ) { stub!.git { git }.subject }
7
+
8
+ subject { described_class.new grit }
9
+
10
+ describe "to get current changes in the git repository" do
11
+ it "calls :diff_index on the Grit git object" do
12
+ mock( git ).diff_index({ p: true }, "HEAD") { DIFF }
13
+
14
+ subject.diff
15
+ end
16
+
17
+ it "returns the patch split into a Hash of file => patch sets" do
18
+ subject.diff.keys.should include(
19
+ "./spec/spec_helper.rb",
20
+ "./spec/zaphod/source_control_spec.rb"
21
+ )
22
+ end
23
+ end
24
+
25
+ DIFF = <<-EOS
26
+ diff --git /dev/null b/spec/spec_helper.rb
27
+ --- /dev/null
28
+ +++ b/spec/spec_helper.rb
29
+ @@ -1 +1,29 @@
30
+ +# This file was generated by the `rspec --init` command. Conventionally, all
31
+ +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
32
+ +# Require this file using `require "spec_helper"` to ensure that it is only
33
+ +# loaded once.
34
+ +#
35
+ +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
36
+ +
37
+ +require 'simplecov'
38
+ +require 'zaphod'
39
+ +
40
+ +SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
41
+ + SimpleCov::Formatter::HTMLFormatter,
42
+ + SimpleCov::Formatter::ZaphodFormatter
43
+ +]
44
+ +
45
+ +SimpleCov.start
46
+ +
47
+ +RSpec.configure do |config|
48
+ + config.treat_symbols_as_metadata_keys_with_true_values = true
49
+ + config.run_all_when_everything_filtered = true
50
+ + config.filter_run :focus
51
+ +
52
+ + # Run specs in random order to surface order dependencies. If you find an
53
+ + # order dependency and want to debug it, you can fix the order by providing
54
+ + # the seed, which is printed after each run.
55
+ + # --seed 1234
56
+ + config.order = 'random'
57
+ +end
58
+ diff --git a/spec/zaphod/source_control_spec.rbf b/spec/zaphod/source_control_spec.rb
59
+ index 73d4e77..8ef378d 100644
60
+ --- a/spec/zaphod/source_control_spec.rb
61
+ +++ b/spec/zaphod/source_control_spec.rb
62
+ @@ -6,6 +6,7 @@ describe Zaphod::Git do
63
+ File.expand_path( File.join __FILE__, "..", ".." )
64
+ )
65
+
66
+ +
67
+ describe "#initialize" do
68
+ it "accepts a repository" do
69
+ described_class.new Grit::Repo.new REPO_PATH
70
+ @@ -13,10 +14,9 @@ describe Zaphod::Git do
71
+ end
72
+
73
+ describe "#changes", integrated: true do
74
+ - let( :first_commit ) { stub diffs: [last_diff] }
75
+ - let( :commits ) { [first_commit] }
76
+ - let( :repository ) { stub commits: commits }
77
+ - let( :last_diff ) { stub diff: DIFF, b_path: "spec/spec_helper.rb" }
78
+ + let( :patch ) { DIFF }
79
+ + let( :git_native ) { stub diff_index: patch }
80
+ + let( :repository ) { stub git: git_native }
81
+
82
+ let( :git ) { described_class.new repository }
83
+ EOS
84
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+ require 'pp'
3
+
4
+ describe Zaphod::SourceControl do
5
+ REPO_PATH = File.dirname(
6
+ File.expand_path( File.join __FILE__, "..", ".." )
7
+ )
8
+
9
+ describe "#initialize" do
10
+ it "accepts a repository" do
11
+ described_class.new Grit::Repo.new REPO_PATH
12
+ end
13
+ end
14
+
15
+ describe "#changes" do
16
+ let( :patch_map ) do
17
+ {
18
+ "./spec/spec_helper.rb" => "+ require 'rspec'\n",
19
+ "./spec/zaphod/source_control_spec.rb" => "+ require 'spec_helper'\n"
20
+ }
21
+ end
22
+ let( :repository ) { stub!.diff { patch_map }.subject }
23
+
24
+ subject { described_class.new repository }
25
+
26
+ it do
27
+ subject.changes.should be_an_instance_of( Zaphod::ChangeSet )
28
+ subject.changes.should_not be_empty
29
+
30
+ subject.changes.each do |change|
31
+ File.exist?( change.path ).should be_true, change.path
32
+ end
33
+ end
34
+
35
+ it "generates a row for each file in the diff" do
36
+ subject.changes.length.should eq 2
37
+ end
38
+
39
+ it "passes the additions to each code set" do
40
+ subject.changes.first.source.length.should eq(
41
+ patch_map["./spec/spec_helper.rb"].lines.select { |l| l =~ /^[+][^+]/ }.to_a.size
42
+ )
43
+ end
44
+
45
+ it "strips the plusses off the lines" do
46
+ subject.changes.first.source.first.should_not start_with( "+" )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+
3
+ describe Zaphod do
4
+ describe ".configure" do
5
+ it "takes a block" do
6
+ Zaphod.configure { :foo }
7
+ end
8
+
9
+ it "yields a configuration object" do
10
+ Zaphod.configure do |config|
11
+ expect( config ).to be_an_instance_of( Zaphod::Configuration )
12
+ end
13
+ end
14
+
15
+ it "yields the same object on repeated calls" do
16
+ config = nil
17
+ Zaphod.configure { |c| config = c }
18
+ Zaphod.configure do |c|
19
+ expect( c ).to be( config )
20
+ end
21
+ end
22
+ end
23
+
24
+ describe ".setup" do
25
+ it "sets the SimpleCov formatter to include the Zaphod formatter" do
26
+ Zaphod.setup
27
+
28
+ expected_formatters = [
29
+ SimpleCov::Formatter::HTMLFormatter,
30
+ SimpleCov::Formatter::ZaphodFormatter
31
+ ]
32
+
33
+ expect( SimpleCov.formatter.new.formatters ).to eq( expected_formatters )
34
+ end
35
+
36
+ it "starts simplecov" do
37
+ mock( SimpleCov ).start
38
+
39
+ Zaphod.setup
40
+ end
41
+
42
+ it "accepts a configuration block" do
43
+ configuration = nil
44
+ Zaphod.setup do |config|
45
+ configuration = config
46
+ end
47
+ expect( configuration ).to be_an_instance_of( Zaphod::Configuration )
48
+ end
49
+ end
50
+ end
data/zaphod.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ $:.push File.expand_path( "../lib", __FILE__ )
2
+ require "zaphod/version"
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "zaphod"
6
+ spec.version = Zaphod::VERSION
7
+
8
+ spec.authors = ["Toby Tripp"]
9
+ spec.email = %q{toby.tripp+gems@gmail.com}
10
+ spec.homepage = %q{http://github.com/tobytripp/zaphod}
11
+
12
+ spec.summary = %q{Catch untested commits and report them.}
13
+ spec.description = %q{}
14
+
15
+ spec.files = `git ls-files`.split("\n")
16
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.extra_rdoc_files = %w[README.org]
20
+ spec.rdoc_options = ["--charset=UTF-8"]
21
+
22
+ spec.add_dependency "grit", "~> 2.5"
23
+ spec.add_dependency "simplecov", "~> 0.8"
24
+
25
+ spec.add_development_dependency "rake", "~> 10.1"
26
+ spec.add_development_dependency "rr", "~> 1.1"
27
+ spec.add_development_dependency "rspec", "~> 2.14"
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "guard", "~> 2.3"
30
+ spec.add_development_dependency "guard-rspec", "~> 4.2"
31
+ spec.add_development_dependency "guard-bundler"
32
+ spec.add_development_dependency "guard-shell"
33
+ spec.add_development_dependency "rb-fsevent"
34
+ spec.add_development_dependency 'rb-readline'
35
+ end