qat-cucumber 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/bin/qat +5 -0
- data/lib/qat/cli/generator/project.rb +32 -0
- data/lib/qat/cli/generator.rb +48 -0
- data/lib/qat/cli/main.rb +102 -0
- data/lib/qat/cli/plugins/core.rb +19 -0
- data/lib/qat/cli.rb +52 -0
- data/lib/qat/cucumber/core_ext/formatter/html.rb +48 -0
- data/lib/qat/cucumber/core_ext/formatter/junit.rb +57 -0
- data/lib/qat/cucumber/core_ext/result.rb +16 -0
- data/lib/qat/cucumber/core_ext.rb +3 -0
- data/lib/qat/cucumber/hooks/scenario.rb +76 -0
- data/lib/qat/cucumber/hooks.rb +72 -0
- data/lib/qat/cucumber/logger.rb +49 -0
- data/lib/qat/cucumber/time.rb +55 -0
- data/lib/qat/cucumber/version.rb +15 -0
- data/lib/qat/cucumber/world.rb +40 -0
- data/lib/qat/cucumber.rb +76 -0
- data/lib/qat/formatter/console.rb +101 -0
- data/lib/qat/formatter/dashboard.rb +84 -0
- data/lib/qat/formatter/loggable/mdc.rb +74 -0
- data/lib/qat/formatter/loggable/scenario_info.rb +40 -0
- data/lib/qat/formatter/loggable.rb +92 -0
- data/lib/qat/formatter/scenario/name.rb +47 -0
- data/lib/qat/formatter/tags.rb +81 -0
- data/lib/qat/formatter/test_ids.rb +93 -0
- data/lib/qat/jenkins.rb +43 -0
- data/lib/qat/project/Gemfile +13 -0
- data/lib/qat/project/Rakefile +3 -0
- data/lib/qat/project/config/cucumber.yml +13 -0
- data/lib/qat/project/config/default.yml +1 -0
- data/lib/qat/project/config/env-dummy/hosts.yml +9 -0
- data/lib/qat/project/config/env-dummy/jenkins.yml +7 -0
- data/lib/qat/project/config/env-dummy/logger.yml +23 -0
- data/lib/qat/project/config/env-dummy/time.yml +11 -0
- data/lib/qat/project/features/feature.feature +45 -0
- data/lib/qat/project/features/step_definitions/steps.rb +4 -0
- data/lib/qat/project/features/support/env.rb +6 -0
- data/lib/qat/project/features/support/hooks.rb +32 -0
- data/lib/qat/tasks/list.rb +50 -0
- data/lib/qat/tasks/steps.rb +20 -0
- data/lib/qat/tasks/tags/test_ids/helpers.rb +105 -0
- data/lib/qat/tasks/tags/test_ids/report.rb +41 -0
- data/lib/qat/tasks/tags/test_ids.rb +60 -0
- data/lib/qat/tasks/tags.rb +2 -0
- data/lib/qat/tasks/test.rb +35 -0
- data/lib/qat/tasks.rb +8 -0
- metadata +193 -0
data/bin/qat
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative '../../cucumber/version'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module QAT::CLI::Generator
|
5
|
+
|
6
|
+
#New project generator
|
7
|
+
# @since 0.1.0
|
8
|
+
class Project
|
9
|
+
include FileUtils
|
10
|
+
|
11
|
+
def initialize stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel
|
12
|
+
@fileutils_output = stdout
|
13
|
+
end
|
14
|
+
|
15
|
+
#Create a new project. Will create a new folder with the project's name.
|
16
|
+
#@param name [String] The new project's name
|
17
|
+
def run! name, opts={}
|
18
|
+
|
19
|
+
raise ArgumentError.new 'No project name given' unless name
|
20
|
+
raise ArgumentError.new "The project '#{name}' already exists" if ::File.directory? name
|
21
|
+
|
22
|
+
mkdir name, opts
|
23
|
+
cp_r ::File.join(::File.dirname(__FILE__), '..', '..', 'project', '.'), name, opts
|
24
|
+
cd name, opts do
|
25
|
+
mkdir_p ::File.join('config', 'common'), opts
|
26
|
+
mkdir_p 'lib', opts
|
27
|
+
mkdir_p 'public', opts
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../cucumber/version'
|
2
|
+
|
3
|
+
module QAT::CLI
|
4
|
+
#Module for the various generators used in the CLI utility
|
5
|
+
# @since 0.1.0
|
6
|
+
module Generator
|
7
|
+
# Creates a new QAT project with a given name
|
8
|
+
# @param name [String] project name
|
9
|
+
def create_project(name)
|
10
|
+
QAT::CLI::Generator::Project.new(@stdin, @stdout, @stderr, @kernel).run! name, @sub_options
|
11
|
+
|
12
|
+
if @options.has_key? :modules
|
13
|
+
FileUtils.cd name, @sub_options do
|
14
|
+
add_modules(@options[:modules])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds QAT modules to the current project
|
20
|
+
# @param modules [Array] list of modules' names to add
|
21
|
+
def add_modules(modules)
|
22
|
+
missing_modules = modules.reject { |mod| QAT::CLI.has_module? mod }
|
23
|
+
|
24
|
+
if missing_modules.any?
|
25
|
+
raise ArgumentError.new "Module#{missing_modules.size > 1 ? 's' : ''} #{missing_modules.join ','} missing!"
|
26
|
+
end
|
27
|
+
|
28
|
+
modules.each do |module_name|
|
29
|
+
add_module(module_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Adds a QAT module to the current project
|
34
|
+
# @param name [String] name of module to add
|
35
|
+
def add_module(name)
|
36
|
+
@stdout.puts "Adding module #{name}" if @sub_options[:verbose]
|
37
|
+
begin
|
38
|
+
QAT::CLI.add_module name, @stdout, @sub_options
|
39
|
+
@stdout.puts "Module #{name} added to #{Dir.getwd.split(::File::SEPARATOR).last}"
|
40
|
+
rescue => exception
|
41
|
+
@stderr.puts "Error adding module #{name}: #{exception.message}"
|
42
|
+
@exit_code = 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
require_relative 'generator/project'
|
data/lib/qat/cli/main.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require_relative '../cli'
|
2
|
+
require_relative '../cucumber/version'
|
3
|
+
require_relative 'generator'
|
4
|
+
require 'optparse'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
#Main class for the CLI.
|
9
|
+
#@since 0.1.0
|
10
|
+
class QAT::CLI::Main
|
11
|
+
include QAT::CLI::Generator
|
12
|
+
|
13
|
+
#Initialization from command line
|
14
|
+
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
|
15
|
+
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
16
|
+
@options = {}
|
17
|
+
@sub_options = {}
|
18
|
+
@exit_code = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
#Main entry point for execution
|
22
|
+
def execute!
|
23
|
+
parse_argv!
|
24
|
+
|
25
|
+
handle_options if @options.any?
|
26
|
+
|
27
|
+
rescue ArgumentError, OptionParser::MissingArgument => exception
|
28
|
+
@stderr.puts "Error: #{exception.message}"
|
29
|
+
@exit_code = 1
|
30
|
+
ensure
|
31
|
+
@kernel.exit(exit_code)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_accessor :exit_code
|
37
|
+
|
38
|
+
def parse_argv!
|
39
|
+
@argv = ['-h'] if @argv.empty?
|
40
|
+
|
41
|
+
opts = OptionParser.new do |parser|
|
42
|
+
parser.banner = 'Usage: qat [OPTIONS]'
|
43
|
+
# parser.separator ''
|
44
|
+
parser.separator 'Options'
|
45
|
+
|
46
|
+
project_options(parser)
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.parse!(@argv)
|
50
|
+
end
|
51
|
+
|
52
|
+
def handle_options
|
53
|
+
if @options.has_key? :project
|
54
|
+
create_project(@options[:project])
|
55
|
+
elsif @options.has_key? :modules
|
56
|
+
add_modules(@options[:modules])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def project_options(parser)
|
61
|
+
parser.on('-n', '--new [NAME]', String, 'Create new project') do |project|
|
62
|
+
@options[:project] = project
|
63
|
+
end
|
64
|
+
|
65
|
+
parser.on('-a', '--add [MODULES]', Array, 'Integrate modules in project') do |modules|
|
66
|
+
@options[:modules] = parse_modules(modules)
|
67
|
+
end
|
68
|
+
|
69
|
+
parser.on('-l', '--list', 'Show available modules') do
|
70
|
+
list_available_modules
|
71
|
+
@exit_code = 0
|
72
|
+
end
|
73
|
+
|
74
|
+
parser.on('-r', '--verbose', 'Show detailed information') do
|
75
|
+
@sub_options[:verbose] = true
|
76
|
+
end
|
77
|
+
|
78
|
+
parser.on('-v', '--version', 'Show QAT-Cucumber version') do
|
79
|
+
@stdout.puts QAT::Cucumber::VERSION
|
80
|
+
@exit_code = 0
|
81
|
+
end
|
82
|
+
|
83
|
+
parser.on('-h', '--help', 'Show this helper') do
|
84
|
+
@stdout.puts parser.help
|
85
|
+
@exit_code = 0
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_modules(modules)
|
90
|
+
modules = modules.to_a
|
91
|
+
existing_modules = @options[:modules]
|
92
|
+
existing_modules ? existing_modules + modules : modules
|
93
|
+
end
|
94
|
+
|
95
|
+
def list_available_modules
|
96
|
+
modules = QAT::CLI.list_extentions
|
97
|
+
|
98
|
+
@stdout.puts 'List of available modules:'
|
99
|
+
names = modules.map { |module_name| "\t#{module_name}" }
|
100
|
+
@stdout.puts names.join("\n")
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module QAT
|
2
|
+
module CLI
|
3
|
+
module Plugins
|
4
|
+
#Plugin for CLI functions
|
5
|
+
#@since 0.1.0
|
6
|
+
module Core
|
7
|
+
|
8
|
+
#Function for adding the Core module to a project. Just used for testing, does nothing.
|
9
|
+
#@param stdout [IO] Stdout stream
|
10
|
+
#@param opts [Hash] Options hash
|
11
|
+
#@since 0.1.0
|
12
|
+
def self.add_module stdout, opts
|
13
|
+
stdout.puts 'Nothing to add in Core module' if opts[:verbose]
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/qat/cli.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'little-plugger'
|
2
|
+
|
3
|
+
module QAT
|
4
|
+
#Module for CLI functions
|
5
|
+
#@since 0.1.0
|
6
|
+
module CLI
|
7
|
+
#Module as namespace for plugin definition
|
8
|
+
#@since 0.1.0
|
9
|
+
module Plugins
|
10
|
+
#Placeholder
|
11
|
+
end
|
12
|
+
# @!parse extend LittlePlugger
|
13
|
+
send :extend, LittlePlugger( :path => 'qat/cli/plugins', :module => ::QAT::CLI::Plugins )
|
14
|
+
|
15
|
+
#Lists all registered extentions/plugins
|
16
|
+
#@since 0.1.0
|
17
|
+
def self.list_extentions
|
18
|
+
plugins.keys.map(&:to_s).sort
|
19
|
+
end
|
20
|
+
|
21
|
+
#Call add_module in a given plugin.
|
22
|
+
#@param mod [String,Symbol] name of the plugin to call
|
23
|
+
#@param stdout [IO] stdout stream
|
24
|
+
#@param opts [Hash] options hash
|
25
|
+
#@raise ArgumentError When module does not exist
|
26
|
+
#@since 0.1.0
|
27
|
+
def self.add_module mod, stdout, opts
|
28
|
+
raise ArgumentError.new "Module #{mod} is not a plugin!" unless has_module? mod
|
29
|
+
|
30
|
+
loaded_mod = plugins[mod.to_sym]
|
31
|
+
|
32
|
+
if loaded_mod.respond_to? :add_module
|
33
|
+
meth = loaded_mod.method :add_module
|
34
|
+
unless meth.arity == 2 || meth.arity < 0
|
35
|
+
raise ArgumentError.new "Invalid implementation of add_module in #{mod}: should have 2 parameters: stdout, opts"
|
36
|
+
end
|
37
|
+
meth.call stdout, opts
|
38
|
+
else
|
39
|
+
stdout.puts "Nothing to add in #{mod}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
#Check if a plugin exists
|
45
|
+
#@param mod [String,Symbol] name of the plugin to call
|
46
|
+
#@return [true,false] true if the plugin exists
|
47
|
+
#@since 0.1.0
|
48
|
+
def self.has_module? mod
|
49
|
+
return plugins.has_key? mod.to_sym
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'cucumber/formatter/html'
|
2
|
+
|
3
|
+
#Extension to the cucumber module adding the embed video options
|
4
|
+
module Cucumber
|
5
|
+
#Extension to the formatter module adding the embed video options
|
6
|
+
module Formatter
|
7
|
+
#Extension to the html class adding the embed video options
|
8
|
+
class Html
|
9
|
+
#Method embed that also contains options to embed video case the extension is met
|
10
|
+
def embed(src, mime_type, label)
|
11
|
+
case (mime_type)
|
12
|
+
when /^image\/(png|gif|jpg|jpeg)/
|
13
|
+
unless File.file?(src) or src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
|
14
|
+
type = mime_type =~ /;base[0-9]+$/ ? mime_type : mime_type + ";base64"
|
15
|
+
src = "data:" + type + "," + src
|
16
|
+
end
|
17
|
+
embed_image(src, label)
|
18
|
+
when /^text\/plain/
|
19
|
+
embed_text(src, label)
|
20
|
+
when /^video\/\w+/
|
21
|
+
embed_video(src,mime_type, label)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#Method to embed the video in the HTML Report
|
26
|
+
def embed_video(src,mime_type, label)
|
27
|
+
@video_id ||= 0
|
28
|
+
|
29
|
+
if @io.respond_to?(:path) and File.file?(src)
|
30
|
+
out_dir = Pathname.new(File.dirname(File.absolute_path(@io.path)))
|
31
|
+
src = Pathname.new(File.absolute_path(src)).relative_path_from(out_dir)
|
32
|
+
end
|
33
|
+
|
34
|
+
@builder.span(:class => 'embed') do |pre|
|
35
|
+
pre << %{
|
36
|
+
<a href="" onclick="video=document.getElementById('video_div_#{@video_id}'); video.style.display = (video.style.display == 'none' ? 'block' : 'none');return false"><br>#{label}</a><br>
|
37
|
+
<div id="video_div_#{@video_id}" style="display: none">
|
38
|
+
<video id="video_#{@video_id}" autostart="0" width="800" height="600" controls> <source src="#{src}" type="#{mime_type}" ></video><br>
|
39
|
+
<a href="#{src}" download="#{src}">Download Video</a>
|
40
|
+
</div>}
|
41
|
+
end
|
42
|
+
|
43
|
+
@video_id += 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'cucumber/formatter/junit'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
module Formatter
|
5
|
+
# The formatter used for <tt>--format junit</tt>
|
6
|
+
class Junit
|
7
|
+
|
8
|
+
#Method to parse time in testsuite elements
|
9
|
+
def end_feature(feature_data)
|
10
|
+
@testsuite = Builder::XmlMarkup.new(:indent => 2)
|
11
|
+
@testsuite.instruct!
|
12
|
+
@testsuite.testsuite(
|
13
|
+
:failures => feature_data[:failures],
|
14
|
+
:errors => feature_data[:errors],
|
15
|
+
:skipped => feature_data[:skipped],
|
16
|
+
:tests => feature_data[:tests],
|
17
|
+
:time => "%.3f" % feature_data[:time],
|
18
|
+
:name => feature_data[:feature].name) do
|
19
|
+
@testsuite << feature_data[:builder].target!
|
20
|
+
end
|
21
|
+
|
22
|
+
write_file(feature_result_filename(feature_data[:feature].file), @testsuite.target!)
|
23
|
+
end
|
24
|
+
|
25
|
+
#Method to parse time in testcase elements
|
26
|
+
def build_testcase(result, scenario_designation, output)
|
27
|
+
duration = ResultBuilder.new(result).test_case_duration
|
28
|
+
@current_feature_data[:time] += duration
|
29
|
+
classname = @current_feature_data[:feature].name
|
30
|
+
name = scenario_designation
|
31
|
+
|
32
|
+
@current_feature_data[:builder].testcase(:classname => classname, :name => name, :time => "%.3f" % duration) do
|
33
|
+
if !result.passed? && result.ok?(@config.strict?)
|
34
|
+
@current_feature_data[:builder].skipped
|
35
|
+
@current_feature_data[:skipped] += 1
|
36
|
+
elsif !result.passed?
|
37
|
+
status = result.to_sym
|
38
|
+
exception = get_backtrace_object(result)
|
39
|
+
@current_feature_data[:builder].failure(:message => "#{status} #{name}", :type => status) do
|
40
|
+
@current_feature_data[:builder].cdata! output
|
41
|
+
@current_feature_data[:builder].cdata!(format_exception(exception)) if exception
|
42
|
+
end
|
43
|
+
@current_feature_data[:failures] += 1
|
44
|
+
end
|
45
|
+
@current_feature_data[:builder].tag!('system-out') do
|
46
|
+
@current_feature_data[:builder].cdata! strip_control_chars(@interceptedout.buffer.join)
|
47
|
+
end
|
48
|
+
@current_feature_data[:builder].tag!('system-err') do
|
49
|
+
@current_feature_data[:builder].cdata! strip_control_chars(@interceptederr.buffer.join)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@current_feature_data[:tests] += 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'cucumber/core/test/result'
|
2
|
+
|
3
|
+
#Patch for Cucumber::Core::Test::Result::Unknown to implement methods used by the formatters
|
4
|
+
#@since 1.1.0
|
5
|
+
class Cucumber::Core::Test::Result::Unknown
|
6
|
+
|
7
|
+
#Dummy function
|
8
|
+
def with_appended_backtrace(_)
|
9
|
+
''
|
10
|
+
end
|
11
|
+
|
12
|
+
#Dummy function
|
13
|
+
def with_filtered_backtrace(_)
|
14
|
+
''
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'cucumber'
|
3
|
+
require 'qat/logger'
|
4
|
+
|
5
|
+
module QAT
|
6
|
+
module Cucumber
|
7
|
+
#Methods to execute with Cucumber Hooks and at_exit.
|
8
|
+
#@since 0.1.0
|
9
|
+
module Hooks
|
10
|
+
module Scenario
|
11
|
+
include QAT::Logger
|
12
|
+
|
13
|
+
def scenario_tags(scenario)
|
14
|
+
scenario.tags.map { |tag| tag.name }.compact
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_test_id(scenario)
|
18
|
+
test_id = "#{test_id(scenario)}"
|
19
|
+
|
20
|
+
QAT[:current_test_id] = test_id
|
21
|
+
QAT[:current_test_run_id] = "#{test_id}_#{QAT[:test_start_timestamp].to_i}"
|
22
|
+
log.info "Scenario has test id: #{QAT[:current_test_id]} and test run id: #{QAT[:current_test_run_id]}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def test_id(scenario)
|
27
|
+
outline_id = get_outline_id(scenario)
|
28
|
+
|
29
|
+
tags = scenario_tags(scenario)
|
30
|
+
tag = tags.select { |tag| tag.match /^\@test\#/ }.first
|
31
|
+
test_id = if tag
|
32
|
+
tag.gsub '@test#', 'test_'
|
33
|
+
else
|
34
|
+
log.warn "Scenario does not have a test id! Using a dummy one..."
|
35
|
+
'test_0'
|
36
|
+
end
|
37
|
+
|
38
|
+
"#{test_id}#{outline_id}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_outline_id(scenario)
|
42
|
+
if scenario.is_a? ::Cucumber::RunningTestCase::ScenarioOutlineExample
|
43
|
+
test_case = scenario.instance_exec { @test_case }
|
44
|
+
test_case_source = test_case.source
|
45
|
+
|
46
|
+
tables = get_example_tables(test_case_source)
|
47
|
+
table_lines = get_examples_size(tables)
|
48
|
+
table_num = current_outline_index(tables, test_case_source)
|
49
|
+
previous_outlines = count_previous_outlines(table_lines, table_num)
|
50
|
+
"_#{previous_outlines + test_case_source[3].number}"
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_example_tables(test_case_source)
|
57
|
+
test_case_source[1].instance_exec { @examples_tables }
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_examples_size(tables)
|
61
|
+
tables.each.map { |table| table.example_rows.size }
|
62
|
+
end
|
63
|
+
|
64
|
+
def current_outline_index(tables, test_case_source)
|
65
|
+
tables.index test_case_source[2]
|
66
|
+
end
|
67
|
+
|
68
|
+
def count_previous_outlines(table_lines, table_num)
|
69
|
+
table_lines[0...table_num].inject(0) { |sum, lines| sum += lines; sum }
|
70
|
+
end
|
71
|
+
|
72
|
+
extend self
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'cucumber'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'qat/time'
|
6
|
+
require_relative 'version'
|
7
|
+
require_relative 'hooks/scenario'
|
8
|
+
|
9
|
+
module QAT
|
10
|
+
module Cucumber
|
11
|
+
#Methods to execute with Cucumber Hooks and at_exit.
|
12
|
+
#@since 0.1.0
|
13
|
+
module Hooks
|
14
|
+
include QAT::Logger
|
15
|
+
|
16
|
+
class << self
|
17
|
+
#Hook to be executed before a scenario. It executes the following actions:
|
18
|
+
# * save scenario tags (Saved in {QAT::Core} with the :scenario_tags key)
|
19
|
+
# * save current test start timestamp (Saved in {QAT::Core} with the :test_start_timestamp key)
|
20
|
+
# * create a temporary folder (Saved in {QAT::Core} with the :tmp_folder key)
|
21
|
+
def before(scenario)
|
22
|
+
QAT.reset!
|
23
|
+
|
24
|
+
QAT.store :scenario_tags, Scenario.scenario_tags(scenario)
|
25
|
+
QAT.store :test_start_timestamp, QAT::Time.now
|
26
|
+
QAT.store :tmp_folder, Dir.mktmpdir
|
27
|
+
|
28
|
+
Scenario.define_test_id(scenario)
|
29
|
+
rescue => error
|
30
|
+
log.warn { error }
|
31
|
+
end
|
32
|
+
|
33
|
+
def after_step
|
34
|
+
#TODO
|
35
|
+
rescue => error
|
36
|
+
log.warn { error }
|
37
|
+
end
|
38
|
+
|
39
|
+
#Hook to be executed after a scenario. It executes the following actions:
|
40
|
+
# * delete the temporary folder
|
41
|
+
# * reset the cache
|
42
|
+
def after(_)
|
43
|
+
FileUtils.rm_r QAT[:tmp_folder]
|
44
|
+
rescue => error
|
45
|
+
log.warn { error }
|
46
|
+
end
|
47
|
+
|
48
|
+
def at_exit
|
49
|
+
#TODO
|
50
|
+
rescue => error
|
51
|
+
log.warn { error }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Before do |scenario|
|
59
|
+
QAT::Cucumber::Hooks.before(scenario)
|
60
|
+
end
|
61
|
+
|
62
|
+
AfterStep do
|
63
|
+
QAT::Cucumber::Hooks.after_step
|
64
|
+
end
|
65
|
+
|
66
|
+
After do |scenario|
|
67
|
+
QAT::Cucumber::Hooks.after(scenario)
|
68
|
+
end
|
69
|
+
|
70
|
+
at_exit do
|
71
|
+
QAT::Cucumber::Hooks.at_exit
|
72
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module QAT
|
2
|
+
module Cucumber
|
3
|
+
# Helper methods for logger configuration
|
4
|
+
# @since 2.0.2
|
5
|
+
module Logger
|
6
|
+
# Configures Logger with a given configuration
|
7
|
+
# @param configuration [Hash] logger configuration
|
8
|
+
def config_logger(configuration)
|
9
|
+
config = validate_logger_config(configuration)
|
10
|
+
|
11
|
+
load_logger_config(config) if config
|
12
|
+
end
|
13
|
+
|
14
|
+
# Validates that a valid logger configuration exists in the QAT environment variable
|
15
|
+
# @param configuration [Hash] logger configuration
|
16
|
+
def validate_logger_config(configuration)
|
17
|
+
logger_env_config = ENV['QAT_LOGGER_CONFIG']
|
18
|
+
|
19
|
+
if logger_env_config
|
20
|
+
raise InvalidConfiguration.new "Configuration file for logger does not exist: '#{logger_env_config}'" unless File.exists?(logger_env_config.to_s)
|
21
|
+
logger_env_config
|
22
|
+
else
|
23
|
+
validate_logger_yaml_config(configuration)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Validates that a valid logger configuration exists in a YAML file
|
28
|
+
# @param configuration [Hash] logger configuration
|
29
|
+
def validate_logger_yaml_config(configuration)
|
30
|
+
configuration_directory = configuration.directory
|
31
|
+
|
32
|
+
files = [File.join(configuration_directory, configuration.environment, 'logger.yml'),
|
33
|
+
File.join(configuration_directory, 'common', 'logger.yml')]
|
34
|
+
|
35
|
+
config = files.select { |file| File.exists?(file) }
|
36
|
+
|
37
|
+
config.first
|
38
|
+
end
|
39
|
+
|
40
|
+
# Loads the logger configuration
|
41
|
+
# @param to_load [Hash] logger configuration to load
|
42
|
+
def load_logger_config(to_load)
|
43
|
+
Log4r::YamlConfigurator.load_yaml_file(to_load)
|
44
|
+
|
45
|
+
log.info { "Loaded logger configuration from file '#{to_load}'" }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module QAT
|
2
|
+
module Cucumber
|
3
|
+
# Helper methods for time sync
|
4
|
+
# @since 2.0.2
|
5
|
+
module Time
|
6
|
+
include QAT::Logger
|
7
|
+
|
8
|
+
# Mandatory keys for time sync
|
9
|
+
MANDATORY_KEYS = [:sync]
|
10
|
+
|
11
|
+
# Does the time synchronization between the host running tests and a target host
|
12
|
+
def time_sync
|
13
|
+
time = validate_time_options
|
14
|
+
|
15
|
+
sync_options = time[:sync]
|
16
|
+
log.info { "Syncing with host #{sync_options[:host]}." }
|
17
|
+
target = sync_options.values_at(:host, :method, :opts)
|
18
|
+
|
19
|
+
start_time_sync(target, sync_options)
|
20
|
+
|
21
|
+
set_time_zone(time[:zone])
|
22
|
+
end
|
23
|
+
|
24
|
+
# validates that the necessary options are present
|
25
|
+
def validate_time_options
|
26
|
+
time = QAT.configuration[:time].deep_symbolize_keys
|
27
|
+
missing = MANDATORY_KEYS - time.keys
|
28
|
+
|
29
|
+
raise InvalidConfiguration.new "Time configuration is not valid! Missing: #{missing.join(', ')}" if missing.any?
|
30
|
+
|
31
|
+
time
|
32
|
+
end
|
33
|
+
|
34
|
+
# Does the time sync with the target host
|
35
|
+
# @param target [Array] host, method of sync, options
|
36
|
+
# @param sync_options [Hash] sync options
|
37
|
+
def start_time_sync(target, sync_options)
|
38
|
+
QAT::Time.synchronize(*target)
|
39
|
+
rescue => exception
|
40
|
+
if sync_options[:kill_if_failed]
|
41
|
+
raise
|
42
|
+
else
|
43
|
+
log.warn { "Synchronization failed but proceeding anyway! [(#{exception.class}) #{exception.message}]" }
|
44
|
+
log.debug exception
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Sets the time zone
|
49
|
+
# @param time_zone [String] time zone
|
50
|
+
def set_time_zone(time_zone)
|
51
|
+
QAT::Time.zone = time_zone if time_zone
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
#QAT Module works as a namespace for all sub modules.
|
4
|
+
#Some singleton methods are also available, as defined by various sub classes.
|
5
|
+
#@since 0.1.0
|
6
|
+
module QAT
|
7
|
+
# Namespace for various helpers when running with cucumber.
|
8
|
+
#Just require 'qat/cucumber' to automatically integrate all the available helpers.
|
9
|
+
#
|
10
|
+
#@since 0.1.0
|
11
|
+
module Cucumber
|
12
|
+
# Represents QAT's version
|
13
|
+
VERSION = '6.0.0'
|
14
|
+
end
|
15
|
+
end
|