hexx-rspec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +67 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +3 -0
  8. data/Gemfile +3 -0
  9. data/Guardfile +29 -0
  10. data/LICENSE +21 -0
  11. data/README.md +85 -0
  12. data/Rakefile +18 -0
  13. data/bin/hexx-rspec +14 -0
  14. data/config/initializer.rb +8 -0
  15. data/config/initializers/focus.rb +5 -0
  16. data/config/initializers/garbage_collection.rb +11 -0
  17. data/config/initializers/i18n.rb +3 -0
  18. data/config/initializers/random_order.rb +4 -0
  19. data/config/initializers/rspec.rb +11 -0
  20. data/hexx-rspec.gemspec +29 -0
  21. data/lib/hexx/rspec/install/Rakefile +17 -0
  22. data/lib/hexx/rspec/install/_rspec +2 -0
  23. data/lib/hexx/rspec/install/simplecov.yml +8 -0
  24. data/lib/hexx/rspec/install.rb +43 -0
  25. data/lib/hexx/rspec/metrics/base.rb +87 -0
  26. data/lib/hexx/rspec/metrics/simplecov.rb +123 -0
  27. data/lib/hexx/rspec/metrics.rb +23 -0
  28. data/lib/hexx/rspec/system.rb +68 -0
  29. data/lib/hexx/rspec/version.rb +13 -0
  30. data/lib/hexx/rspec.rb +65 -0
  31. data/lib/hexx-rspec.rb +16 -0
  32. data/lib/tasks/test/coverage.rake +29 -0
  33. data/lib/tasks/test.rake +6 -0
  34. data/spec/spec_helper.rb +10 -0
  35. data/spec/support/config/sandbox.rb +16 -0
  36. data/spec/support/config/tasks.rb +32 -0
  37. data/spec/support/sandbox/helpers.rb +62 -0
  38. data/spec/support/sandbox/matchers.rb +21 -0
  39. data/spec/tests/bin/install_spec.rb +15 -0
  40. data/spec/tests/lib/install_spec.rb +21 -0
  41. data/spec/tests/lib/metrics/simplecov_spec.rb +108 -0
  42. data/spec/tests/lib/system_spec.rb +99 -0
  43. data/spec/tests/rspec_spec.rb +57 -0
  44. data/spec/tests/tasks/test/coverage/display_spec.rb +49 -0
  45. data/spec/tests/tasks/test/coverage/run_spec.rb +25 -0
  46. data/spec/tests/tasks/test/coverage_spec.rb +26 -0
  47. data/spec/tests/tasks/test_spec.rb +21 -0
  48. metadata +194 -0
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module Hexx
4
+
5
+ module RSpec
6
+
7
+ # The utility sends multiline string to system
8
+ #
9
+ # Allows stubbing system calls in specifications.
10
+ #
11
+ # @example
12
+ # System.call %(
13
+ # inch --pedantic
14
+ # rubocop
15
+ # )
16
+ #
17
+ # @api private
18
+ class System < String
19
+
20
+ # Initializes multiline text to be sent to system
21
+ #
22
+ # Removes repetitive spaces from itself
23
+ #
24
+ # @param [#to_s] _
25
+ # Multiline text to be sent to system
26
+ #
27
+ # @return [undefined]
28
+ def initialize(_)
29
+ super
30
+ strip!
31
+ gsub!(/ {2,}/, " ")
32
+ end
33
+
34
+ # Returns non-empty lines without trailing spaces
35
+ #
36
+ # @return [Array<String>]
37
+ def lines
38
+ Array(super) # Array() is needed to support rubies 1.9.3
39
+ .map(&:strip)
40
+ .reject(&:empty?)
41
+ end
42
+
43
+ # Sends itself to system line by line
44
+ #
45
+ # @return [self]
46
+ def call
47
+ lines.each(&method(:system))
48
+
49
+ self
50
+ end
51
+
52
+ # Sends multiline string to system
53
+ #
54
+ # @example (see Hexx::RSpec::System)
55
+ #
56
+ # @param (see #initialize)
57
+ #
58
+ # @return [Hexx::RSpec::System]
59
+ # utility object (allows chaining)
60
+ def self.call(text)
61
+ new(text).call
62
+ end
63
+
64
+ end # class System
65
+
66
+ end # module RSpec
67
+
68
+ end # module Hexx
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module Hexx
4
+
5
+ module RSpec
6
+
7
+ # The semantic version of the module.
8
+ # @see http://semver.org/ Semantic versioning 2.0
9
+ VERSION = "0.0.1".freeze
10
+
11
+ end # module RSpec
12
+
13
+ end # module Hexx
data/lib/hexx/rspec.rb ADDED
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ module Hexx
4
+
5
+ # Namespace for the module.
6
+ #
7
+ # @api public
8
+ module RSpec
9
+
10
+ require_relative "rspec/system"
11
+ require_relative "rspec/metrics"
12
+ require_relative "rspec/install"
13
+
14
+ class << self
15
+
16
+ # Loads coverage metric in a given scope
17
+ #
18
+ # Checks if a corresponding environment is set
19
+ #
20
+ # @example
21
+ # # spec/spec_helper.rb
22
+ # Hexx::RSpec.load_metrics_for(self)
23
+ #
24
+ # @param [Object] scope
25
+ #
26
+ # @return [self]
27
+ def load_metrics_for(scope)
28
+ return unless ENV["USE_SIMPLECOV"]
29
+ scope.instance_eval { Hexx::RSpec::Metrics::SimpleCov.run }
30
+ end
31
+
32
+ # Loads all the necessary rake tasks
33
+ #
34
+ # @example
35
+ # Hexx::RSpec.install_tasks
36
+ #
37
+ # @return [self]
38
+ def install_tasks
39
+ load_gem_tasks
40
+ load_rspec_tasks
41
+ load_custom_tasks
42
+ end
43
+
44
+ private
45
+
46
+ def load_gem_tasks
47
+ require "bundler/gem_tasks"
48
+ ::Bundler::GemHelper.install_tasks
49
+ end
50
+
51
+ def load_rspec_tasks
52
+ require "rspec/core/rake_task"
53
+ ::RSpec::Core::RakeTask.new(:spec)
54
+ end
55
+
56
+ def load_custom_tasks
57
+ tasks = ::File.expand_path "../../tasks/**/*.rake", __FILE__
58
+ ::Dir[tasks].each { |task| load task }
59
+ end
60
+
61
+ end # singleton class RSpec
62
+
63
+ end # module RSpec
64
+
65
+ end # module Hexx
data/lib/hexx-rspec.rb ADDED
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require "i18n"
4
+ require "rake"
5
+ require "rspec"
6
+ require "thor"
7
+ require "yaml"
8
+
9
+ # Shared namespace for the Hexx-based gems
10
+ module Hexx
11
+
12
+ require_relative "hexx/rspec/version"
13
+ require_relative "hexx/rspec"
14
+ require_relative "../config/initializer.rb"
15
+
16
+ end # module Hexx
@@ -0,0 +1,29 @@
1
+ namespace :test do
2
+
3
+ namespace :coverage do
4
+
5
+ metric = Hexx::RSpec::Metrics::SimpleCov
6
+ caller = Hexx::RSpec::System
7
+ output = -> { ENV.fetch("SIMPLECOV_OUTPUT") { "coveralls/index.html" } }
8
+
9
+ # Loads settings for simplecov from the 'config/metrics/simplecov.yml'
10
+ task :configure do
11
+ metric.load
12
+ end
13
+
14
+ desc "Runs tests under the coveralls"
15
+ task run: :configure do
16
+ caller.call "rake test"
17
+ puts "see results in #{ output.call }"
18
+ end
19
+
20
+ desc "Displays results of the coveralls last run"
21
+ task display: :configure do
22
+ caller.call "launchy #{ output.call }"
23
+ end
24
+ end
25
+
26
+ desc "Runs tests under the coveralls and displays the results"
27
+ task coverage: %w(coverage:run coverage:display)
28
+
29
+ end # namespace :test
@@ -0,0 +1,6 @@
1
+ caller = Hexx::RSpec::System
2
+
3
+ desc "Runs a test rspec in a bundle environment, without monitoring coverage."
4
+ task :test do
5
+ caller.call "bundle exec rspec spec"
6
+ end
@@ -0,0 +1,10 @@
1
+ # Loads the RSpec support files.
2
+ require "rspec"
3
+ Dir[File.expand_path "spec/support/config/*.rb"].each { |file| require file }
4
+
5
+ # encoding: utf-8
6
+ require "coveralls"
7
+ Coveralls.wear!
8
+
9
+ # Loads the code of the module with the RSpec test rspec.
10
+ require "hexx-rspec"
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.configure do |config|
4
+
5
+ # Prepares a sandbox before corresponding spec.
6
+ config.before :each, :sandbox do
7
+ require_relative "../sandbox/helpers"
8
+ require_relative "../sandbox/matchers"
9
+ prepare_sandbox
10
+ end
11
+
12
+ # Clears a sandbox after corresponding spec.
13
+ config.after :each, :sandbox do
14
+ clear_sandbox
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.configure do |config|
4
+
5
+ # Array of commands that was sent to system
6
+ #
7
+ # @return [Array<String>]
8
+ def commands
9
+ @commands ||= []
10
+ end
11
+
12
+ # Checks whether a task with given name has been invoked
13
+ #
14
+ # @param [String] name
15
+ #
16
+ # @return [Boolean]
17
+ def task_invoked?(name)
18
+ Rake::Task[name].instance_eval { @already_invoked }
19
+ end
20
+
21
+ config.before :example, :tasks do
22
+
23
+ # Resets Rake application and reinstalls all tasks to be available
24
+ Rake.application = nil
25
+ Hexx::RSpec.install_tasks
26
+
27
+ # Captures commands that System utility sends to system
28
+ # and stores them in {#commands} array.
29
+ allow_any_instance_of(Hexx::RSpec::System)
30
+ .to receive(:system) { |command| commands << command }
31
+ end
32
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ require "yaml"
3
+
4
+ # Yields block and captures stdout stream.
5
+ #
6
+ # @example
7
+ # capture_stdout { do_something }
8
+ #
9
+ # @return [String] The captured stream.
10
+ def capture_stdout
11
+ begin
12
+ $stdout = StringIO.new
13
+ yield
14
+ result = $stdout.string
15
+ ensure
16
+ $stdout = STDOUT
17
+ end
18
+ result.to_s
19
+ end
20
+
21
+ # Returns the path to the temporary `spec/sandbox`.
22
+ # @return [String] The absolute path.
23
+ def sandbox
24
+ @sandbox ||= File.expand_path "../../../sandbox", __FILE__
25
+ end
26
+
27
+ # Clears the temporary `spec/sandbox`.
28
+ def clear_sandbox
29
+ FileUtils.rm_rf sandbox
30
+ end
31
+
32
+ # Re-creates the temporary `spec/sandbox`.
33
+ def prepare_sandbox
34
+ clear_sandbox
35
+ FileUtils.mkdir_p sandbox
36
+ end
37
+
38
+ # Runs code from the temporary `spec/sandbox`.
39
+ def try_in_sandbox
40
+ FileUtils.cd(sandbox) { capture_stdout { yield } }
41
+ end
42
+
43
+ # Reads file in sandbox and returns file content.
44
+ # Returns a blank string when the file is absent.
45
+ # @return [String] The content.
46
+ def read_in_sandbox(filename)
47
+ file = Dir[File.join(sandbox, filename)].first
48
+ file ? File.read(file) : ""
49
+ end
50
+
51
+ # Creates settings file in a sandbox
52
+ #
53
+ # @param [Hash] settings ({})
54
+ # The list of settings to be stored in 'sandbox/.metrics.yml'
55
+ #
56
+ # @return [undefined]
57
+ def prepare_settings(settings, file = ".metrics.yml")
58
+ try_in_sandbox do
59
+ ::FileUtils.mkdir_p ::File.dirname(file)
60
+ ::File.write file, settings.to_yaml
61
+ end
62
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ # Checks if a file with given name is present in sandbox.
4
+ #
5
+ # @example
6
+ # expect("some_file.rb").to be_present_in_sandbox
7
+ RSpec::Matchers.define :be_present_in_sandbox do
8
+ match do |filename|
9
+ files = Dir[File.join(sandbox, filename)]
10
+ expect(files).to be_any
11
+ end
12
+ end
13
+
14
+ # Checks if a file with given name is absent in sandbox.
15
+ #
16
+ # @example
17
+ # expect("some_file.rb").to be_absent_in_sandbox
18
+ RSpec::Matchers.define_negated_matcher(
19
+ :be_absent_in_sandbox,
20
+ :be_present_in_sandbox
21
+ )
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ describe "hexx-rspec install", :sandbox do
4
+
5
+ before { try_in_sandbox { `hexx-rspec install` } }
6
+
7
+ it "creates necessary files" do
8
+ %w(
9
+ .rspec
10
+ Rakefile
11
+ config/metrics/simplecov.yml
12
+ ).each { |file| expect(file).to be_present_in_sandbox }
13
+ end
14
+
15
+ end # describe hexx-rspec install
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ describe Hexx::RSpec::Install, :sandbox do
4
+
5
+ describe ".start" do
6
+
7
+ before { try_in_sandbox { described_class.start } }
8
+
9
+ it "creates necessary files" do
10
+ %w(
11
+ .rspec
12
+ Rakefile
13
+ config/metrics/simplecov.yml
14
+ ).each { |file| expect(file).to be_present_in_sandbox }
15
+ end
16
+
17
+ it "adds Hexx::RSpec tasks loader to Rakefile" do
18
+ expect(read_in_sandbox "Rakefile").to include "Hexx::RSpec.install_tasks"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,108 @@
1
+ # encoding: utf-8
2
+ require "simplecov"
3
+
4
+ describe Hexx::RSpec::Metrics::SimpleCov, :sandbox do
5
+
6
+ shared_context "without simplecov.yml" do
7
+
8
+ let(:options) do
9
+ {
10
+ "output" => "tmp/coverage",
11
+ "filters" => ["spec/", "config/"],
12
+ "groups" => {
13
+ "Libraries" => "lib/",
14
+ "Application" => "app/"
15
+ }
16
+ }
17
+ end
18
+
19
+ end # shared_context
20
+
21
+ shared_context "with simplecov.yml" do
22
+
23
+ let(:options) do
24
+ {
25
+ "output" => "custom",
26
+ "filters" => ["custom/"],
27
+ "groups" => { "Custom" => "custom/" }
28
+ }
29
+ end
30
+
31
+ before { prepare_settings options, "config/metrics/simplecov.yml" }
32
+
33
+ end # shared_context
34
+
35
+ shared_examples "environmets setter" do
36
+
37
+ before do
38
+ ENV["USE_SIMPLECOV"] = nil
39
+ ENV["SIMPLECOV_OUTPUT"] = nil
40
+ end
41
+
42
+ it "[sets USE_SIMPLECOV]" do
43
+ expect { subject }
44
+ .to change { ENV["USE_SIMPLECOV"] }
45
+ .to "true"
46
+ end
47
+
48
+ it "[sets SIMPLECOV_OUTPUT]" do
49
+ expect { subject }
50
+ .to change { ENV["SIMPLECOV_OUTPUT"] }
51
+ .to "#{ options['output'] }/index.html"
52
+ end
53
+
54
+ end # shared_examples
55
+
56
+ shared_examples "metric loader" do
57
+
58
+ after { subject }
59
+
60
+ it "starts the metric" do
61
+ expect(::SimpleCov).to receive(:start)
62
+ end
63
+
64
+ end # shared_examples
65
+
66
+ describe ".load" do
67
+
68
+ subject { try_in_sandbox { described_class.load } }
69
+
70
+ context "without simplecov.yml" do
71
+
72
+ include_context "without simplecov.yml"
73
+
74
+ it_behaves_like "environmets setter"
75
+ end
76
+
77
+ context "with simplecov.yml" do
78
+
79
+ include_context "with simplecov.yml"
80
+
81
+ it_behaves_like "environmets setter"
82
+ end
83
+
84
+ end # describe .load
85
+
86
+ describe ".run" do
87
+
88
+ subject { try_in_sandbox { described_class.run } }
89
+
90
+ context "without simplecov.yml" do
91
+
92
+ include_context "without simplecov.yml"
93
+
94
+ it_behaves_like "environmets setter"
95
+ it_behaves_like "metric loader"
96
+ end
97
+
98
+ context "with simplecov.yml" do
99
+
100
+ include_context "without simplecov.yml"
101
+
102
+ it_behaves_like "environmets setter"
103
+ it_behaves_like "metric loader"
104
+ end
105
+
106
+ end # describe .run
107
+
108
+ end # describe Hexx::RSpec::Metrics::SimpleCov
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+
3
+ describe Hexx::RSpec::System do
4
+
5
+ it "is a string" do
6
+ subject = described_class.new ""
7
+ expect(subject).to be_kind_of String
8
+ end
9
+
10
+ describe ".new" do
11
+
12
+ it "removes repetitive spaces from source" do
13
+ subject = described_class.new "foo bar \n baz"
14
+
15
+ expect(subject).to eq "foo bar \n baz"
16
+ end
17
+
18
+ it "strips the source" do
19
+ subject = described_class.new " foo bar \n baz "
20
+
21
+ expect(subject).to eq "foo bar \n baz"
22
+ end
23
+
24
+ end # describe .new
25
+
26
+ describe "#lines" do
27
+
28
+ it "strips lines" do
29
+ subject = described_class.new " foo bar \n baz "
30
+
31
+ expect(subject.lines).to eq ["foo bar", "baz"]
32
+ end
33
+
34
+ it "ignores empty lines" do
35
+ subject = described_class.new " \nfoo bar\n \nbaz\n "
36
+
37
+ expect(subject.lines).to eq ["foo bar", "baz"]
38
+ end
39
+
40
+ it "returns an array of utilities" do
41
+ subject = described_class.new "foo bar\nbaz"
42
+
43
+ subject.lines.each { |line| expect(line).to be_kind_of described_class }
44
+ end
45
+
46
+ end # describe #lines
47
+
48
+ describe "#call" do
49
+
50
+ before { allow_any_instance_of(described_class).to receive :system }
51
+
52
+ it "returns itself (allows chaining)" do
53
+ subject = described_class.new "foo"
54
+
55
+ expect(subject.call).to eq subject
56
+ end
57
+
58
+ context "single line" do
59
+
60
+ subject { described_class.new "foo bar" }
61
+ after { subject.call }
62
+
63
+ it "sends itself to system" do
64
+ expect(subject).to receive(:system).with(subject)
65
+ end
66
+
67
+ end # context
68
+
69
+ context "multiline string" do
70
+
71
+ subject { described_class.new "foo bar\nbaz" }
72
+ after { subject.call }
73
+
74
+ it "sends each line to system" do
75
+ subject.lines.each do |line|
76
+ expect(subject).to receive(:system).with(line).ordered
77
+ end
78
+ end
79
+
80
+ end # context
81
+
82
+ end # describe #call
83
+
84
+ describe ".call" do
85
+
86
+ let!(:value) { "foo bar\nbaz" }
87
+ let!(:utility) { described_class.new value }
88
+
89
+ before { allow(described_class).to receive(:new) { utility } }
90
+
91
+ it "constucts the utility object and calls it" do
92
+ expect(described_class).to receive(:new).with(value)
93
+ expect(utility).to receive :call
94
+ described_class.call value
95
+ end
96
+
97
+ end # describe .call
98
+
99
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+
3
+ describe Hexx::RSpec do
4
+
5
+ let(:coverage_settings) { described_class::Metrics::SimpleCov }
6
+ let(:rake_tasks) { Rake::Task.tasks.map(&:name) }
7
+
8
+ describe ".install_tasks" do
9
+
10
+ before { described_class.install_tasks }
11
+
12
+ it "installs Gem tasks" do
13
+ expect(rake_tasks).to include("build", "install", "release")
14
+ end
15
+
16
+ it "installs RSpec tasks" do
17
+ expect(rake_tasks).to include("spec")
18
+ end
19
+
20
+ it "installs described_class tasks" do
21
+ expect(rake_tasks).to include(*%w(
22
+ test:coverage
23
+ test:coverage:display
24
+ test:coverage:run
25
+ test
26
+ ))
27
+ end
28
+
29
+ end # display .insall_tasks
30
+
31
+ describe ".load_metrics_for" do
32
+
33
+ subject { described_class.load_metrics_for(double) }
34
+
35
+ context "when ENV[USE_SIMPLECOV] is set" do
36
+
37
+ before { ENV["USE_SIMPLECOV"] = "true" }
38
+
39
+ it "initializes and runs a coverage settings" do
40
+ expect(coverage_settings).to receive(:run)
41
+ subject
42
+ end
43
+ end
44
+
45
+ context "when ENV[USE_SIMPLECOV] isn't set" do
46
+
47
+ before { ENV["USE_SIMPLECOV"] = nil }
48
+
49
+ it "doesn't run settings" do
50
+ expect(coverage_settings).not_to receive(:run)
51
+ subject
52
+ end
53
+ end
54
+
55
+ end # display .load_metrics_for
56
+
57
+ end # display Hexx::RSpec
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ describe "Rake::Task['test:coverage:display']", :tasks do
4
+
5
+ # The {#commands} variable is defined in the spec/support/config/tasks.rb
6
+ # It collects the list of commands, that has been sent to system by
7
+ # any instance of Hexx::RSpec::System utility.
8
+
9
+ let(:metric) { Hexx::RSpec::Metrics::SimpleCov }
10
+ let(:task) { Rake::Task["test:coverage:display"] }
11
+
12
+ describe ".invoke", :sandbox do
13
+
14
+ subject { try_in_sandbox { task.invoke } }
15
+
16
+ context "when '.metrics.yml' is absent" do
17
+
18
+ it "loads the metric" do
19
+ expect(metric).to receive(:load)
20
+ subject
21
+ end
22
+
23
+ it "displays the default output" do
24
+ expect { subject }.to change { commands }.to [
25
+ "launchy tmp/coverage/index.html"
26
+ ]
27
+ end
28
+ end
29
+
30
+ context "when '.metrics.yml' is present" do
31
+
32
+ let(:output) { "tmp/coverage" }
33
+ before do
34
+ prepare_settings "simplecov" => { "output" => output }
35
+ end
36
+
37
+ it "loads the metric" do
38
+ expect(metric).to receive(:load)
39
+ subject
40
+ end
41
+
42
+ it "uses the custom output folder" do
43
+ expect { subject }.to change { commands }.to [
44
+ "launchy #{ output }/index.html"
45
+ ]
46
+ end
47
+ end
48
+ end
49
+ end