beaker 3.12.0 → 3.13.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.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/acceptance/tests/subcommands/init.rb +17 -15
  3. data/acceptance/tests/subcommands/provision.rb +45 -0
  4. data/beaker.gemspec +5 -9
  5. data/bin/beaker +1 -1
  6. data/docs/concepts/test_tagging.md +27 -14
  7. data/docs/how_to/archive_sut_files.md +19 -1
  8. data/docs/how_to/hypervisors/README.md +20 -3
  9. data/docs/how_to/hypervisors/ec2.md +4 -0
  10. data/docs/how_to/hypervisors/vmpooler.md +24 -0
  11. data/docs/how_to/hypervisors/vsphere.md +0 -3
  12. data/docs/tutorials/installation.md +22 -7
  13. data/lib/beaker/cli.rb +28 -12
  14. data/lib/beaker/dsl.rb +2 -1
  15. data/lib/beaker/dsl/helpers/puppet_helpers.rb +1 -1
  16. data/lib/beaker/dsl/helpers/tk_helpers.rb +1 -1
  17. data/lib/beaker/dsl/structure.rb +0 -130
  18. data/lib/beaker/dsl/test_tagging.rb +157 -0
  19. data/lib/beaker/host/unix/exec.rb +9 -1
  20. data/lib/beaker/host_prebuilt_steps.rb +1 -1
  21. data/lib/beaker/hypervisor/openstack.rb +8 -9
  22. data/lib/beaker/options/command_line_parser.rb +19 -4
  23. data/lib/beaker/options/parser.rb +18 -9
  24. data/lib/beaker/options/presets.rb +6 -4
  25. data/lib/beaker/options/validator.rb +11 -5
  26. data/lib/beaker/subcommand.rb +84 -6
  27. data/lib/beaker/subcommands/subcommand_util.rb +58 -7
  28. data/lib/beaker/version.rb +1 -1
  29. data/spec/beaker/cli_spec.rb +44 -1
  30. data/spec/beaker/dsl/structure_spec.rb +1 -214
  31. data/spec/beaker/dsl/test_tagging_spec.rb +274 -0
  32. data/spec/beaker/host/cisco_spec.rb +4 -4
  33. data/spec/beaker/host/unix/exec_spec.rb +2 -2
  34. data/spec/beaker/host_prebuilt_steps_spec.rb +1 -1
  35. data/spec/beaker/options/command_line_parser_spec.rb +2 -2
  36. data/spec/beaker/options/parser_spec.rb +33 -24
  37. data/spec/beaker/options/validator_spec.rb +18 -3
  38. data/spec/beaker/subcommand/subcommand_util_spec.rb +121 -10
  39. metadata +12 -8
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+
3
+ class ClassMixedWithDSLStructure
4
+ include Beaker::DSL::TestTagging
5
+ include Beaker::DSL::Helpers::TestHelpers
6
+ end
7
+
8
+ describe ClassMixedWithDSLStructure do
9
+ include Beaker::DSL::Assertions
10
+
11
+ let (:logger) { double }
12
+ let (:metadata) { @metadata ||= {} }
13
+
14
+ before :each do
15
+ allow( subject ).to receive(:metadata).and_return(metadata)
16
+ end
17
+
18
+ describe '#tag' do
19
+ let ( :test_tag_and ) { @test_tag_and || [] }
20
+ let ( :test_tag_or ) { @test_tag_or || [] }
21
+ let ( :test_tag_exclude ) { @test_tag_exclude || [] }
22
+ let ( :options ) {
23
+ opts = Beaker::Options::OptionsHash.new
24
+ opts[:test_tag_and] = test_tag_and
25
+ opts[:test_tag_or] = test_tag_or
26
+ opts[:test_tag_exclude] = test_tag_exclude
27
+ opts
28
+ }
29
+
30
+ before :each do
31
+ allow( subject ).to receive( :platform_specific_tag_confines )
32
+ end
33
+
34
+ it 'sets tags on the TestCase\'s metadata object' do
35
+ subject.instance_variable_set(:@options, options)
36
+ tags = ['pants', 'jayjay', 'moguely']
37
+ subject.tag(*tags)
38
+ expect( metadata[:case][:tags] ).to be === tags
39
+ end
40
+
41
+ it 'lowercases the tags' do
42
+ subject.instance_variable_set(:@options, options)
43
+ tags_upper = ['pANTs', 'jAYJAy', 'moGUYly']
44
+ tags_lower = tags_upper.map(&:downcase)
45
+ subject.tag(*tags_upper)
46
+ expect( metadata[:case][:tags] ).to be === tags_lower
47
+ end
48
+
49
+ it 'skips the test if any of the requested tags isn\'t included in this test' do
50
+ test_tags = ['pants', 'jayjay', 'moguely']
51
+ @test_tag_and = test_tags.compact.push('needed_tag_not_in_test')
52
+ subject.instance_variable_set(:@options, options)
53
+
54
+ allow( subject ).to receive( :path )
55
+ expect( subject ).to receive( :skip_test )
56
+ subject.tag(*test_tags)
57
+ end
58
+
59
+ it 'runs the test if all requested tags are included in this test' do
60
+ @test_tag_and = ['pants_on_head', 'jayjay_jayjay', 'mo']
61
+ test_tags = @test_tag_and.compact.push('extra_asdf')
62
+ subject.instance_variable_set(:@options, options)
63
+
64
+ allow( subject ).to receive( :path )
65
+ expect( subject ).to receive( :skip_test ).never
66
+ subject.tag(*test_tags)
67
+ end
68
+
69
+ it 'skips the test if any of the excluded tags are included in this test' do
70
+ test_tags = ['ports', 'jay_john_mary', 'mog_the_dog']
71
+ @test_tag_exclude = [test_tags[0]]
72
+ subject.instance_variable_set(:@options, options)
73
+
74
+ allow( subject ).to receive( :path )
75
+ expect( subject ).to receive( :skip_test )
76
+ subject.tag(*test_tags)
77
+ end
78
+
79
+ it 'skips the test if an and-included & excluded tag are in this test' do
80
+ test_tags = ['ports', 'jay_john_mary', 'mog_the_dog']
81
+ @test_tag_and = [test_tags[1]]
82
+ @test_tag_exclude = [test_tags[0]]
83
+ subject.instance_variable_set(:@options, options)
84
+
85
+ allow( subject ).to receive( :path )
86
+ expect( subject ).to receive( :skip_test )
87
+ subject.tag(*test_tags)
88
+ end
89
+
90
+ it 'runs the test if none of the excluded tags are included in this test' do
91
+ @test_tag_exclude = ['pants_on_head', 'jayjay_jayjay', 'mo']
92
+ test_tags = ['pants_at_head', 'jayj00_jayjay', 'motly_crew']
93
+ subject.instance_variable_set(:@options, options)
94
+
95
+ allow( subject ).to receive( :path )
96
+ expect( subject ).to receive( :skip_test ).never
97
+ subject.tag(*test_tags)
98
+ end
99
+
100
+ it 'skips the test if none of the OR tags are included in this test' do
101
+ test_tags = ['portmanteau', 'foolios']
102
+ @test_tag_or = ['fish', 'crayons', 'parkas']
103
+ subject.instance_variable_set(:@options, options)
104
+
105
+ allow( subject ).to receive( :path )
106
+ expect( subject ).to receive( :skip_test )
107
+ subject.tag(*test_tags)
108
+ end
109
+
110
+ it 'runs the test if only one of the OR tags are included in this test' do
111
+ test_tags = ['portmanteau', 'foolios']
112
+ @test_tag_or = ['foolios', 'crayons', 'parkas']
113
+ subject.instance_variable_set(:@options, options)
114
+
115
+ allow( subject ).to receive( :path )
116
+ expect( subject ).to receive( :skip_test ).never
117
+ subject.tag(*test_tags)
118
+ end
119
+
120
+ it 'skips the test if an or-included & excluded tag are included in this test' do
121
+ test_tags = ['ports', 'jay_john_mary', 'mog_the_dog']
122
+ @test_tag_or = [test_tags[1]]
123
+ @test_tag_exclude = [test_tags[0]]
124
+ subject.instance_variable_set(:@options, options)
125
+
126
+ allow( subject ).to receive( :path )
127
+ expect( subject ).to receive( :skip_test )
128
+ subject.tag(*test_tags)
129
+ end
130
+ end
131
+ end
132
+
133
+ describe Beaker::DSL::TestTagging::PlatformTagConfiner do
134
+ let ( :confines_array ) { @confines_array || [] }
135
+ let ( :confiner ) {
136
+ Beaker::DSL::TestTagging::PlatformTagConfiner.new( confines_array )
137
+ }
138
+
139
+ describe '#initialize' do
140
+ it 'transforms one entry' do
141
+ platform_regex = /^ubuntu$/
142
+ tag_reason_hash = {
143
+ 'tag1' => 'reason1',
144
+ 'tag2' => 'reason2'
145
+ }
146
+ @confines_array = [ {
147
+ :platform => platform_regex,
148
+ :tag_reason_hash => tag_reason_hash
149
+ }
150
+ ]
151
+
152
+ internal_hash = confiner.instance_variable_get( :@tag_confine_details_hash )
153
+ expect( internal_hash.keys() ).to include( 'tag1' )
154
+ expect( internal_hash.keys() ).to include( 'tag2' )
155
+ expect( internal_hash.keys().length() ).to be === 2
156
+
157
+ tag_reason_hash.each do |tag, reason|
158
+ tag_array = internal_hash[tag]
159
+ expect( tag_array.length() ).to be === 1
160
+ tag_hash = tag_array[0]
161
+ expect( tag_hash[:platform_regex] ).to eql( platform_regex )
162
+ expect( tag_hash[:log_message] ).to match( /#{reason}/ )
163
+ expect( tag_hash[:type] ).to be === :except
164
+ end
165
+ end
166
+
167
+ it 'deals with the same tag being used on multiple platforms correctly' do
168
+ @confines_array = [
169
+ {
170
+ :platform => /^el-/,
171
+ :tag_reason_hash => {
172
+ 'tag1' => 'reason el 1',
173
+ 'tag2' => 'reason2'
174
+ }
175
+ }, {
176
+ :platform => /^cisco-/,
177
+ :tag_reason_hash => {
178
+ 'tag1' => 'reason cisco 1',
179
+ 'tag3' => 'reason3'
180
+ }
181
+ }
182
+ ]
183
+
184
+ internal_hash = confiner.instance_variable_get( :@tag_confine_details_hash )
185
+ expect( internal_hash.keys() ).to include( 'tag1' )
186
+ expect( internal_hash.keys() ).to include( 'tag2' )
187
+ expect( internal_hash.keys() ).to include( 'tag3' )
188
+ expect( internal_hash.keys().length() ).to be === 3
189
+
190
+ shared_tag_array = internal_hash['tag1']
191
+ expect( shared_tag_array.length() ).to be === 2
192
+
193
+ platform_el_found = false
194
+ platform_cisco_found = false
195
+ shared_tag_array.each do |confine_details|
196
+ case confine_details[:log_message]
197
+ when /\ el\ 1/
198
+ platform_el_found = true
199
+ platform_to_match = /^el-/
200
+ reason_to_match = /reason\ el\ 1/
201
+ when /\ cisco\ 1/
202
+ platform_cisco_found = true
203
+ platform_to_match = /^cisco-/
204
+ reason_to_match = /reason\ cisco\ 1/
205
+ else
206
+ log_msg = "unexpected log message for confine_details: "
207
+ log_msg << confine_details[:log_message]
208
+ fail( log_msg )
209
+ end
210
+
211
+ expect( confine_details[:platform_regex] ).to eql( platform_to_match )
212
+ expect( confine_details[:log_message] ).to match( reason_to_match )
213
+ end
214
+ expect( platform_el_found ).to be === true
215
+ expect( platform_cisco_found ).to be === true
216
+ end
217
+ end
218
+
219
+ describe '#confine_details' do
220
+ it 'returns an empty array if no tags match' do
221
+ fake_confine_details_hash = { 'tag1' => [ {:type => 1}, {:type => 2} ]}
222
+ confiner.instance_variable_set(
223
+ :@tag_confine_details_hash, fake_confine_details_hash
224
+ )
225
+ expect( confiner.confine_details( [ 'tag2', 'tag3' ] ) ).to be === []
226
+ end
227
+
228
+ context 'descriminates on tag name' do
229
+ fake_confine_details_hash = {
230
+ 'tag0' => [ 10, 20, 30, 40 ],
231
+ 'tag1' => [ 41, 51, 61, 71 ],
232
+ 'tag2' => [ 22, 32, 42, 52 ],
233
+ 'tag3' => [ 63, 73, 83, 93 ],
234
+ 'tag4' => [ 34, 44, 54, 64 ],
235
+ }
236
+
237
+ key_combos_to_test = fake_confine_details_hash.keys.map { |key| [key] }
238
+ key_combos_to_test << [ 'tag0', 'tag2' ]
239
+ key_combos_to_test << [ 'tag1', 'tag4' ]
240
+ key_combos_to_test << [ 'tag2', 'tag3', 'tag4' ]
241
+ key_combos_to_test << fake_confine_details_hash.keys()
242
+
243
+ before :each do
244
+ confiner.instance_variable_set(
245
+ :@tag_confine_details_hash, fake_confine_details_hash
246
+ )
247
+ end
248
+
249
+ key_combos_to_test.each do |key_combo_to_have|
250
+ it "selects key(s) #{key_combo_to_have} from #{fake_confine_details_hash.keys}" do
251
+ haves = []
252
+ key_combo_to_have.each do |key_to_have|
253
+ haves += fake_confine_details_hash[key_to_have]
254
+ end
255
+ keys_not_to_have = fake_confine_details_hash.keys.reject { |key_trial|
256
+ key_combo_to_have.include?( key_trial )
257
+ }
258
+ have_nots = []
259
+ keys_not_to_have.each do |key_not_to_have|
260
+ have_nots += fake_confine_details_hash[key_not_to_have]
261
+ end
262
+
263
+ details = confiner.confine_details( key_combo_to_have )
264
+ have_nots.each do |confine_details|
265
+ expect( details ).to_not include( confine_details )
266
+ end
267
+ haves.each do |confine_details|
268
+ expect( details ).to include( confine_details )
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
@@ -107,8 +107,8 @@ module Cisco
107
107
 
108
108
  it 'turns env maps into paired strings correctly' do
109
109
  @options = { :user => 'root' }
110
- env_map = { 'var1' => 'ans1', 'var2' => 'ans2' }
111
- answer_correct = 'source /etc/profile; export VAR1="ans1" VAR2="ans2";'
110
+ env_map = { 'var1' => 'ans1', 'VAR2' => 'ans2' }
111
+ answer_correct = 'source /etc/profile; export var1="ans1" VAR1="ans1" VAR2="ans2";'
112
112
  answer_test = host.environment_string( env_map )
113
113
  expect( answer_test ).to be === answer_correct
114
114
  end
@@ -141,8 +141,8 @@ module Cisco
141
141
 
142
142
  it 'turns env maps into paired strings correctly' do
143
143
  @options = { :user => 'root' }
144
- env_map = { 'var1' => 'ans1', 'var2' => 'ans2' }
145
- answer_correct = 'source /etc/profile; env VAR1="ans1" VAR2="ans2"'
144
+ env_map = { 'VAR1' => 'ans1', 'var2' => 'ans2' }
145
+ answer_correct = 'source /etc/profile; env VAR1="ans1" var2="ans2" VAR2="ans2"'
146
146
  answer_test = host.environment_string( env_map )
147
147
  expect( answer_test ).to be === answer_correct
148
148
  end
@@ -60,8 +60,8 @@ module Beaker
60
60
  end
61
61
 
62
62
  it 'takes an env hash with var_name/value pairs' do
63
- expect( instance.environment_string( {:HOME => '/'} ) ).
64
- to be == "env HOME=\"/\""
63
+ expect( instance.environment_string( {:HOME => '/', :http_proxy => 'http://foo'} ) ).
64
+ to be == 'env HOME="/" http_proxy="http://foo" HTTP_PROXY="http://foo"'
65
65
  end
66
66
 
67
67
  it 'takes an env hash with var_name/value[Array] pairs' do
@@ -349,7 +349,7 @@ describe Beaker do
349
349
 
350
350
  it "can sync keys on a non-solaris host" do
351
351
 
352
- expect( Beaker::Command ).to receive( :new ).with( sync_cmd % "env PATH=/usr/gnu/bin:$PATH bash" ).exactly( 3 ).times
352
+ expect( Beaker::Command ).to receive( :new ).with( sync_cmd % "env PATH=\"/usr/gnu/bin:$PATH\" bash" ).exactly( 3 ).times
353
353
 
354
354
  subject.sync_root_keys( hosts, options )
355
355
 
@@ -6,8 +6,8 @@ module Beaker
6
6
 
7
7
  let(:parser) {Beaker::Options::CommandLineParser.new}
8
8
  let(:test_opts) {["-h", "vcloud.cfg", "--debug", "--tests", "test.rb", "--help"]}
9
- let(:full_opts_in) {["--hosts", "host.cfg", "--options", "opts_file", "--helper", "path_to_helper", "--load-path", "load_path", "--tests", "test1.rb,test2.rb,test3.rb", "--pre-suite", "pre_suite.rb", "--post-suite", "post_suite.rb", "--pre-cleanup", "pre_cleanup.rb", "--no-provision", "--preserve-hosts", "always", "--root-keys", "--keyfile", "../.ssh/id_rsa", "--install", "gitrepopath", "-m", "module", "-q", "--dry-run", "--no-ntp", "--repo-proxy", "--add-el-extras", "--config", "anotherfile.cfg", "--fail-mode", "fast", "--no-color", "--no-color-host-output", "--version", "--log-level", "info", "--package-proxy", "http://192.168.100.1:3128", "--collect-perf-data", "--parse-only", "--validate", "--timeout", "40", "--log-prefix", "pants", "--configure", "--tag", "1,2,3", "--exclude-tag", "4,5,6", "--xml-time-order"]}
10
- let(:full_opts_out) {{:hosts_file=>"anotherfile.cfg",:options_file=>"opts_file", :helper => "path_to_helper", :load_path => "load_path", :tests => "test1.rb,test2.rb,test3.rb", :pre_suite => "pre_suite.rb", :post_suite => "post_suite.rb", :pre_cleanup => "pre_cleanup.rb", :provision=>false, :preserve_hosts => "always", :root_keys=>true, :keyfile => "../.ssh/id_rsa", :install => "gitrepopath", :modules=>"module", :quiet=>true, :dry_run=>true, :timesync=>false, :repo_proxy=>true, :add_el_extras=>true, :fail_mode => "fast", :color=>false, :color_host_output=>false, :beaker_version_print=>true, :log_level => "info", :package_proxy => "http://192.168.100.1:3128", :collect_perf_data=>"normal", :parse_only=>true, :validate=>true, :timeout => "40", :log_prefix => "pants", :configure => true, :tag_includes => "1,2,3", :tag_excludes => "4,5,6", :xml_time_enabled => true}}
9
+ let(:full_opts_in) {["--hosts", "host.cfg", "--options", "opts_file", "--helper", "path_to_helper", "--load-path", "load_path", "--tests", "test1.rb,test2.rb,test3.rb", "--pre-suite", "pre_suite.rb", "--post-suite", "post_suite.rb", "--pre-cleanup", "pre_cleanup.rb", "--no-provision", "--preserve-hosts", "always", "--root-keys", "--keyfile", "../.ssh/id_rsa", "--install", "gitrepopath", "-m", "module", "-q", "--dry-run", "--no-ntp", "--repo-proxy", "--add-el-extras", "--config", "anotherfile.cfg", "--fail-mode", "fast", "--no-color", "--no-color-host-output", "--version", "--log-level", "info", "--package-proxy", "http://192.168.100.1:3128", "--collect-perf-data", "--parse-only", "--validate", "--timeout", "40", "--log-prefix", "pants", "--configure", "--test-tag-and", "1,2,3", "--test-tag-or", "4,5,6", "--test-tag-exclude", "7,8,9", "--xml-time-order"]}
10
+ let(:full_opts_out) {{:hosts_file=>"anotherfile.cfg",:options_file=>"opts_file", :helper => "path_to_helper", :load_path => "load_path", :tests => "test1.rb,test2.rb,test3.rb", :pre_suite => "pre_suite.rb", :post_suite => "post_suite.rb", :pre_cleanup => "pre_cleanup.rb", :provision=>false, :preserve_hosts => "always", :root_keys=>true, :keyfile => "../.ssh/id_rsa", :install => "gitrepopath", :modules=>"module", :quiet=>true, :dry_run=>true, :timesync=>false, :repo_proxy=>true, :add_el_extras=>true, :fail_mode => "fast", :color=>false, :color_host_output=>false, :beaker_version_print=>true, :log_level => "info", :package_proxy => "http://192.168.100.1:3128", :collect_perf_data=>"normal", :parse_only=>true, :validate=>true, :timeout => "40", :log_prefix => "pants", :configure => true, :test_tag_and => "1,2,3", :test_tag_or => "4,5,6", :test_tag_exclude => "7,8,9", :xml_time_enabled => true}}
11
11
  let(:validate_true) {["--validate"]}
12
12
  let(:validate_false) {["--no-validate"]}
13
13
  let(:configure_true) {['--configure']}
@@ -479,51 +479,60 @@ module Beaker
479
479
  end
480
480
 
481
481
  describe '#normalize_tags!' do
482
- let (:tag_includes) { @tag_includes || [] }
483
- let (:tag_excludes) { @tag_excludes || [] }
484
- let (:options) {
485
- opts = Beaker::Options::OptionsHash.new
486
- opts[:tag_includes] = tag_includes
487
- opts[:tag_excludes] = tag_excludes
482
+ let (:test_tag_and ) { @test_tag_and || [] }
483
+ let (:test_tag_or ) { @test_tag_or || [] }
484
+ let (:test_tag_exclude ) { @test_tag_exclude || [] }
485
+ let (:options ) {
486
+ opts = Beaker::Options::OptionsHash.new
487
+ opts[:test_tag_and] = test_tag_and
488
+ opts[:test_tag_or] = test_tag_or
489
+ opts[:test_tag_exclude] = test_tag_exclude
488
490
  opts
489
491
  }
490
492
 
491
493
  it 'does not error if no tags overlap' do
492
- @tag_includes = 'can,tommies,potatoes,plant'
493
- @tag_excludes = 'joey,long_running,pants'
494
+ @test_tag_and = 'can,tommies,potatoes,plant'
495
+ @test_tag_or = 'juicy,zoomba,plantation'
496
+ @test_tag_exclude = 'joey,long_running,pants'
494
497
  parser.instance_variable_set(:@options, options)
495
498
 
496
- expect { parser.normalize_tags! }.not_to raise_error
499
+ expect { parser.normalize_test_tags! }.not_to raise_error
497
500
  end
498
501
 
499
502
  it 'splits the basic case correctly' do
500
- @tag_includes = 'can,tommies,potatoes,plant'
501
- @tag_excludes = 'joey,long_running,pants'
503
+ @test_tag_and = 'can,tommies,potatoes,plant'
504
+ @test_tag_or = 'johnny,wordsmith,zebra'
505
+ @test_tag_exclude = 'joey,long_running,pants'
502
506
  parser.instance_variable_set(:@options, options)
503
507
 
504
- parser.normalize_tags!
505
- expect(options[:tag_includes]).to be === ['can', 'tommies', 'potatoes', 'plant']
506
- expect(options[:tag_excludes]).to be === ['joey', 'long_running', 'pants']
508
+ parser.normalize_test_tags!
509
+ expect(options[:test_tag_and] ).to be === ['can', 'tommies', 'potatoes', 'plant']
510
+ expect(options[:test_tag_or] ).to be === ['johnny', 'wordsmith', 'zebra']
511
+ expect(options[:test_tag_exclude]).to be === ['joey', 'long_running', 'pants']
507
512
  end
508
513
 
509
514
  it 'returns empty arrays for empty strings' do
510
- @tag_includes = ''
511
- @tag_excludes = ''
515
+ @test_tag_and = ''
516
+ @test_tag_or = ''
517
+ @test_tag_exclude = ''
512
518
  parser.instance_variable_set(:@options, options)
513
519
 
514
- parser.normalize_tags!
515
- expect(options[:tag_includes]).to be === []
516
- expect(options[:tag_excludes]).to be === []
520
+ parser.normalize_test_tags!
521
+ expect(options[:test_tag_and] ).to be === []
522
+ expect(options[:test_tag_or] ).to be === []
523
+ expect(options[:test_tag_exclude]).to be === []
517
524
  end
518
525
 
519
526
  it 'lowercases all tags correctly for later use' do
520
- @tag_includes = 'jeRRy_And_tOM,PARka'
521
- @tag_excludes = 'lEet_spEAK,pOland'
527
+ @test_tag_and = 'jeRRy_And_tOM,PARka'
528
+ @test_tag_or = 'clearLy_They,Neva'
529
+ @test_tag_exclude = 'lEet_spEAK,pOland'
522
530
  parser.instance_variable_set(:@options, options)
523
531
 
524
- parser.normalize_tags!
525
- expect(options[:tag_includes]).to be === ['jerry_and_tom', 'parka']
526
- expect(options[:tag_excludes]).to be === ['leet_speak', 'poland']
532
+ parser.normalize_test_tags!
533
+ expect(options[:test_tag_and] ).to be === ['jerry_and_tom', 'parka']
534
+ expect(options[:test_tag_or] ).to be === ['clearly_they', 'neva']
535
+ expect(options[:test_tag_exclude]).to be === ['leet_speak', 'poland']
527
536
  end
528
537
  end
529
538
 
@@ -93,19 +93,34 @@ module Beaker
93
93
  end
94
94
  end
95
95
 
96
- describe '#validate_tags' do
96
+ describe '#validate_test_tags' do
97
97
  it 'does error if tags overlap' do
98
98
  tag_includes = %w(can tommies should_error potatoes plant)
99
99
  tag_excludes = %w(joey long_running pants should_error)
100
100
 
101
- expect { validator.validate_tags(tag_includes, tag_excludes) }.to raise_error(ArgumentError)
101
+ expect {
102
+ validator.validate_test_tags(tag_includes, [], tag_excludes)
103
+ }.to raise_error(ArgumentError)
102
104
  end
103
105
 
104
106
  it 'does not raise an error if tags do not overlap' do
105
107
  tag_includes = %w(horse dog cat)
106
108
  tag_excludes = %w(car truck train)
107
109
 
108
- expect { validator.validate_tags(tag_includes, tag_excludes) }.to_not raise_error
110
+ expect {
111
+ validator.validate_test_tags(tag_includes, [], tag_excludes)
112
+ }.to_not raise_error
113
+ end
114
+
115
+ it 'raises an error if AND and OR are both used' do
116
+ # this is because we don't have a way to specify how they
117
+ # should interact
118
+ tag_and = %w(square)
119
+ tag_or = %w(circle)
120
+
121
+ expect {
122
+ validator.validate_test_tags(tag_and, tag_or, [])
123
+ }.to raise_error(ArgumentError)
109
124
  end
110
125
  end
111
126