allure-cucumber 2.13.3 → 2.13.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf71ff4be37b0dbb4c892bb0c1eac4e2675afd72108f74d77523acf2e3f60524
4
- data.tar.gz: 4bb650000518a74f2c687355a4e8a22a28d74789098bc9023ab55a1f623fedd9
3
+ metadata.gz: 4816fa39660623c9ae118e5e098ce2c2c11987e40320de2a3b504fcc572d17c6
4
+ data.tar.gz: e1a1b03c2b3d3361526a2f178cedce4fa0130e9c748a33b44830cefa69227f2a
5
5
  SHA512:
6
- metadata.gz: e1c369902bd7135359bc82f7ab8a562357a5670dfeb6e9ffe142dca93dccced4508cbf26149fce39b59cfd350fe51929722d313c92756190c49b6f3e9a3f6c58
7
- data.tar.gz: 5b1470875e259afd0b01dd992a848c06fa43304800c2b484fa5209368eccd78805b8e54e3fd8aaf5242751c181239b782555e81a976b11358f7cc1fe6fc9f137
6
+ metadata.gz: 5c7a059f69ed4c0e994c18d5bd6520ba8578bdcff1dcef86ed9bdb216e2cfd8e2e0809fea16f61a05604e43cf60f8d41a978eae30ab4c160c13800fbb30ab63e
7
+ data.tar.gz: 11dae442e16bf6c5b5b59322492ca860ba1a4fa51ea66ad53f39b9bbe72b5ada4ac6c85889f2b9633960e26b9060900fd0ec5379e0139d8fa24592368d173517
data/README.md CHANGED
@@ -1,44 +1,58 @@
1
1
  # Allure Cucumber Adaptor
2
+
2
3
  [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/allure-cucumber)
3
4
 
