knapsack 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53cb2c59c972a7fe5a858ced2695d4bd6bf76631
4
- data.tar.gz: d8c1d8bca8a3389d2da75e2e046a91b00621f504
3
+ metadata.gz: 8d7cc1eea5e971f88d8ecbf9770abff5729f12d6
4
+ data.tar.gz: 2d5aabc7712378be6352a4e1d8a0118a3dc51008
5
5
  SHA512:
6
- metadata.gz: 29732cd69e2577317468c48d74543c50d2c811696d785aac4361f1863d1e64a796aa41e65c740cc825061a89991a5bff61fec751ffc0b7d61de941a1e43eabe4
7
- data.tar.gz: c5ac456de00a76758094d53f1cdd412e3b836040c208956b5b55e3adc6ffdf9fca09bd673e74157b144a73801a749bf8450aacab848673dff5a126e588760ad1
6
+ metadata.gz: 63bcee2574ba094111d130dd6bfcbdec7028a81e98ec5a9d06fa33e850c3a3a917da9938712da6e842ab4b7964c85a24989c1d91f509c76f3abe3fe512203771
7
+ data.tar.gz: ab4c75f8bae3c992f6fe58077a08006d284cfec5de8ed4442a7508341f40d81a1025d2bb055b1ac2f5237b386ad18bf0c0425e4072cb988a514b42375df82c59
@@ -26,9 +26,12 @@ script:
26
26
  - echo "Run rake task for the second CI node"
27
27
  - CI_NODE_TOTAL=2 CI_NODE_INDEX=1 KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
28
28
 
29
+ - echo "Run specs with custom knapsack logger"
30
+ - CUSTOM_LOGGER=true KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
31
+
29
32
  - echo "Run specs for custom knapsack report path"
30
33
  - cp knapsack_report.json custom_knapsack_report.json
31
- - KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" KNAPSACK_REPORT_PATH="custom_knapsack_report.json" bundle exec rake knapsack:rspec
34
+ - KNAPSACK_REPORT_PATH="custom_knapsack_report.json" KNAPSACK_SPEC_PATTERN="spec_examples/**/*_spec.rb" bundle exec rake knapsack:rspec
32
35
 
33
36
  - echo "Run specs when spec file was removed and still exists in knapsack report json"
34
37
  - rm spec_examples/fast/1_spec.rb
@@ -2,6 +2,10 @@
2
2
 
3
3
  * TODO
4
4
 
5
+ ### 0.2.0
6
+
7
+ * Add knapsack logger. Allow to use custom logger.
8
+
5
9
  ### 0.1.4
6
10
 
7
11
  * Fix wrong time presentation for negative seconds.
data/README.md CHANGED
@@ -12,9 +12,19 @@
12
12
 
13
13
  Parallel specs across CI server nodes based on each spec file's time execution. It generates spec time execution report and uses it for further test runs.
14
14
 
15
+ Short [presentation](http://slides.com/arturt/knapsack) about gem.
16
+
17
+ ### Without Knapsack
18
+
19
+ ![Without Knapsack gem](docs/images/without_knapsack.png)
20
+
21
+ ### With Knapsack
22
+
23
+ ![With Knapsack gem](docs/images/with_knapsack.png)
24
+
15
25
  ## Installation
16
26
 
17
- Add this line to your application's Gemfile in test group:
27
+ Add this line to your application's Gemfile:
18
28
 
19
29
  gem 'knapsack'
20
30
 
@@ -30,8 +40,8 @@ Add at the beginning of your `spec_helper.rb`:
30
40
 
31
41
  # default configuration, you can change it or omit completely
32
42
  Knapsack.tracker.config({
33
- enable_time_offset_warning: true,
34
- time_offset_in_seconds: 30
43
+ enable_time_offset_warning: true,
44
+ time_offset_in_seconds: 30
35
45
  })
36
46
 
37
47
  # default configuration for report, you can change it or omit completely
@@ -39,6 +49,12 @@ Add at the beginning of your `spec_helper.rb`:
39
49
  report_path: 'knapsack_report.json'
40
50
  })
41
51
 
52
+ # you can use your own logger or omit completely
53
+ require 'logger'
54
+ Knapsack.logger = Logger.new(STDOUT)
55
+ Knapsack.logger.level = Logger::INFO
56
+
57
+ # bind adapter, required
42
58
  Knapsack::Adapters::RspecAdapter.bind
