zaphod 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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