4
5
  This repository contains Allure adaptor for [Cucumber](http://cukes.info/) framework.
5
6
 
7
+ ## Cucumber versions
8
+
9
+ allure-cucumber versions <= 2.13.4 support only cucumber 3 and lower\
10
+ allure-cucumber versions >= 2.13.5 only support cucumber 4 and are not backwards compatible with cucumber 3 and lower
11
+
6
12
  ## Installation
7
13
 
8
14
  Add this line to your application's Gemfile:
9
15
 
10
16
  ```ruby
11
- gem 'allure-cucumber'
17
+ gem "allure-cucumber"
12
18
  ```
13
19
 
14
20
  And then execute:
15
21
 
16
22
  ```bash
17
- $ bundle
23
+ bundle
18
24
  ```
19
25
 
20
26
  Or install it yourself as:
21
27
 
22
28
  ```bash
23
- $ gem install allure-cucumber
29
+ gem install allure-cucumber
30
+ ```
31
+
32
+ Require in "support/env.rb":
33
+
34
+ ```ruby
35
+ require "allure-cucumber"
24
36
  ```
25
37
 
26
38
  ## Configuration
27
39
 
28
- Common allure configuration is set via `Allure.configure` method. To change id, add the following in `features/support/env.rb` file:
40
+ Common allure configuration is set via `AllureCucumber.configure` method. To change it, add the following in `features/support/env.rb` file:
29
41
 
30
42
  ```ruby
31
- Allure.configure do |c|
32
- c.results_directory = "/whatever/you/like"
33
- c.clean_results_directory = true
34
- c.logging_level = Logger::INFO
43
+ require "allure-cucumber"
44
+
45
+ AllureCucumber.configure do |config|
46
+ config.results_directory = "/whatever/you/like"
47
+ config.clean_results_directory = true
48
+ config.logging_level = Logger::INFO
35
49
  # these are used for creating links to bugs or test cases where {} is replaced with keys of relevant items
36
- c.link_tms_pattern = "http://www.jira.com/browse/{}"
37
- c.link_issue_pattern = "http://www.jira.com/browse/{}"
50
+ config.link_tms_pattern = "http://www.jira.com/browse/{}"
51
+ config.link_issue_pattern = "http://www.jira.com/browse/{}"
38
52
  end
39
53
  ```
40
54
 
41
- By default, allure-cucumber will analyze your cucumber tags looking for Test Management, Issue Management, and Severity hooks. Links to TMS and ISSUE and test severity will be displayed in the report. By default these prefixes are used:
55
+ By default, allure-cucumber will analyze your cucumber tags looking for Test Management, Issue Management, and Severity tag. Links to TMS and ISSUE and test severity will be displayed in the report. By default these prefixes are used:
42
56
 
43
57
  ```ruby
44
58
  DEFAULT_TMS_PREFIX = 'TMS:'
@@ -58,10 +72,10 @@ Example:
58
72
  You can configure these prefixes as well as tms and issue tracker urls like this:
59
73
 
60
74
  ```ruby
61
- AllureCucumber.configure do |c|
62
- c.tms_prefix = 'HIPTEST--'
63
- c.issue_prefix = 'JIRA++'
64
- c.severity_prefix = 'URGENCY:'
75
+ AllureCucumber.configure do |config|
76
+ config.tms_prefix = 'HIPTEST--'
77
+ config.issue_prefix = 'JIRA++'
78
+ config.severity_prefix = 'URGENCY:'
65
79
  end
66
80
  ```
67
81
 
@@ -78,12 +92,6 @@ Additional special tags exists for setting status detail of test scenarios, allu
78
92
 
79
93
  ## Usage
80
94
 
81
- Put the following in your `features/support/env.rb` file:
82
-
83
- ```ruby
84
- require 'allure-cucumber'
85
- ```
86
-
87
95
  Use `--format AllureCucumber::CucumberFormatter --out where/you-want-results` while running cucumber or add it to `cucumber.yml`. Note that cucumber `--out` option overrides `results_directory` set via `Allure.configure` method.
88
96
 
89
97
  You can also manually attach screenshots and links to test steps and test cases by interacting with allure lifecycle directly. For more info check out `allure-ruby-commons`
@@ -3,8 +3,8 @@
3
3
 
4
4
  require "allure-ruby-commons"
5
5
 
6
- require "allure_cucumber/formatter"
7
6
  require "allure_cucumber/config"
7
+ require "allure_cucumber/formatter"
8
8
 
9
9
  # Main allure-cucumber module providing configuration methods
10
10
  module AllureCucumber
@@ -12,7 +12,7 @@ module AllureCucumber
12
12
  # Get allure cucumber configuration
13
13
  # @return [Allure::CucumberConfig]
14
14
  def configuration
15
- CucumberConfig
15
+ CucumberConfig.instance
16
16
  end
17
17
 
18
18
  # Set allure configuration
@@ -20,7 +20,7 @@ module AllureCucumber
20
20
  # @yieldreturn [void]
21
21
  # @return [void]
22
22
  def configure
23
- yield(CucumberConfig)
23
+ yield(configuration)
24
24
  end
25
25
  end
26
26
  end
@@ -1,32 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "singleton"
4
+ require "forwardable"
5
+
3
6
  module AllureCucumber
4
7
  # Allure cucumber configuration
5
- class CucumberConfig
6
- class << self
7
- # @return [String] default tms tag prefix
8
- DEFAULT_TMS_PREFIX = "TMS:"
9
- # @return [String] default issue tag prefix
10
- DEFAULT_ISSUE_PREFIX = "ISSUE:"
11
- # @return [String] default severity tag prefix
12
- DEFAULT_SEVERITY_PREFIX = "SEVERITY:"
13
-
14
- attr_writer :tms_prefix, :issue_prefix, :severity_prefix
15
-
16
- # @return [String]
17
- def tms_prefix
18
- @tms_prefix || DEFAULT_TMS_PREFIX
19
- end
20
-
21
- # @return [String]
22
- def issue_prefix
23
- @issue_prefix || DEFAULT_ISSUE_PREFIX
24
- end
25
-
26
- # @return [String]
27
- def severity_prefix
28
- @severity_prefix || DEFAULT_SEVERITY_PREFIX
29
- end
8
+ class CucumberConfig < Allure::Config
9
+ include Singleton
10
+ extend Forwardable
11
+
12
+ # @return [String] default tms tag prefix
13
+ DEFAULT_TMS_PREFIX = "TMS:"
14
+ # @return [String] default issue tag prefix
15
+ DEFAULT_ISSUE_PREFIX = "ISSUE:"
16
+ # @return [String] default severity tag prefix
17
+ DEFAULT_SEVERITY_PREFIX = "SEVERITY:"
18
+
19
+ def_delegators :@allure_config,
20
+ :clean_results_directory,
21
+ :clean_results_directory=,
22
+ :link_issue_pattern,
23
+ :link_issue_pattern=,
24
+ :link_tms_pattern,
25
+ :link_tms_pattern=,
26
+ :logging_level,
27
+ :logging_level=,
28
+ :results_directory,
29
+ :results_directory=
30
+
31
+ attr_writer :tms_prefix, :issue_prefix, :severity_prefix
32
+
33
+ def initialize
34
+ @allure_config = Allure.configuration
35
+ end
36
+
37
+ # @return [String]
38
+ def tms_prefix
39
+ @tms_prefix || DEFAULT_TMS_PREFIX
40
+ end
41
+
42
+ # @return [String]
43
+ def issue_prefix
44
+ @issue_prefix || DEFAULT_ISSUE_PREFIX
45
+ end
46
+
47
+ # @return [String]
48
+ def severity_prefix
49
+ @severity_prefix || DEFAULT_SEVERITY_PREFIX
30
50
  end
31
51
  end
32
52
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "cucumber_model"
3
+ require "cucumber/core"
4
+
5
+ require_relative "models/cucumber_model"
4
6
 
5
7
  module AllureCucumber
6
8
  # Main formatter class. Translates cucumber event to allure lifecycle
7
9
  class CucumberFormatter
8
- include AllureCucumberModel
9
-
10
10
  # @return [Hash] hook handler methods
11
11
  HOOK_HANDLERS = {
12
12
  "Before hook" => :start_prepare_fixture,
@@ -25,6 +25,8 @@ module AllureCucumber
25
25
  c.results_directory = config.out_stream if config.out_stream.is_a?(String)
26
26
  end
27
27
 
28
+ @cucumber_model = AllureCucumberModel.new(config)
29
+
28
30
  config.on_event(:test_run_started, &method(:on_test_run_started))
29
31
  config.on_event(:test_case_started, &method(:on_test_case_started))
30
32
  config.on_event(:test_step_started, &method(:on_test_step_started))
@@ -33,48 +35,46 @@ module AllureCucumber
33
35
  end
34
36
 
35
37
  # Clean test result directory before starting run
36
- # @param [Cucumber::Events::TestRunStarted<Type>] _event
38
+ # @param [Cucumber::Events::TestRunStarted] _event
37
39
  # @return [void]
38
40
  def on_test_run_started(_event)
39
41
  lifecycle.clean_results_dir
40
42
  end
41
43
 
42
44
  # Handle test case started event
43
- # @param [Cucumber::Core::Events::TestCaseStarted] event
45
+ # @param [Cucumber::Events::TestCaseStarted] event
44
46
  # @return [void]
45
47
  def on_test_case_started(event)
46
48
  lifecycle.start_test_container(Allure::TestResultContainer.new(name: event.test_case.name))
47
- lifecycle.start_test_case(test_result(event.test_case))
49
+ lifecycle.start_test_case(cucumber_model.test_result(event.test_case))
48
50
  end
49
51
 
50
52
  # Handle test step started event
51
- # @param [Cucumber::Core::Events::TestStepStarted] event
53
+ # @param [Cucumber::Events::TestStepStarted] event
52
54
  # @return [void]
53
55
  def on_test_step_started(event)
54
- hook?(event.test_step) ? handle_hook_started(event.test_step) : handle_step_started(event.test_step)
56
+ event.test_step.hook? ? handle_hook_started(event.test_step) : handle_step_started(event.test_step)
55
57
  end
56
58
 
57
59
  # Handle test step finished event
58
- # @param [Cucumber::Core::Events::TestStepFinished] event
60
+ # @param [Cucumber::Events::TestStepFinished] event
59
61
  # @return [void]
60
62
  def on_test_step_finished(event)
61
- return if prepare_world_hook?(event.test_step)
62
-
63
63
  update_block = proc do |step|
64
64
  step.stage = Allure::Stage::FINISHED
65
65
  step.status = ALLURE_STATUS.fetch(event.result.to_sym, Allure::Status::BROKEN)
66
66
  end
67
- step_type = hook?(event.test_step) ? "fixture" : "test_step"
67
+ step_type = event.test_step.hook? ? "fixture" : "test_step"
68
68
 
69
69
  lifecycle.public_send("update_#{step_type}", &update_block)
70
70
  lifecycle.public_send("stop_#{step_type}")
71
71
  end
72
72
 
73
73
  # Handle test case finished event
74
- # @param [Cucumber::Core::Events::TestCaseFinished] event
74
+ # @param [Cucumber::Events::TestCaseFinished] event
75
75
  # @return [void]
76
76
  def on_test_case_finished(event)
77
- failure_details = failure_details(event.result)
77
+ failure_details = cucumber_model.failure_details(event.result)
78
78
  status = ALLURE_STATUS.fetch(event.result.to_sym, Allure::Status::BROKEN)
79
79
  lifecycle.update_test_case do |test_case|
80
80
  test_case.stage = Allure::Stage::FINISHED
@@ -89,30 +89,26 @@ module AllureCucumber
89
89
 
90
90
  private
91
91
 
92
- # @param [Cucumber::Core::Test::Step] test_step <description>
93
- # @return [Boolean]
94
- def hook?(test_step)
95
- HOOK_HANDLERS.key?(test_step.text)
96
- end
92
+ attr_accessor :cucumber_model
97
93
 
98
- # @param [Cucumber::Core::Test::Step] test_step
99
- # @return [Boolean]
100
- def prepare_world_hook?(test_step)
101
- hook?(test_step) && test_step.inspect.include?("prepare_world.rb")
94
+ # Get thread specific lifecycle
95
+ # @return [Allure::AllureLifecycle]
96
+ def lifecycle
97
+ Allure.lifecycle
102
98
  end
103
99
 
104
100
  # @param [Cucumber::Core::Test::Step] test_step
105
101
  # @return [void]
106
102
  def handle_step_started(test_step)
107
- lifecycle.start_test_step(step_result(test_step))
103
+ step = cucumber_model.step_result(test_step)
104
+ lifecycle.start_test_step(step[:allure_step])
105
+ step[:attachments].each { |att| lifecycle.write_attachment(att[:source], att[:allure_attachment]) }
108
106
  end
109
107
 
110
- # @param [Cucumber::Core::Test::Step] test_step
108
+ # @param [Cucumber::Core::Test::HookStep] hook_step
111
109
  # @return [void]
112
- def handle_hook_started(test_step)
113
- return if prepare_world_hook?(test_step)
114
-
115
- lifecycle.public_send(HOOK_HANDLERS[test_step.text], fixture_result(test_step))
110
+ def handle_hook_started(hook_step)
111
+ lifecycle.public_send(HOOK_HANDLERS[hook_step.text], cucumber_model.fixture_result(hook_step))
116
112
  end
117
113
  end
118
114
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+ require "cucumber/core"
5
+ require "cucumber/formatter/ast_lookup"
6
+
7
+ require_relative "scenario"
8
+ require_relative "step"
9
+ require_relative "tag_parser"
10
+
11
+ module AllureCucumber
12
+ # Support class for transforming cucumber test entities in to allure model entities
13
+ class AllureCucumberModel
14
+ include TagParser
15
+
16
+ # @param [Cucumber::Configuration] config
17
+ def initialize(config)
18
+ @ast_lookup = Cucumber::Formatter::AstLookup.new(config)
19
+ end
20
+
21
+ # Convert to allure test result
22
+ # @param [Cucumber::Core::Test::Case] test_case
23
+ # @return [Allure::TestResult]
24
+ def test_result(test_case)
25
+ scenario = Scenario.new(test_case, ast_lookup)
26
+
27
+ Allure::TestResult.new(
28
+ name: scenario.name,
29
+ description: scenario.description,
30
+ description_html: scenario.description,
31
+ history_id: scenario.id,
32
+ full_name: "#{scenario.feature_name}: #{scenario.name}",
33
+ labels: labels(scenario),
34
+ links: links(scenario),
35
+ parameters: parameters(scenario),
36
+ status_details: Allure::StatusDetails.new(**status_detail_tags(scenario.tags)),
37
+ )
38
+ end
39
+
40
+ # Convert to allure step result
41
+ # @param [Cucumber::Core::Test::Step] test_step
42
+ # @return [Hash]
43
+ def step_result(test_step)
44
+ step = Step.new(ast_lookup.step_source(test_step))
45
+ attachments = step_attachments(step)
46
+ allure_step = Allure::StepResult.new(
47
+ name: step.name,
48
+ attachments: attachments.map { |att| att[:allure_attachment] },
49
+ )
50
+
51
+ { allure_step: allure_step, attachments: attachments }
52
+ end
53
+
54
+ # Convert to allure step result
55
+ # @param [Cucumber::Core::Test::HookStep] hook_step
56
+ # @return [Allure::StepResult]
57
+ def fixture_result(hook_step)
58
+ Allure::FixtureResult.new(name: hook_step.location.to_s.split("/").last)
59
+ end
60
+
61
+ # Get failure details
62
+ # @param [Cucumber::Core::Test::Result] result
63
+ # @return [Hash<Symbol, String>]
64
+ def failure_details(result)
65
+ return { message: result.exception.message, trace: result.exception.backtrace.join("\n") } if result.failed?
66
+ return { message: result.message, trace: result.backtrace.join("\n") } if result.undefined?
67
+
68
+ {}
69
+ end
70
+
71
+ private
72
+
73
+ attr_reader :ast_lookup, :lifecycle
74
+
75
+ # @param [Scenario] scenario
76
+ # @return [Array<Allure::Label>]
77
+ def labels(scenario)
78
+ labels = []
79
+ labels << Allure::ResultUtils.framework_label("cucumber")
80
+ labels << Allure::ResultUtils.feature_label(scenario.feature_name)
81
+ labels << Allure::ResultUtils.package_label(scenario.feature_folder)
82
+ labels << Allure::ResultUtils.suite_label(scenario.feature_name)
83
+ labels << Allure::ResultUtils.story_label(scenario.name)
84
+ labels << Allure::ResultUtils.test_class_label(scenario.feature_file_name)
85
+ unless scenario.tags.empty?
86
+ labels.push(*tag_labels(scenario.tags))
87
+ labels << severity(scenario.tags)
88
+ end
89
+
90
+ labels
91
+ end
92
+
93
+ # @param [Cucumber::Core::Test::Case] test_case
94
+ # @return [Array<Allure::Link>]
95
+ def links(test_case)
96
+ tms_links(test_case.tags) + issue_links(test_case.tags)
97
+ end
98
+
99
+ # @param [AllureCucumber::Scenario] scenario
100
+ # @return [Array<Allure::Parameter>]
101
+ def parameters(scenario)
102
+ scenario.examples.map { |k, v| Allure::Parameter.new(k, v) }
103
+ end
104
+
105
+ # @param [Step] step
106
+ # @return [Array<Allure::Attachment>]
107
+ def step_attachments(step)
108
+ [data_table_attachment(step), docstring_attachment(step)].compact
109
+ end
110
+
111
+ # @param [Step] step
112
+ # @return [Allure::Attachment]
113
+ def data_table_attachment(step)
114
+ return unless step.data_table
115
+
116
+ attachment = Allure::ResultUtils.prepare_attachment("data-table", Allure::ContentType::CSV)
117
+ csv = step.data_table.rows.each_with_object([]) { |row, arr| arr.push(row.cells.map(&:value).to_csv) }.join("")
118
+ { source: csv, allure_attachment: attachment }
119
+ end
120
+
121
+ # @param [Step] step
122
+ # @return [String]
123
+ def docstring_attachment(step)
124
+ return unless step.doc_string
125
+
126
+ attachment = Allure::ResultUtils.prepare_attachment("docstring", Allure::ContentType::TXT)
127
+ { source: step.doc_string.content, allure_attachment: attachment }
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+
5
+ module AllureCucumber
6
+ # Cucumber scenario wrapper class
7
+ class Scenario
8
+ # @param [Cucumber::Core::Test::Case] test_case
9
+ # @param [Cucumber::Formatter::AstLookup] ast_lookup
10
+ def initialize(test_case, ast_lookup)
11
+ @test_case = test_case
12
+ @feature = ast_lookup.gherkin_document(test_case.location.file).feature
13
+ @scenario_source = ast_lookup.scenario_source(test_case)
14
+ end
15
+
16
+ # Unique scenario id
17
+ # @return [String]
18
+ def id
19
+ @id ||= Digest::MD5.hexdigest(test_case.inspect)
20
+ end
21
+
22
+ # Feature name scenario belongs to
23
+ # @return [String]
24
+ def feature_name
25
+ @feature_name ||= feature.name
26
+ end
27
+
28
+ # Scenario name
29
+ # @return [String]
30
+ def name
31
+ @name ||= scenario_outline? ? "#{scenario.name}, #{example_row}" : scenario.name
32
+ end
33
+
34
+ # Scenario description or it's location
35
+ # @return [String]
36
+ def description
37
+ @description ||= begin
38
+ scenario.description.empty? ? "Location - #{test_case.location}" : scenario.description.strip
39
+ end
40
+ end
41
+
42
+ # Scenario outline row parameters
43
+ # @return [Hash<String, String>]
44
+ def examples
45
+ @examples ||= scenario_outline? ? outline_parameters : {}
46
+ end
47
+
48
+ # Scenario tags
49
+ # @return [Array<String>]
50
+ def tags
51
+ @tags ||= test_case.tags.map(&:name)
52
+ end
53
+
54
+ # Feature file name
55
+ # @return [String]
56
+ def feature_file_name
57
+ @feature_file_name ||= test_case.location.file.split("/").last.gsub(".feature", "")
58
+ end
59
+
60
+ # Feature folder
61
+ # @return [String]
62
+ def feature_folder
63
+ @feature_folder ||= test_case.location.file.split("/")[-2]
64
+ end
65
+
66
+ private
67
+
68
+ attr_reader :test_case, :scenario_source, :feature
69
+
70
+ # Is scenario outline
71
+ # @return [Boolean]
72
+ def scenario_outline?
73
+ scenario_source.type == :ScenarioOutline
74
+ end
75
+
76
+ # Cucumber scenario object
77
+ # @return [
78
+ # Cucumber::Messages::GherkinDocument::Feature::Scenario,
79
+ # Cucumber::Messages::GherkinDocument::Feature::ScenarioOutline
80
+ # ]
81
+ def scenario
82
+ @scenario ||= scenario_outline? ? scenario_source.scenario_outline : scenario_source.scenario
83
+ end
84
+
85
+ # Scenario outline example row
86
+ # @return [String]
87
+ def example_row
88
+ @example_row ||= begin
89
+ "Examples (##{scenario_source.examples.table_body.index { |row| row.id == scenario_source.row.id } + 1})"
90
+ end
91
+ end
92
+
93
+ # Scenario outline row parameters
94
+ # @return [Hash<String, String>]
95
+ def outline_parameters
96
+ @outline_parameters ||= begin
97
+ names = scenario_source.examples.table_header.cells.map(&:value)
98
+ values = scenario_source.row.cells.map(&:value)
99
+ names.zip(values).to_h
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AllureCucumber
4
+ # Cucumber step wrapper class
5
+ class Step
6
+ # @param [Cucumber::Formatter::AstLookup::StepSource] step_source
7
+ def initialize(step_source)
8
+ @step = step_source.step
9
+ end
10
+
11
+ # Step name
12
+ # @return [String]
13
+ def name
14
+ @name ||= "#{step.keyword}#{step.text}"
15
+ end
16
+
17
+ # Step data table
18
+ # @return [Cucumber::Messages::GherkinDocument::Feature::Step::DataTable]
19
+ def data_table
20
+ @data_table ||= step.data_table
21
+ end
22
+
23
+ # Step docstring
24
+ # @return [String]
25
+ def doc_string
26
+ @doc_string ||= step.doc_string
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :step
32
+ end
33
+ end
@@ -1,52 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "config"
4
-
5
3
  module AllureCucumber
6
4
  # Cucumber tag parser helper methods
7
5
  module TagParser
8
- # @param [Cucumber::Core::Ast::Tag] tags
6
+ # @param [Array<String>] tags
9
7
  # @return [Array<Allure::Label>]
10
8
  def tag_labels(tags)
11
9
  tags
12
- .reject { |tag| reserved?(tag.name) }
13
- .map { |tag| Allure::ResultUtils.tag_label(tag.name.delete_prefix("@")) }
10
+ .reject { |tag| reserved?(tag) }
11
+ .map { |tag| Allure::ResultUtils.tag_label(tag.delete_prefix("@")) }
14
12
  end
15
13
 
16
- # @param [Cucumber::Core::Ast::Tag] tags
14
+ # @param [Array<String>] tags
17
15
  # @return [Array<Allure::Link>]
18
16
  def tms_links(tags)
19
- return [] unless Allure::Config.link_tms_pattern
17
+ return [] unless AllureCucumber.configuration.link_tms_pattern
20
18
 
21
- tms_pattern = reserved_patterns[:tms]
22
- tags
23
- .select { |tag| tag.name.match?(tms_pattern) }
24
- .map { |tag| tag.name.match(tms_pattern) { |match| Allure::ResultUtils.tms_link(match[:tms]) } }
19
+ matching_links(tags, :tms)
25
20
  end
26
21
 
27
- # @param [Cucumber::Core::Ast::Tag] tags
22
+ # @param [Array<String>] tags
28
23
  # @return [Array<Allure::Link>]
29
24
  def issue_links(tags)
30
- return [] unless Allure::Config.link_issue_pattern
25
+ return [] unless AllureCucumber.configuration.link_issue_pattern
31
26
 
32
- issue_pattern = reserved_patterns[:issue]
33
- tags
34
- .select { |tag| tag.name.match?(issue_pattern) }
35
- .map { |tag| tag.name.match(issue_pattern) { |match| Allure::ResultUtils.issue_link(match[:issue]) } }
27
+ matching_links(tags, :issue)
36
28
  end
37
29
 
38
- # @param [Cucumber::Core::Ast::Tag] tags
30
+ # @param [Array<String>] tags
39
31
  # @return [Allure::Label]
40
32
  def severity(tags)
41
33
  severity_pattern = reserved_patterns[:severity]
42
34
  severity = tags
43
- .detect { |tag| tag.name.match?(severity_pattern) }&.name
35
+ .detect { |tag| tag.match?(severity_pattern) }
44
36
  &.match(severity_pattern)&.[](:severity) || "normal"
45
37
 
46
38
  Allure::ResultUtils.severity_label(severity)
47
39
  end
48
40
 
49
- # @param [Cucumber::Core::Ast::Tag] tags
41
+ # @param [Array<String>] tags
50
42
  # @return [Hash<Symbol, Boolean>]
51
43
  def status_detail_tags(tags)
52
44
  {
@@ -58,12 +50,22 @@ module AllureCucumber
58
50
 
59
51
  private
60
52
 
61
- # @return [Hash<Symbol, Regexp>] <description>
53
+ # @param [Array<String>] tags
54
+ # @param [Symbol] type
55
+ # @return [Array<Allure::Link>]
56
+ def matching_links(tags, type)
57
+ pattern = reserved_patterns[type]
58
+ tags
59
+ .select { |tag| tag.match?(pattern) }
60
+ .map { |tag| tag.match(pattern) { |match| Allure::ResultUtils.public_send("#{type}_link", match[type]) } }
61
+ end
62
+
63
+ # @return [Hash<Symbol, Regexp>]
62
64
  def reserved_patterns
63
65
  @reserved_patterns ||= {
64
- tms: /@#{CucumberConfig.tms_prefix}(?<tms>\S+)/,
65
- issue: /@#{CucumberConfig.issue_prefix}(?<issue>\S+)/,
66
- severity: /@#{CucumberConfig.severity_prefix}(?<severity>\S+)/,
66
+ tms: /@#{AllureCucumber.configuration.tms_prefix}(?<tms>\S+)/,
67
+ issue: /@#{AllureCucumber.configuration.issue_prefix}(?<issue>\S+)/,
68
+ severity: /@#{AllureCucumber.configuration.severity_prefix}(?<severity>\S+)/,
67
69
  flaky: /@flaky/,
68
70
  muted: /@muted/,
69
71
  known: /@known/,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allure-cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.3
4
+ version: 2.13.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrejs Cunskis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-07 00:00:00.000000000 Z
11
+ date: 2020-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allure-ruby-commons
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 2.13.3
19
+ version: 2.13.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 2.13.3
26
+ version: 2.13.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: cucumber
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '3.1'
33
+ version: 4.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '3.1'
40
+ version: 4.0.0
41
41
  description: Cucumber adaptor to generate rich allure test reports
42
42
  email: andrejs.cunskis@gmail.com
43
43
  executables: []
@@ -46,11 +46,12 @@ extra_rdoc_files: []
46
46
  files:
47
47
  - README.md
48
48
  - lib/allure-cucumber.rb
49
- - lib/allure_cucumber/ast_transformer.rb
50
49
  - lib/allure_cucumber/config.rb
51
- - lib/allure_cucumber/cucumber_model.rb
52
50
  - lib/allure_cucumber/formatter.rb
53
- - lib/allure_cucumber/tag_parser.rb
51
+ - lib/allure_cucumber/models/cucumber_model.rb
52
+ - lib/allure_cucumber/models/scenario.rb
53
+ - lib/allure_cucumber/models/step.rb
54
+ - lib/allure_cucumber/models/tag_parser.rb
54
55
  homepage: https://github.com/allure-framework/allure-ruby
55
56
  licenses:
56
57
  - Apache-2.0
@@ -75,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
76
  - !ruby/object:Gem::Version
76
77
  version: '0'
77
78
  requirements: []
78
- rubygems_version: 3.0.3
79
+ rubygems_version: 3.1.2
79
80
  signing_key:
80
81
  specification_version: 4
81
82
  summary: Allure cucumber ruby adaptor
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AllureCucumber
4
- # Cucumber::Core::Ast is removed in cucumber-core 4.0 version.
5
- # This will have to be updated accordingly, once stable version rolls out
6
- module AstTransformer
7
- # Get scenario object
8
- # @param [Cucumber::Core::Test::Case] test_case
9
- # @return [Cucumber::Core::Ast::Scenario, Cucumber::Core::Ast::ScenarioOutline]
10
- def scenario(test_case)
11
- test_case.source.detect do |it|
12
- it.is_a?(Cucumber::Core::Ast::Scenario) || it.is_a?(Cucumber::Core::Ast::ScenarioOutline)
13
- end
14
- end
15
-
16
- # Get step object
17
- # @param [Cucumber::Core::Test::Step] test_step
18
- # @return [Cucumber::Core::Ast::Step]
19
- def step(test_step)
20
- test_step.source.detect { |it| it.is_a?(Cucumber::Core::Ast::Step) }
21
- end
22
-
23
- # Get scenario outline example row
24
- # @param [Cucumber::Core::Test::Case] test_case
25
- # @return [Cucumber::Core::Ast::ExamplesTable::Row]
26
- def example_row(test_case)
27
- test_case.source.detect { |it| it.is_a?(Cucumber::Core::Ast::ExamplesTable::Row) }
28
- end
29
-
30
- # Get step multiline argument
31
- # @param [Cucumber::Core::Test::Step] test_step
32
- # @return [Cucumber::Core::Ast::DataTable, String]
33
- def multiline_arg(test_step)
34
- multiline_arg = step(test_step).multiline_arg
35
- return if multiline_arg.is_a?(Cucumber::Core::Ast::EmptyMultilineArgument)
36
-
37
- multiline_arg
38
- end
39
- end
40
- end
@@ -1,135 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "cucumber"
4
- require "cucumber/core"
5
- require "digest"
6
- require "csv"
7
-
8
- require_relative "ast_transformer"
9
- require_relative "tag_parser"
10
-
11
- module AllureCucumber
12
- # Support class for transforming cucumber test entities in to allure model entities
13
- module AllureCucumberModel
14
- include AstTransformer
15
- include TagParser
16
-
17
- # Convert to allure test result
18
- # @param [Cucumber::Core::Test::Case] test_case
19
- # @return [TestResult]
20
- def test_result(test_case)
21
- Allure::TestResult.new(
22
- name: test_case.name,
23
- description: description(test_case),
24
- description_html: description(test_case),
25
- history_id: Digest::MD5.hexdigest(test_case.inspect),
26
- full_name: "#{test_case.feature.name}: #{test_case.name}",
27
- labels: labels(test_case),
28
- links: links(test_case),
29
- parameters: parameters(test_case) || [],
30
- status_details: Allure::StatusDetails.new(**status_detail_tags(test_case.tags.map(&:name))),
31
- )
32
- end
33
-
34
- # Convert to allure step result
35
- # @param [Cucumber::Core::Test::Step] test_step
36
- # @return [StepResult]
37
- def step_result(test_step)
38
- Allure::StepResult.new(
39
- name: "#{step(test_step).keyword}#{test_step.text}",
40
- attachments: [multiline_arg_attachment(test_step)].compact,
41
- )
42
- end
43
-
44
- # Convert to allure step result
45
- # @param [Cucumber::Core::Test::Step] test_step
46
- # @return [StepResult]
47
- def fixture_result(test_step)
48
- location = test_step.location.to_s.split("/").last
49
- Allure::FixtureResult.new(name: location)
50
- end
51
-
52
- # Get failure details
53
- # @param [Cucumber::Core::Test::Result] result <description>
54
- # @return [Hash<Symbol, String>]
55
- def failure_details(result)
56
- return { message: result.exception.message, trace: result.exception.backtrace.join("\n") } if result.failed?
57
- return { message: result.message, trace: result.backtrace.join("\n") } if result.undefined?
58
-
59
- {}
60
- end
61
-
62
- # Get thread specific lifecycle
63
- # @return [Allure::AllureLifecycle]
64
- def lifecycle
65
- Allure.lifecycle
66
- end
67
-
68
- private
69
-
70
- # @param [Cucumber::Core::Test::Case] test_case
71
- # @return [Array<Allure::Label>]
72
- def labels(test_case)
73
- labels = []
74
- labels << Allure::ResultUtils.framework_label("cucumber")
75
- labels << Allure::ResultUtils.feature_label(test_case.feature.name)
76
- labels << Allure::ResultUtils.package_label(test_case.feature.name)
77
- labels << Allure::ResultUtils.suite_label(test_case.feature.name)
78
- labels << Allure::ResultUtils.story_label(test_case.name)
79
- labels << Allure::ResultUtils.test_class_label(test_case.name)
80
- unless test_case.tags.empty?
81
- labels.push(*tag_labels(test_case.tags))
82
- labels << severity(test_case.tags)
83
- end
84
-
85
- labels
86
- end
87
-
88
- # @param [Cucumber::Core::Test::Case] test_case
89
- # @return [Array<Allure::Link>]
90
- def links(test_case)
91
- return [] unless test_case.tags
92
-
93
- tms_links(test_case.tags) + issue_links(test_case.tags)
94
- end
95
-
96
- # @param [Cucumber::Core::Test::Case] test_case
97
- # @return [Array<Allure::Parameter>]
98
- def parameters(test_case)
99
- example_row(test_case)&.values&.map { |value| Allure::Parameter.new("argument", value) }
100
- end
101
-
102
- # @param [Cucumber::Core::Test::Case] test_case
103
- # @return [String]
104
- def description(test_case)
105
- scenario = scenario(test_case)
106
- scenario.description.empty? ? "Location - #{scenario.file_colon_line}" : scenario.description.strip
107
- end
108
-
109
- # @param [Cucumber::Core::Test::Step] test_step
110
- # @return [Allure::Attachment]
111
- def multiline_arg_attachment(test_step)
112
- arg = multiline_arg(test_step)
113
- return unless arg
114
-
115
- arg.data_table? ? data_table_attachment(arg) : docstring_attachment(arg)
116
- end
117
-
118
- # @param [Cucumber::Core::Ast::DataTable] multiline_arg
119
- # @return [Allure::Attachment]
120
- def data_table_attachment(multiline_arg)
121
- attachment = lifecycle.prepare_attachment("data-table", Allure::ContentType::CSV)
122
- csv = multiline_arg.raw.each_with_object([]) { |row, arr| arr.push(row.to_csv) }.join("")
123
- lifecycle.write_attachment(csv, attachment)
124
- attachment
125
- end
126
-
127
- # @param [String] multiline_arg
128
- # @return [String]
129
- def docstring_attachment(multiline_arg)
130
- attachment = lifecycle.prepare_attachment("docstring", Allure::ContentType::TXT)
131
- lifecycle.write_attachment(multiline_arg.content, attachment)
132
- attachment
133
- end
134
- end
135
- end