43
59
 
44
60
  Add in your `Rakefile` this lines:
@@ -52,6 +68,8 @@ Generate time execution report for your spec files. Run it on your CI machine.
52
68
 
53
69
  Commit generated report `knapsack_report.json` into your repository.
54
70
 
71
+ Report should be updated only after you add a lot of new heavy test or you change existing one which causes a big time execution difference between CI nodes. Anyway you will get time offset warning at the end of rspec results which reminds you when it's good time to regenerate knapsack report.
72
+
55
73
  ## Setup your CI server
56
74
 
57
75
  On your CI server run this command for the first CI node. Update `CI_NODE_INDEX` for the next one.
@@ -78,11 +96,23 @@ If you are using circleci.com you can omit `CI_NODE_TOTAL` and `CI_NODE_INDEX`.
78
96
 
79
97
  Here is example for test configuration in your `circleci.yml` file.
80
98
 
99
+ For the first time run all specs on a single CI node with enabled report generator.
100
+
101
+ test:
102
+ override:
103
+ - KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec
104
+
105
+ After tests pass on your CircleCI machine your should copy knapsack json report which is rendered at the end of rspec results. Save it into your repository as `knapsack_report.json` file and commit.
106
+
107
+ Now you should update test command and enable parallel. Please remember to add additional containers for your project in CircleCI settings.
108
+
81
109
  test:
82
110
  override:
83
111
  - bundle exec rake knapsack:rspec:
84
112
  parallel: true
85
113
 
114
+ Now everything should works. You will get warning at the end of rspec results if time execution will take too much.
115
+
86
116
  ## Tests
87
117
 
88
118
  ### Spec
@@ -1,6 +1,7 @@
1
1
  require 'singleton'
2
2
  require_relative 'knapsack/version'
3
3
  require_relative 'knapsack/config'
4
+ require_relative 'knapsack/logger'
4
5
  require_relative 'knapsack/tracker'
5
6
  require_relative 'knapsack/presenter'
6
7
  require_relative 'knapsack/report'
@@ -14,6 +15,8 @@ require_relative 'knapsack/adapters/rspec_adapter'
14
15
 
15
16
  module Knapsack
16
17
  class << self
18
+ @@logger = nil
19
+
17
20
  def tracker
18
21
  Knapsack::Tracker.instance
19
22
  end
@@ -30,5 +33,16 @@ module Knapsack
30
33
  task_loader = Knapsack::TaskLoader.new
31
34
  task_loader.load_tasks
32
35
  end
36
+
37
+ def logger
38
+ return @@logger if @@logger
39
+ log = Knapsack::Logger.new
40
+ log.level = Knapsack::Logger::INFO
41
+ @@logger = log
42
+ end
43
+
44
+ def logger=(value)
45
+ @@logger = value
46
+ end
33
47
  end
34
48
  end
@@ -9,15 +9,15 @@ module Knapsack
9
9
 
10
10
  def bind
11
11
  if tracker.config[:generate_report]
12
- puts 'Knapsack report generator started!'
12
+ Knapsack.logger.info 'Knapsack report generator started!'
13
13
  bind_time_tracker
14
14
  bind_report_generator
15
15
  elsif tracker.config[:enable_time_offset_warning]
16
- puts 'Knapsack time offset warning enabled!'
16
+ Knapsack.logger.info 'Knapsack time offset warning enabled!'
17
17
  bind_time_tracker
18
18
  bind_time_offset_warning
19
19
  else
20
- puts 'Knapsack is off!'
20
+ Knapsack.logger.warn 'Knapsack adapter is off!'
21
21
  end
22
22
  end
23
23
 
@@ -13,7 +13,7 @@ module Knapsack
13
13
  end
14
14
 
15
15
  config.after(:suite) do
16
- puts Presenter.global_time
16
+ Knapsack.logger.info(Presenter.global_time)
17
17
  end
18
18
  end
19
19
  end
@@ -22,7 +22,7 @@ module Knapsack
22
22
  ::RSpec.configure do |config|
23
23
  config.after(:suite) do
24
24
  Knapsack.report.save
25
- puts Presenter.report_details
25
+ Knapsack.logger.info(Presenter.report_details)
26
26
  end
27
27
  end
28
28
  end
