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.
- checksums.yaml +7 -0
- data/.bundle/config +1 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +86 -0
- data/Guardfile +20 -0
- data/LICENSE +198 -0
- data/README.org +59 -0
- data/Rakefile +9 -0
- data/lib/simplecov/formatter/zaphod_formatter.rb +40 -0
- data/lib/zaphod/change_set.rb +14 -0
- data/lib/zaphod/code_change.rb +23 -0
- data/lib/zaphod/configuration.rb +15 -0
- data/lib/zaphod/git.rb +38 -0
- data/lib/zaphod/source_control.rb +31 -0
- data/lib/zaphod/spike.rb +7 -0
- data/lib/zaphod/version.rb +3 -0
- data/lib/zaphod.rb +26 -0
- data/spec/do_spec.rb +8 -0
- data/spec/simplecov/formatter/zaphod_formatter_spec.rb +73 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/zaphod/change_set_spec.rb +59 -0
- data/spec/zaphod/code_change_spec.rb +76 -0
- data/spec/zaphod/configuration_spec.rb +20 -0
- data/spec/zaphod/git_spec.rb +84 -0
- data/spec/zaphod/source_control_spec.rb +49 -0
- data/spec/zaphod_spec.rb +50 -0
- data/zaphod.gemspec +35 -0
- metadata +241 -0
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
data/spec/zaphod_spec.rb
ADDED
@@ -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
|