From 77103646678deed776784be9c3eba2ced4c6daea Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 9 Nov 2017 11:53:57 +0000 Subject: Make it possible to define global scenario attributes --- qa/.gitignore | 1 + qa/bin/qa | 2 +- qa/qa.rb | 1 + qa/qa/page/mattermost/login.rb | 2 +- qa/qa/page/mattermost/main.rb | 2 +- qa/qa/runtime/scenario.rb | 22 ++++++++++++- qa/qa/scenario/bootable.rb | 47 +++++++++++++++++++++++++++ qa/qa/scenario/entrypoint.rb | 2 ++ qa/qa/scenario/test/integration/mattermost.rb | 3 +- qa/spec/runtime/scenario_spec.rb | 27 +++++++++++++++ qa/spec/scenario/bootable_spec.rb | 24 ++++++++++++++ 11 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 qa/qa/scenario/bootable.rb create mode 100644 qa/spec/runtime/scenario_spec.rb create mode 100644 qa/spec/scenario/bootable_spec.rb diff --git a/qa/.gitignore b/qa/.gitignore index 3fec32c8427..19ec17d0005 100644 --- a/qa/.gitignore +++ b/qa/.gitignore @@ -1 +1,2 @@ tmp/ +.ruby-version diff --git a/qa/bin/qa b/qa/bin/qa index cecdeac14db..f1704dc54e9 100755 --- a/qa/bin/qa +++ b/qa/bin/qa @@ -4,4 +4,4 @@ require_relative '../qa' QA::Scenario .const_get(ARGV.shift) - .perform(*ARGV) + .launch!(*ARGV) diff --git a/qa/qa.rb b/qa/qa.rb index e8689a44f4d..a0d46c7c283 100644 --- a/qa/qa.rb +++ b/qa/qa.rb @@ -18,6 +18,7 @@ module QA ## # Support files # + autoload :Bootable, 'qa/scenario/bootable' autoload :Actable, 'qa/scenario/actable' autoload :Entrypoint, 'qa/scenario/entrypoint' autoload :Template, 'qa/scenario/template' diff --git a/qa/qa/page/mattermost/login.rb b/qa/qa/page/mattermost/login.rb index 2001dc5b230..42ab9c6f675 100644 --- a/qa/qa/page/mattermost/login.rb +++ b/qa/qa/page/mattermost/login.rb @@ -3,7 +3,7 @@ module QA module Mattermost class Login < Page::Base def initialize - visit(Runtime::Scenario.mattermost + '/login') + visit(Runtime::Scenario.mattermost_address + '/login') end def sign_in_using_oauth diff --git a/qa/qa/page/mattermost/main.rb b/qa/qa/page/mattermost/main.rb index e636d7676f4..4b8fc28e53f 100644 --- a/qa/qa/page/mattermost/main.rb +++ b/qa/qa/page/mattermost/main.rb @@ -3,7 +3,7 @@ module QA module Mattermost class Main < Page::Base def initialize - visit(Runtime::Scenario.mattermost) + visit(Runtime::Scenario.mattermost_address) end end end diff --git a/qa/qa/runtime/scenario.rb b/qa/qa/runtime/scenario.rb index 0c5e9787e17..7ef59046640 100644 --- a/qa/qa/runtime/scenario.rb +++ b/qa/qa/runtime/scenario.rb @@ -1,8 +1,28 @@ module QA module Runtime + ## + # Singleton approach to global test scenario arguments. + # module Scenario extend self - attr_accessor :mattermost + + attr_reader :attributes + + def define(attribute, value) + (@attributes ||= {}).store(attribute.to_sym, value) + + define_singleton_method(attribute) do + @attributes[attribute.to_sym].tap do |value| + if value.to_s.empty? + raise ArgumentError, "Empty `#{attribute}` attribute!" + end + end + end + end + + def method_missing(name, *) + raise ArgumentError, "Scenario attribute `#{name}` not defined!" + end end end end diff --git a/qa/qa/scenario/bootable.rb b/qa/qa/scenario/bootable.rb new file mode 100644 index 00000000000..22496bcc2fc --- /dev/null +++ b/qa/qa/scenario/bootable.rb @@ -0,0 +1,47 @@ +require 'optparse' + +module QA + module Scenario + module Bootable + Option = Struct.new(:name, :arg, :desc) + + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def launch!(argv) + arguments = OptionParser.new do |parser| + options.to_a.each do |opt| + parser.on(opt.arg, opt.desc) do |value| + Runtime::Scenario.define(opt.name, value) + end + end + end + + arguments.parse!(argv) + + if has_attributes? + self.perform(**Runtime::Scenario.attributes) + else + self.perform(*argv) + end + end + + private + + def attribute(name, arg, desc) + options.push(Option.new(name, arg, desc)) + end + + def options + @options ||= [] + end + + def has_attributes? + options.any? + end + end + end + end +end diff --git a/qa/qa/scenario/entrypoint.rb b/qa/qa/scenario/entrypoint.rb index 33cb2696f8f..8f708fe38ab 100644 --- a/qa/qa/scenario/entrypoint.rb +++ b/qa/qa/scenario/entrypoint.rb @@ -5,6 +5,8 @@ module QA # including staging and on-premises installation. # class Entrypoint < Template + include Bootable + def self.tags(*tags) @tags = tags end diff --git a/qa/qa/scenario/test/integration/mattermost.rb b/qa/qa/scenario/test/integration/mattermost.rb index 0220da929ce..7d0702afdb1 100644 --- a/qa/qa/scenario/test/integration/mattermost.rb +++ b/qa/qa/scenario/test/integration/mattermost.rb @@ -10,7 +10,8 @@ module QA tags :core, :mattermost def perform(address, mattermost, *files) - Runtime::Scenario.mattermost = mattermost + Runtime::Scenario.define(:mattermost_address, mattermost) + super(address, *files) end end diff --git a/qa/spec/runtime/scenario_spec.rb b/qa/spec/runtime/scenario_spec.rb new file mode 100644 index 00000000000..7009192bcc0 --- /dev/null +++ b/qa/spec/runtime/scenario_spec.rb @@ -0,0 +1,27 @@ +describe QA::Runtime::Scenario do + subject do + Module.new.extend(described_class) + end + + it 'makes it possible to define global scenario attributes' do + subject.define(:my_attribute, 'some-value') + subject.define(:another_attribute, 'another-value') + + expect(subject.my_attribute).to eq 'some-value' + expect(subject.another_attribute).to eq 'another-value' + expect(subject.attributes) + .to eq(my_attribute: 'some-value', another_attribute: 'another-value') + end + + it 'raises error when attribute is not known' do + expect { subject.invalid_accessor } + .to raise_error ArgumentError, /invalid_accessor/ + end + + it 'raises error when attribute is empty' do + subject.define(:empty_attribute, '') + + expect { subject.empty_attribute } + .to raise_error ArgumentError, /empty_attribute/ + end +end diff --git a/qa/spec/scenario/bootable_spec.rb b/qa/spec/scenario/bootable_spec.rb new file mode 100644 index 00000000000..273aac7677e --- /dev/null +++ b/qa/spec/scenario/bootable_spec.rb @@ -0,0 +1,24 @@ +describe QA::Scenario::Bootable do + subject do + Class.new(QA::Scenario::Template) + .include(described_class) + end + + it 'makes it possible to define the scenario attribute' do + subject.class_eval do + attribute :something, '--something SOMETHING', 'Some attribute' + attribute :another, '--another ANOTHER', 'Some other attribute' + end + + expect(subject).to receive(:perform) + .with(something: 'test', another: 'other') + + subject.launch!(%w[--another other --something test]) + end + + it 'does not require attributes to be defined' do + expect(subject).to receive(:perform).with('some', 'argv') + + subject.launch!(%w[some argv]) + end +end -- cgit v1.2.1