@@ -30,16 +30,14 @@ module Knapsack
30
30
  def bind_time_offset_warning
31
31
  ::RSpec.configure do |config|
32
32
  config.after(:suite) do
33
- puts Presenter.time_offset_warning
33
+ Knapsack.logger.warn(Presenter.time_offset_warning)
34
34
  end
35
35
  end
36
36
  end
37
37
 
38
- protected
39
-
40
38
  def self.spec_path
41
39
  example_group = ::RSpec.current_example.metadata[:example_group]
42
- while !example_group[:parent_example_group].nil?
40
+ until example_group[:parent_example_group].nil?
43
41
  example_group = example_group[:parent_example_group]
44
42
  end
45
43
  example_group[:file_path]
@@ -0,0 +1,24 @@
1
+ module Knapsack
2
+ class Logger
3
+ attr_accessor :level
4
+
5
+ DEBUG = 0
6
+ INFO = 1
7
+ WARN = 2
8
+
9
+ def debug(text=nil)
10
+ return if level != DEBUG
11
+ puts text
12
+ end
13
+
14
+ def info(text=nil)
15
+ return if level > INFO
16
+ puts text
17
+ end
18
+
19
+ def warn(text=nil)
20
+ return if level > WARN
21
+ puts text
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Knapsack
2
- VERSION = '0.1.4'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -1,29 +1,98 @@
1
1
  describe Knapsack::Adapters::RspecAdapter do
2
- before do
3
- expect(::RSpec).to receive(:configure)
4
- end
2
+ it_behaves_like 'adapter'
3
+
4
+ describe 'bind methods' do
5
+ let(:config) { double }
6
+ let(:logger) { instance_double(Knapsack::Logger) }
7
+
8
+ before do
9
+ expect(Knapsack).to receive(:logger).and_return(logger)
10
+ end
11
+
12
+ describe '#bind_time_tracker' do
13
+ let(:tracker) { instance_double(Knapsack::Tracker) }
14
+ let(:spec_path) { 'spec/a_spec.rb' }
15
+ let(:global_time) { 'Global time: 01m 05s' }
16
+
17
+ it do
18
+ expect(described_class).to receive(:spec_path).and_return(spec_path)
19
+
20
+ allow(Knapsack).to receive(:tracker).and_return(tracker)
21
+ expect(tracker).to receive(:spec_path=).with(spec_path)
22
+ expect(tracker).to receive(:start_timer)
23
+ expect(tracker).to receive(:stop_timer)
24
+
25
+ expect(Knapsack::Presenter).to receive(:global_time).and_return(global_time)
26
+
27
+ expect(config).to receive(:before).with(:each).and_yield
28
+ expect(config).to receive(:after).with(:each).and_yield
29
+ expect(config).to receive(:after).with(:suite).and_yield
30
+ expect(::RSpec).to receive(:configure).and_yield(config)
31
+
32
+ expect(logger).to receive(:info).with(global_time)
5
33
 
6
- describe '#bind_time_tracker' do
7
- it do
8
- expect {
9
34
  subject.bind_time_tracker
10
- }.not_to raise_error
35
+ end
11
36
  end
12
- end
13
37
 
14
- describe '#bind_report_generator' do
15
- it do
16
- expect {
38
+ describe '#bind_report_generator' do
39
+ let(:report) { instance_double(Knapsack::Report) }
40
+ let(:report_details) { 'Report details' }
41
+
42
+ it do
43
+ expect(Knapsack).to receive(:report).and_return(report)
44
+ expect(report).to receive(:save)
45
+
46
+ expect(Knapsack::Presenter).to receive(:report_details).and_return(report_details)
47
+
48
+ expect(config).to receive(:after).with(:suite).and_yield
49
+ expect(::RSpec).to receive(:configure).and_yield(config)
50
+
51
+ expect(logger).to receive(:info).with(report_details)
52
+
17
53
  subject.bind_report_generator
18
- }.not_to raise_error
54
+ end
19
55
  end
20
- end
21
56
 
