hexx-rspec 0.0.1

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.
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