diff options
Diffstat (limited to 'qa/spec')
-rw-r--r-- | qa/spec/git/repository_spec.rb | 2 | ||||
-rw-r--r-- | qa/spec/helpers/stub_env.rb (renamed from qa/spec/support/stub_env.rb) | 2 | ||||
-rw-r--r-- | qa/spec/page/base_spec.rb | 30 | ||||
-rw-r--r-- | qa/spec/page/logging_spec.rb | 13 | ||||
-rw-r--r-- | qa/spec/resource/base_spec.rb | 2 | ||||
-rw-r--r-- | qa/spec/resource/events/base_spec.rb | 29 | ||||
-rw-r--r-- | qa/spec/resource/events/project_spec.rb | 69 | ||||
-rw-r--r-- | qa/spec/runtime/api/client_spec.rb | 2 | ||||
-rw-r--r-- | qa/spec/runtime/env_spec.rb | 2 | ||||
-rw-r--r-- | qa/spec/shared_examples/scenario_shared_examples.rb (renamed from qa/spec/support/shared_examples/scenario_shared_examples.rb) | 0 | ||||
-rw-r--r-- | qa/spec/spec_helper.rb | 91 | ||||
-rw-r--r-- | qa/spec/spec_helper_spec.rb | 373 | ||||
-rw-r--r-- | qa/spec/support/waiter_spec.rb | 37 |
13 files changed, 465 insertions, 187 deletions
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb index 4a350cd6c42..62c81050bd9 100644 --- a/qa/spec/git/repository_spec.rb +++ b/qa/spec/git/repository_spec.rb @@ -1,5 +1,5 @@ describe QA::Git::Repository do - include Support::StubENV + include Helpers::StubENV shared_context 'git directory' do let(:repository) { described_class.new } diff --git a/qa/spec/support/stub_env.rb b/qa/spec/helpers/stub_env.rb index 4788e0ab46c..62b4a1df787 100644 --- a/qa/spec/support/stub_env.rb +++ b/qa/spec/helpers/stub_env.rb @@ -1,5 +1,5 @@ # Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb -module Support +module Helpers module StubENV def stub_env(key_or_hash, value = nil) init_stub unless env_stubbed? diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb index 076a8087db5..32a350f2154 100644 --- a/qa/spec/page/base_spec.rb +++ b/qa/spec/page/base_spec.rb @@ -59,4 +59,34 @@ describe QA::Page::Base do end end end + + describe '#wait' do + subject { Class.new(described_class).new } + + context 'when the condition is true' do + it 'does not refresh' do + expect(subject).not_to receive(:refresh) + + subject.wait(max: 0.01) { true } + end + + it 'returns true' do + expect(subject.wait(max: 0.1) { true }).to be_truthy + end + end + + context 'when the condition is false' do + it 'refreshes' do + expect(subject).to receive(:refresh).at_least(:once) + + subject.wait(max: 0.01) { false } + end + + it 'returns false' do + allow(subject).to receive(:refresh) + + expect(subject.wait(max: 0.01) { false }).to be_falsey + end + end + end end diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb index f289ee3c2bb..a6e9601cee4 100644 --- a/qa/spec/page/logging_spec.rb +++ b/qa/spec/page/logging_spec.rb @@ -4,8 +4,6 @@ require 'capybara/dsl' require 'logger' describe QA::Support::Page::Logging do - include Support::StubENV - let(:page) { double.as_null_object } before do @@ -31,11 +29,22 @@ describe QA::Support::Page::Logging do it 'logs wait' do expect { subject.wait(max: 0) {} } + .to output(/next wait uses reload: true/).to_stdout_from_any_process + expect { subject.wait(max: 0) {} } .to output(/with wait/).to_stdout_from_any_process expect { subject.wait(max: 0) {} } .to output(/ended wait after .* seconds$/).to_stdout_from_any_process end + it 'logs wait with reload false' do + expect { subject.wait(max: 0, reload: false) {} } + .to output(/next wait uses reload: false/).to_stdout_from_any_process + expect { subject.wait(max: 0, reload: false) {} } + .to output(/with wait/).to_stdout_from_any_process + expect { subject.wait(max: 0, reload: false) {} } + .to output(/ended wait after .* seconds$/).to_stdout_from_any_process + end + it 'logs scroll_to' do expect { subject.scroll_to(:element) } .to output(/scrolling to :element/).to_stdout_from_any_process diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb index a2a3ad01749..4a6b76c869f 100644 --- a/qa/spec/resource/base_spec.rb +++ b/qa/spec/resource/base_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true describe QA::Resource::Base do - include Support::StubENV + include Helpers::StubENV let(:resource) { spy('resource') } let(:location) { 'http://location' } diff --git a/qa/spec/resource/events/base_spec.rb b/qa/spec/resource/events/base_spec.rb new file mode 100644 index 00000000000..9cdf4785092 --- /dev/null +++ b/qa/spec/resource/events/base_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +describe QA::Resource::Events::Base do + let(:resource) do + Class.new(QA::Resource::Base) do + def api_get_path + '/foo' + end + end + end + + subject { resource.tap { |f| f.include(described_class) }.new } + + describe "#events" do + it 'fetches all events when called without parameters' do + allow(subject).to receive(:parse_body).and_return('returned') + + expect(subject).to receive(:api_get_from).with('/foo/events') + expect(subject.events).to eq('returned') + end + + it 'fetches events with a specified action type' do + allow(subject).to receive(:parse_body).and_return('returned') + + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed') + expect(subject.events(action: 'pushed')).to eq('returned') + end + end +end diff --git a/qa/spec/resource/events/project_spec.rb b/qa/spec/resource/events/project_spec.rb new file mode 100644 index 00000000000..b3efdb518f3 --- /dev/null +++ b/qa/spec/resource/events/project_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +describe QA::Resource::Events::Project do + let(:resource) do + Class.new(QA::Resource::Base) do + def api_get_path + '/foo' + end + end + end + let(:all_events) do + [ + { + "action_name": "pushed", + "push_data": { + "commit_title": "foo commit" + } + }, + { + "action_name": "pushed", + "push_data": { + "ref": "master" + } + }, + { + "action_name": "pushed", + "push_data": { + "ref": "another-branch" + } + } + ] + end + + before do + allow(subject).to receive(:max_wait).and_return(0.01) + allow(subject).to receive(:parse_body).and_return(all_events) + end + + subject { resource.tap { |f| f.include(described_class) }.new } + + describe "#wait_for_push" do + it 'waits for a push with a specified commit message' do + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed') + expect { subject.wait_for_push('foo commit') }.not_to raise_error + end + + it 'raises an error if a push with the specified commit message is not found' do + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed').at_least(:once) + expect { subject.wait_for_push('bar') }.to raise_error(QA::Resource::Events::EventNotFoundError) + end + end + + describe "#wait_for_push_new_branch" do + it 'waits for a push to master if no branch is given' do + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed') + expect { subject.wait_for_push_new_branch }.not_to raise_error + end + + it 'waits for a push to the given branch' do + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed') + expect { subject.wait_for_push_new_branch('another-branch') }.not_to raise_error + end + + it 'raises an error if a push with the specified branch is not found' do + expect(subject).to receive(:api_get_from).with('/foo/events?action=pushed').at_least(:once) + expect { subject.wait_for_push_new_branch('bar') }.to raise_error(QA::Resource::Events::EventNotFoundError) + end + end +end diff --git a/qa/spec/runtime/api/client_spec.rb b/qa/spec/runtime/api/client_spec.rb index 975586b505f..af43facc73d 100644 --- a/qa/spec/runtime/api/client_spec.rb +++ b/qa/spec/runtime/api/client_spec.rb @@ -1,5 +1,5 @@ describe QA::Runtime::API::Client do - include Support::StubENV + include Helpers::StubENV describe 'initialization' do it 'defaults to :gitlab address' do diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb index bc0ec08d66d..fc51f45c3a1 100644 --- a/qa/spec/runtime/env_spec.rb +++ b/qa/spec/runtime/env_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true describe QA::Runtime::Env do - include Support::StubENV + include Helpers::StubENV shared_examples 'boolean method' do |**kwargs| it_behaves_like 'boolean method with parameter', kwargs diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/shared_examples/scenario_shared_examples.rb index 5fd55d7d96b..5fd55d7d96b 100644 --- a/qa/spec/support/shared_examples/scenario_shared_examples.rb +++ b/qa/spec/shared_examples/scenario_shared_examples.rb diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index 0f3cf5f4408..cbdd6e881b1 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -1,42 +1,21 @@ require_relative '../qa' +require 'rspec/retry' -Dir[::File.join(__dir__, 'support', '**', '*.rb')].each { |f| require f } +%w[helpers shared_examples].each do |d| + Dir[::File.join(__dir__, d, '**', '*.rb')].each { |f| require f } +end RSpec.configure do |config| - ServerNotRespondingError = Class.new(RuntimeError) - - # The login page could take some time to load the first time it is visited. - # We visit the login page and wait for it to properly load only once at the beginning of the suite. - config.before(:suite) do - if QA::Runtime::Scenario.respond_to?(:gitlab_address) - QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login) - - unless QA::Page::Main::Login.perform(&:page_loaded?) - raise ServerNotRespondingError, "Login page did not load at #{QA::Page::Main::Login.perform(&:current_url)}" - end + config.before(:context) do + if self.class.metadata.keys.include?(:quarantine) + skip_or_run_quarantined_tests(self.class.metadata.keys, config.inclusion_filter.rules.keys) end end config.before do |example| QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug? - # If quarantine is tagged, skip tests that have other metadata unless - # they're also tagged. This lets us run quarantined tests in a particular - # category without running tests in other categories. - # E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged - # 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests - # using `--tag quarantine --tag smoke`, without this check we'd end up - # running that ldap test as well. - if config.inclusion_filter[:quarantine] - skip("Running tests tagged with all of #{config.inclusion_filter.rules.keys}") unless quarantine_and_optional_other_tag?(example, config) - end - end - - config.before(:each, :quarantine) do |example| - # Skip tests in quarantine unless we explicitly focus on them - # We could use an exclusion filter, but this way the test report will list - # the quarantined tests when they're not run so that we're aware of them - skip('In quarantine') unless config.inclusion_filter[:quarantine] + skip_or_run_quarantined_tests(example.metadata.keys, config.inclusion_filter.rules.keys) end config.expect_with :rspec do |expectations| @@ -53,20 +32,54 @@ RSpec.configure do |config| config.profile_examples = 10 config.order = :random Kernel.srand config.seed + + # show retry status in spec process + config.verbose_retry = true + + # show exception that triggers a retry if verbose_retry is set to true + config.display_try_failure_messages = true + + config.around do |example| + retry_times = example.metadata.keys.include?(:quarantine) ? 1 : 3 + example.run_with_retry retry: retry_times + end +end + +# Skip tests in quarantine unless we explicitly focus on them. +# Skip the entire context if a context is tagged. This avoids running before +# blocks unnecessarily. +# If quarantine is focussed, skip tests/contexts that have other metadata +# unless they're also focussed. This lets us run quarantined tests in a +# particular category without running tests in other categories. +# E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged +# 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests +# using `--tag quarantine --tag smoke`, without this check we'd end up +# running that ldap test as well. +# We could use an exclusion filter, but this way the test report will list +# the quarantined tests when they're not run so that we're aware of them +def skip_or_run_quarantined_tests(metadata_keys, filter_keys) + included_filters = filters_other_than_quarantine(filter_keys) + + if filter_keys.include?(:quarantine) + skip("Only running tests tagged with :quarantine and any of #{included_filters}") unless quarantine_and_optional_other_tag?(metadata_keys, included_filters) + else + skip('In quarantine') if metadata_keys.include?(:quarantine) + end +end + +def filters_other_than_quarantine(filter_keys) + filter_keys.reject { |key| key == :quarantine } end # Checks if a test has the 'quarantine' tag and other tags in the inclusion filter. # # Returns true if -# - the example metadata includes the quarantine tag -# - and the metadata and inclusion filter both have any other tag -# - or no other tags are in the inclusion filter -def quarantine_and_optional_other_tag?(example, config) - return false unless example.metadata.keys.include? :quarantine - - filters_other_than_quarantine = config.inclusion_filter.rules.keys.reject { |key| key == :quarantine } - - return true if filters_other_than_quarantine.empty? +# - the metadata includes the quarantine tag +# - and the metadata and inclusion filter both have any other tag +# - or no other tags are in the inclusion filter +def quarantine_and_optional_other_tag?(metadata_keys, included_filters) + return false unless metadata_keys.include? :quarantine + return true if included_filters.empty? - filters_other_than_quarantine.any? { |key| example.metadata.keys.include? key } + included_filters.any? { |key| metadata_keys.include? key } end diff --git a/qa/spec/spec_helper_spec.rb b/qa/spec/spec_helper_spec.rb index f001200fb52..27ec1ec80fe 100644 --- a/qa/spec/spec_helper_spec.rb +++ b/qa/spec/spec_helper_spec.rb @@ -10,49 +10,98 @@ describe 'rspec config tests' do end end + context 'default' do + it_behaves_like 'passing tests' + end + context 'foo', :foo do it_behaves_like 'passing tests' end - context 'default' do + context 'quarantine', :quarantine do + it_behaves_like 'passing tests' + end + + context 'bar quarantine', :bar, :quarantine do it_behaves_like 'passing tests' end end end - context 'default config' do - it 'tests are skipped if in quarantine' do + let(:group_2) do + RSpec.describe do + before(:all) do + @expectations = [1, 2, 3] + end + + example 'not in quarantine' do + expect(@expectations.shift).to be(3) + end + + example 'in quarantine', :quarantine do + expect(@expectations.shift).to be(3) + end + end + end + + context 'with no tags focussed' do + before do group.run + end - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) + context 'in a context tagged :foo' do + it 'skips tests in quarantine' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end + end - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to eq(2) + context 'in an untagged context' do + it 'skips tests in quarantine' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) - ex = default_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end + end + + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end end end - context "with 'quarantine' tagged" do + context 'with :quarantine focussed' do before do RSpec.configure do |config| config.inclusion_filter = :quarantine end + + group.run end after do RSpec.configure do |config| @@ -60,26 +109,44 @@ describe 'rspec config tests' do end end - it "only quarantined tests are run" do - group.run + context 'in an untagged context' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(1) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end + end + + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(1) - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to be(1) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end + end - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + context 'in a context tagged :quarantine' do + it 'runs all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to be(1) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end end end - context "with 'foo' tagged" do + context 'with a non-quarantine tag (:foo) focussed' do before do RSpec.configure do |config| config.inclusion_filter = :foo @@ -93,30 +160,43 @@ describe 'rspec config tests' do end end - it "tests are not run if not tagged 'foo'" do - default_context = group.children.find { |c| c.description == "default" } - expect(default_context.descendant_filtered_examples.count).to eq(0) + context 'in an untagged context' do + it 'runs no tests' do + context = group.children.find { |c| c.description == "default" } + expect(context.descendant_filtered_examples.count).to eq(0) + end end - it "tests are skipped if in quarantine" do - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) + context 'in a context tagged :foo' do + it 'skips quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end + end - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + context 'in a context tagged :quarantine' do + it 'runs no tests' do + context = group.children.find { |c| c.description == "quarantine" } + expect(context.descendant_filtered_examples.count).to eq(0) + end end end - context "with 'quarantine' and 'foo' tagged" do + context 'with :quarantine and a non-quarantine tag (:foo) focussed' do before do RSpec.configure do |config| config.inclusion_filter = { quarantine: true, foo: true } end + + group.run end after do RSpec.configure do |config| @@ -124,38 +204,67 @@ describe 'rspec config tests' do end end - it 'of tests tagged foo, only tests in quarantine run' do - group.run + context 'in an untagged context' do + it 'ignores untagged tests and skips tests even if in quarantine' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(1) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end + end - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:quarantine, :foo]') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end end - it 'if tests are not tagged they are skipped, even if they are in quarantine' do - group.run - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to eq(1) + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end + end + + context 'in a context tagged :bar and :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:quarantine, :foo]') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end end end - context "with 'foo' and 'bar' tagged" do + context 'with :quarantine and multiple non-quarantine tags focussed' do before do RSpec.configure do |config| - config.inclusion_filter = { bar: true, foo: true } + config.inclusion_filter = { bar: true, foo: true, quarantine: true } end + + group.run end after do RSpec.configure do |config| @@ -163,102 +272,84 @@ describe 'rspec config tests' do end end - it "runs tests tagged either 'foo' or 'bar'" do - group = RSpec.describe do - example 'foo', :foo do - end - example 'bar', :bar do - end - example 'foo and bar', :foo, :bar do - end - end - - group.run - expect(group.examples.count).to eq(3) - - ex = group.examples.find { |e| e.description == "foo" } - expect(ex.execution_result.status).to eq(:passed) + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "bar" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = group.examples.find { |e| e.description == "foo and bar" } - expect(ex.execution_result.status).to eq(:passed) - end - - it "skips quarantined tests tagged 'foo' and/or 'bar'" do - group = RSpec.describe do - example 'foo in quarantine', :foo, :quarantine do - end - example 'foo and bar in quarantine', :foo, :bar, :quarantine do - end + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') end + end - group.run - expect(group.examples.count).to eq(2) + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "foo in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') - ex = group.examples.find { |e| e.description == "foo and bar in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') + end end - it "ignores quarantined tests not tagged either 'foo' or 'bar'" do - group = RSpec.describe do - example 'in quarantine', :quarantine do - end - end + context 'in a context tagged :bar and :quarantine' do + it 'runs all tests' do + context = group.children.find { |c| c.description == "bar quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - group.run + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = group.examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to be_nil + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end end end - context "with 'foo' and 'bar' and 'quarantined' tagged" do - before do - RSpec.configure do |config| - config.inclusion_filter = { bar: true, foo: true, quarantine: true } + context 'rspec retry' do + context 'in an untagged context' do + before do + group_2.run end - end - after do - RSpec.configure do |config| - config.inclusion_filter.clear + + it 'should run example :retry times' do + examples = group_2.descendant_filtered_examples + ex = examples.find { |e| e.description == 'not in quarantine' } + expect(ex.execution_result.status).to eq(:passed) end end - it "runs tests tagged 'quarantine' and 'foo' or 'bar'" do - group = RSpec.describe do - example 'foo', :foo do - end - example 'bar and quarantine', :bar, :quarantine do - end - example 'foo and bar', :foo, :bar do - end - example 'foo, bar, and quarantine', :foo, :bar, :quarantine do + context 'with :quarantine focussed' do + before do + RSpec.configure do |config| + config.inclusion_filter = :quarantine end + group_2.run end - group.run - expect(group.examples.count).to eq(4) - - ex = group.examples.find { |e| e.description == "foo" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:bar, :foo, :quarantine]') - - ex = group.examples.find { |e| e.description == "bar and quarantine" } - expect(ex.execution_result.status).to eq(:passed) - - ex = group.examples.find { |e| e.description == "foo and bar" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:bar, :foo, :quarantine]') + after do + RSpec.configure do |config| + config.inclusion_filter.clear + end + end - ex = group.examples.find { |e| e.description == "foo, bar, and quarantine" } - expect(ex.execution_result.status).to eq(:passed) + it 'should run example once only' do + examples = group_2.descendant_filtered_examples + ex = examples.find { |e| e.description == 'in quarantine' } + expect(ex.execution_result.status).to eq(:failed) + end end end end diff --git a/qa/spec/support/waiter_spec.rb b/qa/spec/support/waiter_spec.rb new file mode 100644 index 00000000000..8283b65e1be --- /dev/null +++ b/qa/spec/support/waiter_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'logger' + +describe QA::Support::Waiter do + before do + logger = ::Logger.new $stdout + logger.level = ::Logger::DEBUG + QA::Runtime::Logger.logger = logger + end + + describe '.wait' do + context 'when the condition is true' do + it 'logs the start' do + expect { subject.wait(max: 0) {} } + .to output(/with wait: max 0; interval 0.1/).to_stdout_from_any_process + end + + it 'logs the end' do + expect { subject.wait(max: 0) {} } + .to output(/ended wait after .* seconds$/).to_stdout_from_any_process + end + end + + context 'when the condition is false' do + it 'logs the start' do + expect { subject.wait(max: 0) { false } } + .to output(/with wait: max 0; interval 0.1/).to_stdout_from_any_process + end + + it 'logs the end' do + expect { subject.wait(max: 0) { false } } + .to output(/ended wait after .* seconds$/).to_stdout_from_any_process + end + end + end +end |