22
- describe '#bind_time_offset_warning' do
23
- it do
24
- expect {
57
+ describe '#bind_time_offset_warning' do
58
+ let(:time_offset_warning) { 'Time offset warning' }
59
+
60
+ it do
61
+ expect(Knapsack::Presenter).to receive(:time_offset_warning).and_return(time_offset_warning)
62
+
63
+ expect(config).to receive(:after).with(:suite).and_yield
64
+ expect(::RSpec).to receive(:configure).and_yield(config)
65
+
66
+ expect(logger).to receive(:warn).with(time_offset_warning)
67
+
25
68
  subject.bind_time_offset_warning
26
- }.not_to raise_error
69
+ end
27
70
  end
28
71
  end
72
+
73
+ describe '.spec_path' do
74
+ let(:current_example) { double }
75
+ let(:metadata) do
76
+ {
77
+ example_group: {
78
+ file_path: '1_shared_example.rb',
79
+ parent_example_group: {
80
+ file_path: '2_shared_example.rb',
81
+ parent_example_group: {
82
+ file_path: 'a_spec.rb'
83
+ }
84
+ }
85
+ }
86
+ }
87
+ end
88
+
89
+ subject { described_class.spec_path }
90
+
91
+ before do
92
+ allow(::RSpec).to receive(:current_example).and_return(current_example)
93
+ allow(current_example).to receive(:metadata).and_return(metadata)
94
+ end
95
+
96
+ it { should eql 'a_spec.rb' }
97
+ end
29
98
  end
