shoulda 3.5.0 → 3.6.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 +6 -14
- data/.gitignore +7 -7
- data/.hound.yml +3 -0
- data/.hound/ruby.yml +1042 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +11 -7
- data/Appraisals +13 -10
- data/CONTRIBUTING.md +6 -1
- data/Gemfile +8 -1
- data/README.md +58 -73
- data/Rakefile +21 -12
- data/gemfiles/4.2.gemfile +17 -0
- data/gemfiles/4.2.gemfile.lock +174 -0
- data/gemfiles/5.0.gemfile +17 -0
- data/gemfiles/5.0.gemfile.lock +179 -0
- data/lib/shoulda/version.rb +1 -1
- data/shoulda.gemspec +23 -23
- data/test/acceptance/rails_integration_test.rb +76 -0
- data/test/acceptance_test_helper.rb +17 -0
- data/test/report_warnings.rb +7 -0
- data/test/support/acceptance/add_shoulda_to_project.rb +78 -0
- data/test/support/acceptance/helpers.rb +19 -0
- data/test/support/acceptance/helpers/active_model_helpers.rb +11 -0
- data/test/support/acceptance/helpers/array_helpers.rb +13 -0
- data/test/support/acceptance/helpers/base_helpers.rb +14 -0
- data/test/support/acceptance/helpers/command_helpers.rb +54 -0
- data/test/support/acceptance/helpers/file_helpers.rb +19 -0
- data/test/support/acceptance/helpers/gem_helpers.rb +31 -0
- data/test/support/acceptance/helpers/pluralization_helpers.rb +13 -0
- data/test/support/acceptance/helpers/step_helpers.rb +69 -0
- data/test/support/acceptance/matchers/have_output.rb +31 -0
- data/test/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +54 -0
- data/test/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +75 -0
- data/test/support/tests/bundle.rb +94 -0
- data/test/support/tests/command_runner.rb +230 -0
- data/test/support/tests/current_bundle.rb +61 -0
- data/test/support/tests/filesystem.rb +100 -0
- data/test/support/tests/version.rb +45 -0
- data/test/test_helper.rb +18 -0
- data/test/warnings_spy.rb +62 -0
- data/test/warnings_spy/filesystem.rb +45 -0
- data/test/warnings_spy/partitioner.rb +36 -0
- data/test/warnings_spy/reader.rb +53 -0
- data/test/warnings_spy/reporter.rb +88 -0
- metadata +80 -121
- data/features/rails_integration.feature +0 -87
- data/features/step_definitions/rails_steps.rb +0 -77
- data/features/support/env.rb +0 -14
- data/gemfiles/3.0.gemfile +0 -7
- data/gemfiles/3.0.gemfile.lock +0 -127
- data/gemfiles/3.1.gemfile +0 -9
- data/gemfiles/3.1.gemfile.lock +0 -148
- data/gemfiles/3.2.gemfile +0 -9
- data/gemfiles/3.2.gemfile.lock +0 -146
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative 'base_helpers'
|
2
|
+
require_relative '../../tests/command_runner'
|
3
|
+
|
4
|
+
module AcceptanceTests
|
5
|
+
module CommandHelpers
|
6
|
+
include BaseHelpers
|
7
|
+
|
8
|
+
def run_command(*args)
|
9
|
+
Tests::CommandRunner.run(*args) do |runner|
|
10
|
+
runner.directory = fs.project_directory
|
11
|
+
yield runner if block_given?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def run_command!(*args)
|
16
|
+
run_command(*args) do |runner|
|
17
|
+
runner.run_successfully = true
|
18
|
+
yield runner if block_given?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_command_within_bundle(*args)
|
23
|
+
run_command(*args) do |runner|
|
24
|
+
runner.command_prefix = 'bundle exec'
|
25
|
+
runner.env['BUNDLE_GEMFILE'] = fs.find_in_project('Gemfile').to_s
|
26
|
+
|
27
|
+
runner.around_command do |run_command|
|
28
|
+
Bundler.with_clean_env(&run_command)
|
29
|
+
end
|
30
|
+
|
31
|
+
yield runner if block_given?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_command_within_bundle!(*args)
|
36
|
+
run_command_within_bundle(*args) do |runner|
|
37
|
+
runner.run_successfully = true
|
38
|
+
yield runner if block_given?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def run_rake_tasks(*tasks)
|
43
|
+
options = tasks.last.is_a?(Hash) ? tasks.pop : {}
|
44
|
+
args = ['bundle', 'exec', 'rake', *tasks, '--trace'] + [options]
|
45
|
+
run_command(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_rake_tasks!(*tasks)
|
49
|
+
options = tasks.last.is_a?(Hash) ? tasks.pop : {}
|
50
|
+
args = ['bundle', 'exec', 'rake', *tasks, '--trace'] + [options]
|
51
|
+
run_command!(*args)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'base_helpers'
|
2
|
+
|
3
|
+
module AcceptanceTests
|
4
|
+
module FileHelpers
|
5
|
+
include BaseHelpers
|
6
|
+
|
7
|
+
def append_to_file(path, content, options = {})
|
8
|
+
fs.append_to_file(path, content, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_from_file(path, pattern)
|
12
|
+
fs.remove_from_file(path, pattern)
|
13
|
+
end
|
14
|
+
|
15
|
+
def write_file(path, content)
|
16
|
+
fs.write(path, content)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'base_helpers'
|
2
|
+
require_relative 'command_helpers'
|
3
|
+
require_relative 'file_helpers'
|
4
|
+
|
5
|
+
module AcceptanceTests
|
6
|
+
module GemHelpers
|
7
|
+
include BaseHelpers
|
8
|
+
include CommandHelpers
|
9
|
+
include FileHelpers
|
10
|
+
|
11
|
+
def add_gem(gem, *args)
|
12
|
+
bundle.add_gem(gem, *args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def install_gems
|
16
|
+
bundle.install_gems
|
17
|
+
end
|
18
|
+
|
19
|
+
def updating_bundle(&block)
|
20
|
+
bundle.updating(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def bundle_version_of(gem)
|
24
|
+
bundle.version_of(gem)
|
25
|
+
end
|
26
|
+
|
27
|
+
def bundle_includes?(gem)
|
28
|
+
bundle.includes?(gem)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module AcceptanceTests
|
2
|
+
module PluralizationHelpers
|
3
|
+
def pluralize(count, singular_version, plural_version = nil)
|
4
|
+
plural_version ||= singular_version + 's'
|
5
|
+
|
6
|
+
if count == 1
|
7
|
+
"#{count} #{singular_version}"
|
8
|
+
else
|
9
|
+
"#{count} #{plural_version}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'file_helpers'
|
2
|
+
require_relative 'gem_helpers'
|
3
|
+
|
4
|
+
module AcceptanceTests
|
5
|
+
module StepHelpers
|
6
|
+
include FileHelpers
|
7
|
+
include GemHelpers
|
8
|
+
|
9
|
+
def add_shoulda_to_project(options = {})
|
10
|
+
AddShouldaToProject.call(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_minitest_to_project
|
14
|
+
add_gem 'minitest-reporters'
|
15
|
+
|
16
|
+
append_to_file 'test/test_helper.rb', <<-FILE
|
17
|
+
require 'minitest/autorun'
|
18
|
+
require 'minitest/reporters'
|
19
|
+
|
20
|
+
Minitest::Reporters.use!(Minitest::Reporters::SpecReporter.new)
|
21
|
+
FILE
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_n_unit_tests(*paths)
|
25
|
+
run_command_within_bundle 'ruby -I lib -I test', *paths
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_n_unit_test_suite
|
29
|
+
run_rake_tasks('test', env: { TESTOPTS: '-v' })
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_rails_application
|
33
|
+
fs.clean
|
34
|
+
rails_new
|
35
|
+
remove_unnecessary_gems
|
36
|
+
add_minitest_reporters_to_test_helper
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def rails_new
|
42
|
+
command = "bundle exec rails new #{fs.project_directory} --skip-bundle --no-rc"
|
43
|
+
|
44
|
+
run_command!(command) do |runner|
|
45
|
+
runner.directory = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
command
|
49
|
+
end
|
50
|
+
|
51
|
+
def remove_unnecessary_gems
|
52
|
+
updating_bundle do |bundle|
|
53
|
+
bundle.remove_gem 'turn'
|
54
|
+
bundle.remove_gem 'coffee-rails'
|
55
|
+
bundle.remove_gem 'uglifier'
|
56
|
+
bundle.remove_gem 'debugger'
|
57
|
+
bundle.remove_gem 'byebug'
|
58
|
+
bundle.remove_gem 'web-console'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_minitest_reporters_to_test_helper
|
63
|
+
fs.append_to_file 'test/test_helper.rb', <<-TEXT
|
64
|
+
require 'minitest/reporters'
|
65
|
+
Minitest::Reporters.use!(Minitest::Reporters::SpecReporter.new)
|
66
|
+
TEXT
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module AcceptanceTests
|
2
|
+
module Matchers
|
3
|
+
def have_output(output)
|
4
|
+
HaveOutputMatcher.new(output)
|
5
|
+
end
|
6
|
+
|
7
|
+
class HaveOutputMatcher
|
8
|
+
def initialize(output)
|
9
|
+
@output = output
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?(runner)
|
13
|
+
@runner = runner
|
14
|
+
runner.has_output?(output)
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
"Expected command to have output, but did not.\n\n" +
|
19
|
+
"Command: #{runner.formatted_command}\n\n" +
|
20
|
+
"Expected output:\n" +
|
21
|
+
output.inspect + "\n\n" +
|
22
|
+
"Actual output:\n" +
|
23
|
+
runner.output
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
attr_reader :output, :runner
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative '../helpers/pluralization_helpers'
|
2
|
+
|
3
|
+
module AcceptanceTests
|
4
|
+
module Matchers
|
5
|
+
def indicate_number_of_tests_was_run(expected_output)
|
6
|
+
IndicateNumberOfTestsWasRunMatcher.new(expected_output)
|
7
|
+
end
|
8
|
+
|
9
|
+
class IndicateNumberOfTestsWasRunMatcher
|
10
|
+
include PluralizationHelpers
|
11
|
+
|
12
|
+
def initialize(number)
|
13
|
+
@number = number
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches?(runner)
|
17
|
+
@runner = runner
|
18
|
+
expected_output === actual_output
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
message = "Expected output to indicate that #{some_tests_were_run}.\n" +
|
23
|
+
"Expected output: #{expected_output}\n"
|
24
|
+
|
25
|
+
message <<
|
26
|
+
if actual_output.empty?
|
27
|
+
'Actual output: (empty)'
|
28
|
+
else
|
29
|
+
"Actual output:\n#{actual_output}"
|
30
|
+
end
|
31
|
+
|
32
|
+
message
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
attr_reader :number, :runner
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def expected_output
|
42
|
+
/#{number} (?:tests?|runs?|examples?)(?:, #{number} assertions)?, 0 failures(?:, 0 errors(?:, 0 skips)?)?/
|
43
|
+
end
|
44
|
+
|
45
|
+
def actual_output
|
46
|
+
runner.output
|
47
|
+
end
|
48
|
+
|
49
|
+
def some_tests_were_run
|
50
|
+
pluralize(number, 'test was', 'tests were') + ' run'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../helpers/array_helpers'
|
2
|
+
require_relative '../helpers/pluralization_helpers'
|
3
|
+
|
4
|
+
module AcceptanceTests
|
5
|
+
module Matchers
|
6
|
+
def indicate_that_tests_were_run(series)
|
7
|
+
IndicateThatTestsWereRunMatcher.new(series)
|
8
|
+
end
|
9
|
+
|
10
|
+
class IndicateThatTestsWereRunMatcher
|
11
|
+
include ArrayHelpers
|
12
|
+
include PluralizationHelpers
|
13
|
+
|
14
|
+
def initialize(args)
|
15
|
+
@args = args
|
16
|
+
@series = args.values
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(runner)
|
20
|
+
@runner = runner
|
21
|
+
!matching_expected_output.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure_message
|
25
|
+
"Expected output to indicate that #{some_tests_were_run}.\n" +
|
26
|
+
"#{formatted_expected_output}\n" +
|
27
|
+
"#{formatted_actual_output}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
attr_reader :args, :series, :runner
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def matching_expected_output
|
37
|
+
@_matching_expected_output ||=
|
38
|
+
actual_output =~ expected_output
|
39
|
+
end
|
40
|
+
|
41
|
+
def expected_output
|
42
|
+
total = series.inject(:+)
|
43
|
+
/#{total} (tests|runs), #{total} assertions, 0 failures, 0 errors(, 0 skips)?/
|
44
|
+
end
|
45
|
+
|
46
|
+
def formatted_expected_output
|
47
|
+
if matching_expected_output
|
48
|
+
"Expected output:\n#{matching_actual_output}"
|
49
|
+
else
|
50
|
+
'Expected output: (n/a)'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def actual_output
|
55
|
+
runner.output
|
56
|
+
end
|
57
|
+
|
58
|
+
def formatted_actual_output
|
59
|
+
if actual_output.empty?
|
60
|
+
'Actual output: (empty)'
|
61
|
+
else
|
62
|
+
"Actual output:\n#{actual_output}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def some_tests_were_run
|
67
|
+
clauses = args.map do |type, number|
|
68
|
+
pluralize(number, "#{type} test was run", "#{type} tests were run")
|
69
|
+
end
|
70
|
+
|
71
|
+
to_sentence(clauses)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative 'filesystem'
|
2
|
+
require_relative 'command_runner'
|
3
|
+
require_relative 'version'
|
4
|
+
|
5
|
+
module Tests
|
6
|
+
class Bundle
|
7
|
+
def initialize
|
8
|
+
@already_updating = false
|
9
|
+
@fs = Filesystem.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def updating
|
13
|
+
if already_updating?
|
14
|
+
yield self
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
@already_updating = true
|
19
|
+
|
20
|
+
yield self
|
21
|
+
|
22
|
+
@already_updating = false
|
23
|
+
|
24
|
+
install_gems
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_gem(gem, *args)
|
28
|
+
updating do
|
29
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
30
|
+
version = args.shift
|
31
|
+
line = assemble_gem_line(gem, version, options)
|
32
|
+
fs.append_to_file('Gemfile', line)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def remove_gem(gem)
|
37
|
+
updating do
|
38
|
+
fs.comment_lines_matching('Gemfile', /^[ ]*gem ("|')#{gem}\1/)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def install_gems
|
43
|
+
CommandRunner.run!('bundle install --local') do |runner|
|
44
|
+
runner.retries = 5
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def version_of(gem)
|
49
|
+
Version.new(Bundler.definition.specs[gem][0].version)
|
50
|
+
end
|
51
|
+
|
52
|
+
def includes?(gem)
|
53
|
+
Bundler.definition.dependencies.any? do |dependency|
|
54
|
+
dependency.name == gem
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
attr_reader :fs
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def already_updating?
|
65
|
+
@already_updating
|
66
|
+
end
|
67
|
+
|
68
|
+
def assemble_gem_line(gem, version, options)
|
69
|
+
formatted_options = options.
|
70
|
+
map { |key, value| "#{key}: #{formatted_value(value)}" }.
|
71
|
+
join(', ')
|
72
|
+
|
73
|
+
line = %(gem '#{gem}')
|
74
|
+
|
75
|
+
if version
|
76
|
+
line << %(, '#{version}')
|
77
|
+
end
|
78
|
+
|
79
|
+
if options.any?
|
80
|
+
line << %(, #{formatted_options})
|
81
|
+
end
|
82
|
+
|
83
|
+
line << "\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
def formatted_value(value)
|
87
|
+
if value.is_a?(Pathname)
|
88
|
+
value.to_s.inspect
|
89
|
+
else
|
90
|
+
value.inspect
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|