Skip to content

Commit

Permalink
Merge pull request #60 from KnapsackPro/queue-mode-minitest
Browse files Browse the repository at this point in the history
Add Queue Mode for Minitest
  • Loading branch information
ArturT authored May 11, 2018
2 parents 2ad27ea + 1d883a0 commit 9ce3940
Show file tree
Hide file tree
Showing 11 changed files with 332 additions and 4 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

* TODO

### 0.54.0

* Add Queue Mode for Minitest

https://github.com/KnapsackPro/knapsack_pro-ruby/pull/60

https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v0.53.0...v0.54.0

### 0.53.0

* Add support for Heroku CI environment variables.
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,12 @@ Please use a separate API token for queue mode from one used already for regular

Use this command to run queue mode:

# RSpec
bundle exec rake knapsack_pro:queue:rspec

# Minitest
bundle exec rake knapsack_pro:queue:minitest

If the above command fails then you may need to explicitly pass an argument to require the `rails_helper` file or `spec_helper` in case you are not doing this in some of your test files:

bundle exec rake "knapsack_pro:queue:rspec[--require rails_helper]"
Expand Down Expand Up @@ -597,6 +601,7 @@ You can install knapsack_pro globally and use binary. For instance:
$ knapsack_pro queue:rspec "--tag custom_tag_name --profile"
$ knapsack_pro cucumber "--name feature"
$ knapsack_pro minitest "--verbose --pride"
$ knapsack_pro queue:minitest "--verbose"
$ knapsack_pro test_unit "--verbose"
$ knapsack_pro spinach "--arg_name value"
Expand Down Expand Up @@ -714,6 +719,13 @@ Here is another example for CircleCI 2.0 platform.
# export word is important here!
export RAILS_ENV=test
bundle exec rake "knapsack_pro:queue:rspec[--format documentation]"
- run:
name: Minitest via knapsack_pro Queue Mode
command: |
# export word is important here!
export RAILS_ENV=test
bundle exec rake "knapsack_pro:queue:minitest[--verbose]"
```
Please remember to add additional containers for your project in CircleCI settings.
Expand Down
1 change: 1 addition & 0 deletions bin/knapsack_pro
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ MAP = {
'queue:rspec' => KnapsackPro::Runners::Queue::RSpecRunner,
'cucumber' => KnapsackPro::Runners::CucumberRunner,
'minitest' => KnapsackPro::Runners::MinitestRunner,
'queue:minitest' => KnapsackPro::Runners::Queue::MinitestRunner,
'test_unit' => KnapsackPro::Runners::TestUnitRunner,
'spinach' => KnapsackPro::Runners::SpinachRunner,
}
Expand Down
1 change: 1 addition & 0 deletions lib/knapsack_pro.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
require_relative 'knapsack_pro/runners/spinach_runner'
require_relative 'knapsack_pro/runners/queue/base_runner'
require_relative 'knapsack_pro/runners/queue/rspec_runner'
require_relative 'knapsack_pro/runners/queue/minitest_runner'
require_relative 'knapsack_pro/crypto/encryptor'
require_relative 'knapsack_pro/crypto/branch_encryptor'
require_relative 'knapsack_pro/crypto/decryptor'
Expand Down
12 changes: 8 additions & 4 deletions lib/knapsack_pro/adapters/base_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ def bind

if KnapsackPro::Config::Env.queue_recording_enabled?
KnapsackPro.logger.debug('Test suite time execution queue recording enabled.')
bind_tracker_reset
bind_before_queue_hook
bind_time_tracker
bind_save_queue_report
bind_queue_mode
end
end

Expand All @@ -45,6 +42,13 @@ def bind_tracker_reset
def bind_before_queue_hook
raise NotImplementedError
end

def bind_queue_mode
bind_tracker_reset
bind_before_queue_hook
bind_time_tracker
bind_save_queue_report
end
end
end
end
28 changes: 28 additions & 0 deletions lib/knapsack_pro/adapters/minitest_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,34 @@ def set_test_helper_path(file_path)
@@parent_of_test_dir = File.expand_path('../', test_dir_path)
end

module BindQueueModeMinitestPlugin
def before_setup
super

unless ENV['KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED']
KnapsackPro::Hooks::Queue.call_before_queue
ENV['KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED'] = 'true'
end

KnapsackPro.tracker.current_test_path = KnapsackPro::Adapters::MinitestAdapter.test_path(self)
KnapsackPro.tracker.start_timer
end

def after_teardown
KnapsackPro.tracker.stop_timer

super
end
end

def bind_queue_mode
::Minitest::Test.send(:include, BindQueueModeMinitestPlugin)

add_post_run_callback do
KnapsackPro.logger.debug(KnapsackPro::Presenter.global_time)
end
end

private

def add_post_run_callback(&block)
Expand Down
70 changes: 70 additions & 0 deletions lib/knapsack_pro/runners/queue/minitest_runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module KnapsackPro
module Runners
module Queue
class MinitestRunner < BaseRunner
def self.run(args)
require 'minitest'

ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_minitest
ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true'
ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id

runner = new(KnapsackPro::Adapters::MinitestAdapter)

# Add test_dir to load path to make work:
# require 'test_helper'
# in test files.
$LOAD_PATH.unshift(runner.test_dir)

cli_args = (args || '').split
run_tests(runner, true, cli_args, 0, [])
end

def self.run_tests(runner, can_initialize_queue, args, exitstatus, all_test_file_paths)
test_file_paths = runner.test_file_paths(
can_initialize_queue: can_initialize_queue,
executed_test_files: all_test_file_paths
)

if test_file_paths.empty?
KnapsackPro::Hooks::Queue.call_after_queue

KnapsackPro::Report.save_node_queue_to_api
exit(exitstatus)
else
subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id
ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id

KnapsackPro.tracker.reset!

all_test_file_paths += test_file_paths

result = minitest_run(runner, test_file_paths, args)
exitstatus = 1 unless result

KnapsackPro::Hooks::Queue.call_after_subset_queue

KnapsackPro::Report.save_subset_queue_to_file

run_tests(runner, false, args, exitstatus, all_test_file_paths)
end
end

private

def self.minitest_run(runner, test_file_paths, args)
test_file_paths.each do |test_file_path|
require "./#{test_file_path}"
end

# duplicate args because Minitest modifies args
result = Minitest.run(args.dup)

Minitest::Runnable.reset

result
end
end
end
end
end
9 changes: 9 additions & 0 deletions lib/tasks/queue/minitest.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'knapsack_pro'

namespace :knapsack_pro do
namespace :queue do
task :minitest, [:minitest_args] do |_, args|
KnapsackPro::Runners::Queue::MinitestRunner.run(args[:minitest_args])
end
end
end
62 changes: 62 additions & 0 deletions spec/knapsack_pro/adapters/minitest_adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ module FakeMinitest
class Test < ::Minitest::Test
include KnapsackPro::Adapters::MinitestAdapter::BindTimeTrackerMinitestPlugin
end

class TestQueueMode < ::Minitest::Test
include KnapsackPro::Adapters::MinitestAdapter::BindQueueModeMinitestPlugin
end
end

describe KnapsackPro::Adapters::MinitestAdapter do
Expand Down Expand Up @@ -83,6 +87,47 @@ def location
end
end

describe 'BindQueueModeMinitestPlugin' do
let(:tracker) { instance_double(KnapsackPro::Tracker) }

subject { ::FakeMinitest::TestQueueMode.new }

before do
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
end

describe '#before_setup' do
let(:file) { 'test/models/user_test.rb' }

before do
stub_const('ENV', {
'KNAPSACK_PRO_BEFORE_QUEUE_HOOK_CALLED' => nil,
})
end

it do
expect(KnapsackPro::Hooks::Queue).to receive(:call_before_queue).once

expect(described_class).to receive(:test_path).with(subject).twice.and_return(file)
expect(tracker).to receive(:current_test_path=).with(file).twice
expect(tracker).to receive(:start_timer).twice

subject.before_setup

# second call should not trigger KnapsackPro::Hooks::Queue.call_before_queue
subject.before_setup
end
end

describe '#after_teardown' do
it do
expect(tracker).to receive(:stop_timer)

subject.after_teardown
end
end
end

describe 'bind methods' do
describe '#bind_time_tracker' do
let(:logger) { instance_double(Logger) }
Expand Down Expand Up @@ -110,6 +155,23 @@ def location
subject.bind_save_report
end
end

describe '#bind_queue_mode' do
let(:logger) { instance_double(Logger) }
let(:global_time) { 'Global time: 01m 05s' }

it do
expect(::Minitest::Test).to receive(:send).with(:include, KnapsackPro::Adapters::MinitestAdapter::BindQueueModeMinitestPlugin)

expect(::Minitest).to receive(:after_run).and_yield

expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
expect(KnapsackPro).to receive(:logger).and_return(logger)
expect(logger).to receive(:debug).with(global_time)

subject.bind_queue_mode
end
end
end

describe '#set_test_helper_path' do
Expand Down
Loading

0 comments on commit 9ce3940

Please sign in to comment.