@@ -0,0 +1,60 @@
1
+ describe Knapsack::Logger do
2
+ let(:text) { 'Text' }
3
+
4
+ describe '#debug' do
5
+ before { subject.level = level }
6
+
7
+ context 'when level is DEBUG' do
8
+ let(:level) { described_class::DEBUG }
9
+ it { expect { subject.debug(text) }.to output(/#{text}/).to_stdout }
10
+ end
11
+
12
+ context 'when level is INFO' do
13
+ let(:level) { described_class::INFO }
14
+ it { expect { subject.debug(text) }.to output('').to_stdout }
15
+ end
16
+
17
+ context 'when level is WARN' do
18
+ let(:level) { described_class::WARN }
19
+ it { expect { subject.debug(text) }.to output('').to_stdout }
20
+ end
21
+ end
22
+
23
+ describe '#info' do
24
+ before { subject.level = level }
25
+
26
+ context 'when level is DEBUG' do
27
+ let(:level) { described_class::DEBUG }
28
+ it { expect { subject.info(text) }.to output(/#{text}/).to_stdout }
29
+ end
30
+
31
+ context 'when level is INFO' do
32
+ let(:level) { described_class::INFO }
33
+ it { expect { subject.info(text) }.to output(/#{text}/).to_stdout }
34
+ end
35
+
36
+ context 'when level is WARN' do
37
+ let(:level) { described_class::WARN }
38
+ it { expect { subject.info(text) }.to output('').to_stdout }
39
+ end
40
+ end
41
+
42
+ describe '#warn' do
43
+ before { subject.level = level }
44
+
45
+ context 'when level is DEBUG' do
46
+ let(:level) { described_class::DEBUG }
47
+ it { expect { subject.warn(text) }.to output(/#{text}/).to_stdout }
48
+ end
49
+
50
+ context 'when level is INFO' do
51
+ let(:level) { described_class::INFO }
52
+ it { expect { subject.warn(text) }.to output(/#{text}/).to_stdout }
53
+ end
54
+
55
+ context 'when level is WARN' do
56
+ let(:level) { described_class::WARN }
57
+ it { expect { subject.warn(text) }.to output(/#{text}/).to_stdout }
58
+ end
59
+ end
60
+ end
@@ -28,4 +28,32 @@ describe Knapsack do
28
28
  described_class.load_tasks
29
29
  end
30
30
  end
31
+
32
+ describe '.logger' do
33
+ subject { described_class.logger }
34
+
35
+ before { described_class.logger = nil }
36
+ after { described_class.logger = nil }
37
+
38
+ context 'when default logger' do
39
+ let(:logger) { instance_double(Knapsack::Logger) }
40
+
41
+ before do
42
+ expect(Knapsack::Logger).to receive(:new).and_return(logger)
43
+ expect(logger).to receive(:level=).with(Knapsack::Logger::INFO)
44
+ end
45
+
46
+ it { should eql logger }
47
+ end
48
+
49
+ context 'when custom logger' do
50
+ let(:logger) { double('custom logger') }
51
+
52
+ before do
53
+ described_class.logger = logger
54
+ end
55
+
56
+ it { should eql logger }
57
+ end
58
+ end
31
59
  end
@@ -6,6 +6,8 @@ CodeClimate::TestReporter.start
6
6
 
7
7
  require 'knapsack'
8
8
 
9
+ Dir["#{Knapsack.root}/spec/support/**/*.rb"].each { |f| require f }
10
+
9
11
  RSpec.configure do |config|
10
12
  config.order = :random
11
13
  config.mock_with :rspec do |mocks|
@@ -0,0 +1,29 @@
1
+ shared_examples 'adapter' do
2
+ before do
3
+ expect(::RSpec).to receive(:configure)
4
+ end
5
+
6
+ describe '#bind_time_tracker' do
7
+ it do
8
+ expect {
9
+ subject.bind_time_tracker
10
+ }.not_to raise_error
11
+ end
12
+ end
13
+
14
+ describe '#bind_report_generator' do
15
+ it do
16
+ expect {
17
+ subject.bind_report_generator
18
+ }.not_to raise_error
19
+ end
20
+ end
21
+
22
+ describe '#bind_time_offset_warning' do
23
+ it do
24
+ expect {
25
+ subject.bind_time_offset_warning
26
+ }.not_to raise_error
27
+ end
28
+ end
29
+ end
@@ -8,6 +8,13 @@ Knapsack.tracker.config({
8
8
  Knapsack.report.config({
9
9
  report_path: 'knapsack_report.json'
10
10
  })
11
+
12
+ if ENV['CUSTOM_LOGGER']
13
+ require 'logger'
14
+ Knapsack.logger = Logger.new(STDOUT)
15
+ Knapsack.logger.level = Logger::INFO
16
+ end
17
+
11
18
  Knapsack::Adapters::RspecAdapter.bind
12
19
 
13
20
  RSpec.configure do |config|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-13 00:00:00.000000000 Z
11
+ date: 2014-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -104,6 +104,8 @@ files:
104
104
  - README.md
105
105
  - Rakefile
106
106
  - TODO.md
107
+ - docs/images/with_knapsack.png
108
+ - docs/images/without_knapsack.png
107
109
  - knapsack.gemspec
108
110
  - knapsack_report.json
109
111
  - lib/knapsack.rb
@@ -114,6 +116,7 @@ files:
114
116
  - lib/knapsack/distributors/base_distributor.rb
115
117
  - lib/knapsack/distributors/leftover_distributor.rb
116
118
  - lib/knapsack/distributors/report_distributor.rb
119
+ - lib/knapsack/logger.rb
117
120
  - lib/knapsack/presenter.rb
118
121
  - lib/knapsack/report.rb
119
122
  - lib/knapsack/task_loader.rb
@@ -127,12 +130,14 @@ files:
127
130
  - spec/knapsack/distributors/base_distributor_spec.rb
128
131
  - spec/knapsack/distributors/leftover_distributor_spec.rb
129
132
  - spec/knapsack/distributors/report_distributor_spec.rb
133
+ - spec/knapsack/logger_spec.rb
130
134
  - spec/knapsack/presenter_spec.rb
131
135
  - spec/knapsack/report_spec.rb
132
136
  - spec/knapsack/task_loader_spec.rb
133
137
  - spec/knapsack/tracker_spec.rb
134
138
  - spec/knapsack_spec.rb
135
139
  - spec/spec_helper.rb
140
+ - spec/support/shared_examples/adapter.rb
136
141
  - spec_examples/fast/1_spec.rb
137
142
  - spec_examples/fast/2_spec.rb
138
143
  - spec_examples/fast/3_spec.rb
@@ -179,9 +184,11 @@ test_files:
179
184
  - spec/knapsack/distributors/base_distributor_spec.rb
180
185
  - spec/knapsack/distributors/leftover_distributor_spec.rb
181
186
  - spec/knapsack/distributors/report_distributor_spec.rb
187
+ - spec/knapsack/logger_spec.rb
182
188
  - spec/knapsack/presenter_spec.rb
183
189
  - spec/knapsack/report_spec.rb
184
190
  - spec/knapsack/task_loader_spec.rb
185
191
  - spec/knapsack/tracker_spec.rb
186
192
  - spec/knapsack_spec.rb
187
193
  - spec/spec_helper.rb
194
+ - spec/support/shared_examples/adapter.rb