gauge-ruby 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e04db5143c0125740f2adb38e62d1dd57ad9670
4
- data.tar.gz: 14d3f58fdf3e195028b69bc0c7758922cb2a27f8
3
+ metadata.gz: 3d02594acc904fc72ca2ee33b36d035f16a2f7d6
4
+ data.tar.gz: 101648409eacd64b386ee67a779676fb4c7e3d34
5
5
  SHA512:
6
- metadata.gz: eb5ada07b9e706a722b480a17e75f8e88bc17c32e0317e88f2ece1f9cd6b744fdc3199cbfec05159fc7ebe4ba26be5fa68291781b6f892fff1b2692665aa027e
7
- data.tar.gz: 3c11170de25a233e43d309d7eb47bba637a1124a0af38dfa78b2cfc16ec236899badf59ee5d2aa67330fa09244a585c612263183ce71a441b462e08717d45434
6
+ metadata.gz: 4447626f14695ddf0f3ce41562007a4544e4f55451ef0a9d613c83e552f8d1c2c77a04c41021826ae58f31edfb4bbaf18753a4048064d4cb33ed74aabee3012b
7
+ data.tar.gz: 99a5cf6190e7e4ab33736ee3dfd15c7b568a30d6fee44681341c4123664f0ddc91b0fca511f47fd489ba23d9e9a9d3a5074ee452ee9bee82dd42c5c995e54713
data/lib/code_parser.rb CHANGED
@@ -19,6 +19,7 @@ require 'parser/current'
19
19
  require 'method_source'
20
20
  require 'fileutils'
21
21
  require 'tempfile'
22
+ require 'util'
22
23
 
23
24
  module Gauge
24
25
  # @api private
@@ -32,9 +33,13 @@ module Gauge
32
33
  def self.refactor_args(code, param_positions, new_param_values, new_step_text)
33
34
  new_params = []
34
35
  args = step_args_from_code code
35
- param_positions.sort_by!(&:newPosition).each { |e|
36
+ param_positions.sort_by!(&:newPosition).each.with_index { |e,i|
36
37
  if e.oldPosition == -1
37
- new_params[e.newPosition] = "arg_#{new_param_values[e.newPosition].downcase.split.join('_')}"
38
+ param = Util.remove_special_chars new_param_values[e.newPosition].downcase.split.join('_')
39
+ if param == ''
40
+ param = i
41
+ end
42
+ new_params[e.newPosition] = "arg_#{param}"
38
43
  else
39
44
  new_params[e.newPosition] = args[e.oldPosition].children[0]
40
45
  end
@@ -58,8 +63,7 @@ module Gauge
58
63
 
59
64
  def self.refactor(code, param_positions, new_param_values, new_step_text)
60
65
  source_code=code.source
61
- ast = code_to_ast source_code
62
- file, line = code.source_location
66
+ file, _ = code.source_location
63
67
  refactored_code=refactor_args(source_code, param_positions, new_param_values, new_step_text)
64
68
  tmp_file = Tempfile.new File.basename(file, ".rb")
65
69
  tmp_file.write(File.open(file, "r") { |f| f.read.gsub(source_code, refactored_code)})
data/lib/configuration.rb CHANGED
@@ -22,7 +22,8 @@ module Gauge
22
22
  class << self
23
23
  # @api public
24
24
  # Custom configuration for Gauge
25
- # Lets you configure modules that need to be included at runtime.
25
+ # - Lets you configure modules that need to be included at runtime.
26
+ # - Lets you define a custom screengrabber, which will be invoked to capture screenshot on failure.
26
27
  #
27
28
  # @example
28
29
  # # Given there are two modules defined
@@ -37,6 +38,12 @@ module Gauge
37
38
  # Gauge.configure do |config|
38
39
  # config.include Foo, Bar
39
40
  # end
41
+ # @example
42
+ # # Default behaviour is to capture the active desktop at the point of failure.
43
+ # # The implementation should return a byte array of the image.
44
+ # Gauge.configure do |config|
45
+ # config.screengrabber = -> { return File.binread("/path/to/screenshot")}
46
+ # end
40
47
  def configure(&block)
41
48
  Configuration.instance.instance_eval &block
42
49
  end
@@ -46,6 +53,13 @@ module Gauge
46
53
  class Configuration
47
54
  def initialize
48
55
  @includes=[]
56
+ @screengrabber = -> {
57
+ file = File.open("#{Dir.tmpdir}/screenshot.png", "w+")
58
+ `gauge_screenshot #{file.path}`
59
+ file_content = File.binread(file.path)
60
+ File.delete file
61
+ return file_content
62
+ }
49
63
  end
50
64
 
51
65
  def self.instance
@@ -60,6 +74,14 @@ module Gauge
60
74
  @includes
61
75
  end
62
76
 
77
+ def screengrabber
78
+ @screengrabber
79
+ end
80
+
81
+ def screengrabber=(block)
82
+ @screengrabber=block
83
+ end
84
+
63
85
  def self.include_configured_modules
64
86
  # include all modules that have been configured
65
87
  # TODO: move this feature to something more specific, ex look at supporting Sandboxed execution.
data/lib/executor.rb CHANGED
@@ -21,7 +21,13 @@ module Gauge
21
21
  # @api private
22
22
  module Executor
23
23
  def self.load_steps(steps_implementation_dir)
24
- Dir["#{steps_implementation_dir}/**/*.rb"].each { |x| require x }
24
+ Dir["#{steps_implementation_dir}/**/*.rb"].each { |x|
25
+ begin
26
+ require x
27
+ rescue Exception => e
28
+ puts "[ERROR] Cannot import #{x}. Reason: #{e.message}"
29
+ end
30
+ }
25
31
  end
26
32
 
27
33
  def self.execute_step(step, args)
data/lib/gauge.rb CHANGED
@@ -89,13 +89,28 @@ module Kernel
89
89
  # puts x.columns.join("|")
90
90
  # x.rows.each { |r| puts r.join("|") }
91
91
  # end
92
+ # @example
93
+ # # for a given step say
94
+ # # setting :continue_on_failure=>true in implementation will not break on failure of this step
95
+ # # and will continue to execute the next step in the scenario
96
+ # # * say "hello" to "gauge"
97
+ # step 'say <what> to <who>', :continue_on_failure => false do |what, who|
98
+ # puts "say #{what} to #{who}"
99
+ # raise "Some Failure"
100
+ # end
101
+ #
92
102
  # @param step_texts [string, ...] the step text(s)
103
+ # @param opts [Hash] pass :continue_on_failure => true to tell Gauge not to break on failure for this step
93
104
  # @param block [block] the implementation block for given step.
94
- def step(*step_texts, &block)
105
+ def step(*args, &block)
106
+ opts = args.select {|x| x.is_a? Hash}
107
+ step_texts = args-opts
108
+ opts = {:continue_on_failure => false}.merge opts.reduce({}, :merge)
95
109
  step_texts.each do |text|
96
110
  parameterized_step_text = Gauge::Connector.step_value(text)
97
111
  Gauge::MethodCache.add_step(parameterized_step_text, &block)
98
112
  Gauge::MethodCache.add_step_text(parameterized_step_text, text)
113
+ Gauge::MethodCache.set_recoverable(parameterized_step_text) if opts[:continue_on_failure]
99
114
  end
100
115
  Gauge::MethodCache.add_step_alias(*step_texts)
101
116
  end
data/lib/gauge_runtime.rb CHANGED
@@ -74,5 +74,6 @@ module Gauge
74
74
  Connector.make_connections()
75
75
  Executor.load_steps(DEFAULT_IMPLEMENTATIONS_DIR_PATH)
76
76
  dispatch_messages(Connector.executionSocket)
77
+ exit(0)
77
78
  end
78
79
  end
data/lib/messages.pb.rb CHANGED
@@ -157,6 +157,7 @@ module Gauge
157
157
  set_fully_qualified_name "gauge.messages.StepValidateResponse.ErrorType"
158
158
 
159
159
  STEP_IMPLEMENTATION_NOT_FOUND = 0
160
+ DUPLICATE_STEP_IMPLEMENTATION = 1
160
161
  end
161
162
 
162
163
  set_fully_qualified_name "gauge.messages.StepValidateResponse"
data/lib/method_cache.rb CHANGED
@@ -34,11 +34,16 @@ module Gauge
34
34
  end
35
35
 
36
36
  def self.add_step(parameterized_step_text, &block)
37
- @@steps_map[parameterized_step_text] = block
37
+ @@steps_map[parameterized_step_text] = @@steps_map[parameterized_step_text] || []
38
+ @@steps_map[parameterized_step_text].push(block)
38
39
  end
39
40
 
40
41
  def self.get_step(parameterized_step_text)
41
- @@steps_map[parameterized_step_text]
42
+ @@steps_map[parameterized_step_text][0]
43
+ end
44
+
45
+ def self.get_steps(parameterized_step_text)
46
+ @@steps_map[parameterized_step_text] || []
42
47
  end
43
48
 
44
49
  def self.add_step_text(parameterized_step_text, step_text)
@@ -65,10 +70,19 @@ module Gauge
65
70
  @@steps_text_map.values
66
71
  end
67
72
 
73
+ def self.is_recoverable?(parameterized_step_text)
74
+ @@recoverable_steps.include? parameterized_step_text
75
+ end
76
+
77
+ def self.set_recoverable(parameterized_step_text)
78
+ @@recoverable_steps.push parameterized_step_text
79
+ end
80
+
68
81
  private
69
82
  @@steps_map = Hash.new
70
83
  @@steps_text_map = Hash.new
71
84
  @@steps_with_aliases = []
85
+ @@recoverable_steps = []
72
86
  @@before_suite_hooks = []
73
87
  @@after_suite_hooks = []
74
88
  @@before_spec_hooks = []
@@ -29,7 +29,7 @@ module Gauge
29
29
  begin
30
30
  Executor.execute_step step_text, args
31
31
  rescue Exception => e
32
- return handle_failure message, e, time_elapsed_since(start_time)
32
+ return handle_failure message, e, time_elapsed_since(start_time), MethodCache.is_recoverable?(step_text)
33
33
  end
34
34
  handle_pass message, time_elapsed_since(start_time)
35
35
  end
@@ -27,7 +27,7 @@ module Gauge
27
27
  if execution_error == nil
28
28
  return handle_pass message, time_elapsed_since(start_time)
29
29
  else
30
- return handle_failure message, execution_error, time_elapsed_since(start_time)
30
+ return handle_failure message, execution_error, time_elapsed_since(start_time), false
31
31
  end
32
32
  end
33
33
 
@@ -36,11 +36,11 @@ module Gauge
36
36
  Messages::Message.new(:messageType => Messages::Message::MessageType::ExecutionStatusResponse, :messageId => message.messageId, :executionStatusResponse => execution_status_response)
37
37
  end
38
38
 
39
- def handle_failure(message, exception, execution_time)
39
+ def handle_failure(message, exception, execution_time, recoverable)
40
40
  execution_status_response =
41
41
  Messages::ExecutionStatusResponse.new(
42
42
  :executionResult => Messages::ProtoExecutionResult.new(:failed => true,
43
- :recoverableError => false,
43
+ :recoverableError => recoverable,
44
44
  :errorMessage => exception.message,
45
45
  :stackTrace => exception.backtrace.join("\n")+"\n",
46
46
  :executionTime => execution_time,
@@ -51,11 +51,12 @@ module Gauge
51
51
 
52
52
  def screenshot_bytes
53
53
  return nil if (ENV['screenshot_enabled'] || "").downcase == "false" || which("gauge_screenshot").nil?
54
- file = File.open("#{Dir.tmpdir}/screenshot.png", "w+")
55
- `gauge_screenshot #{file.path}`
56
- file_content = File.binread(file.path)
57
- File.delete file
58
- return file_content
54
+ begin
55
+ Configuration.instance.screengrabber.call
56
+ rescue Exception => e
57
+ puts e
58
+ return nil
59
+ end
59
60
  end
60
61
 
61
62
  def time_elapsed_since(start_time)
@@ -85,7 +86,7 @@ module Gauge
85
86
  }
86
87
  end
87
88
  return nil
88
- end
89
+ end
89
90
  end
90
91
  end
91
92
  end
@@ -22,15 +22,23 @@ module Gauge
22
22
  def refactor_step(message)
23
23
  oldStepValue = message.refactorRequest.oldStepValue.stepValue
24
24
  newStep = message.refactorRequest.newStepValue
25
- stepBlock = MethodCache.get_step oldStepValue
26
25
  refactor_response = Messages::RefactorResponse.new(success: true)
27
26
  begin
27
+ stepBlock = get_step oldStepValue
28
28
  CodeParser.refactor stepBlock, message.refactorRequest.paramPositions, newStep.parameters, newStep.parameterizedStepValue
29
+ file, _ = stepBlock.source_location
30
+ refactor_response.filesChanged = [file]
29
31
  rescue Exception => e
30
32
  refactor_response.success=false
31
33
  refactor_response.error=e.message
32
34
  end
33
35
  Messages::Message.new(:messageType => Messages::Message::MessageType::RefactorResponse, :messageId => message.messageId, refactorResponse: refactor_response)
34
36
  end
37
+
38
+ def get_step(step_text)
39
+ blocks = MethodCache.get_steps step_text
40
+ raise "Multiple step implementations found for => '#{step_text}'" if blocks.length > 1
41
+ blocks[0]
42
+ end
35
43
  end
36
44
  end
@@ -19,9 +19,20 @@ module Gauge
19
19
  module Processors
20
20
  def process_step_validation_request(message)
21
21
  step_validate_request = message.stepValidateRequest
22
- is_valid = MethodCache.valid_step?(step_validate_request.stepText)
23
- step_validate_response = Messages::StepValidateResponse.new(:isValid => is_valid,
24
- :errorMessage => is_valid ? "" : "Step implementation not found", :errorType => Messages::StepValidateResponse::ErrorType::STEP_IMPLEMENTATION_NOT_FOUND)
22
+ is_valid = true
23
+ msg = ''
24
+ err_type = nil
25
+ blocks = MethodCache.get_steps(step_validate_request.stepText)
26
+ if blocks.length > 1
27
+ is_valid = false
28
+ msg = "Multiple step implementations found for => '#{step_validate_request.stepText}'"
29
+ err_type = Messages::StepValidateResponse::ErrorType::DUPLICATE_STEP_IMPLEMENTATION
30
+ elsif blocks.length == 0
31
+ is_valid = false
32
+ msg = 'Step implementation not found'
33
+ err_type = Messages::StepValidateResponse::ErrorType::STEP_IMPLEMENTATION_NOT_FOUND
34
+ end
35
+ step_validate_response = Messages::StepValidateResponse.new(:isValid => is_valid, :errorMessage => msg, :errorType => err_type)
25
36
  Messages::Message.new(:messageType => Messages::Message::MessageType::StepValidateResponse,
26
37
  :messageId => message.messageId,
27
38
  :stepValidateResponse => step_validate_response)
data/lib/spec.pb.rb CHANGED
@@ -9,6 +9,7 @@ module Gauge
9
9
  class ProtoSpec < ::ProtocolBuffers::Message; end
10
10
  class ProtoItem < ::ProtocolBuffers::Message; end
11
11
  class ProtoScenario < ::ProtocolBuffers::Message; end
12
+ class Span < ::ProtocolBuffers::Message; end
12
13
  class ProtoTableDrivenScenario < ::ProtocolBuffers::Message; end
13
14
  class ProtoStep < ::ProtocolBuffers::Message; end
14
15
  class ProtoConcept < ::ProtocolBuffers::Message; end
@@ -80,6 +81,16 @@ module Gauge
80
81
  optional :int64, :executionTime, 8
81
82
  required :bool, :skipped, 9
82
83
  repeated :string, :skipErrors, 10
84
+ optional :string, :ID, 11
85
+ repeated ::Gauge::Messages::ProtoItem, :tearDownSteps, 12
86
+ optional ::Gauge::Messages::Span, :span, 13
87
+ end
88
+
89
+ class Span < ::ProtocolBuffers::Message
90
+ set_fully_qualified_name "gauge.messages.Span"
91
+
92
+ required :int64, :start, 1
93
+ required :int64, :end, 2
83
94
  end
84
95
 
85
96
  class ProtoTableDrivenScenario < ::ProtocolBuffers::Message
@@ -185,6 +196,18 @@ module Gauge
185
196
  end
186
197
 
187
198
  class ProtoExecutionResult < ::ProtocolBuffers::Message
199
+ # forward declarations
200
+
201
+ # enums
202
+ module ErrorType
203
+ include ::ProtocolBuffers::Enum
204
+
205
+ set_fully_qualified_name "gauge.messages.ProtoExecutionResult.ErrorType"
206
+
207
+ ASSERTION = 1
208
+ VERIFICATION = 2
209
+ end
210
+
188
211
  set_fully_qualified_name "gauge.messages.ProtoExecutionResult"
189
212
 
190
213
  required :bool, :failed, 1
@@ -194,6 +217,7 @@ module Gauge
194
217
  optional :bytes, :screenShot, 5
195
218
  required :int64, :executionTime, 6
196
219
  repeated :string, :message, 7
220
+ optional ::Gauge::Messages::ProtoExecutionResult::ErrorType, :errorType, 8, :default => ::Gauge::Messages::ProtoExecutionResult::ErrorType::ASSERTION
197
221
  end
198
222
 
199
223
  class ProtoHookFailure < ::ProtocolBuffers::Message
data/lib/table.rb CHANGED
@@ -24,20 +24,18 @@ module Gauge
24
24
  @columns = protoTable.headers.cells
25
25
  @rows = []
26
26
  protoTable.rows.each do |row|
27
- @rows.push row.cells
27
+ @rows.push Row.new(@columns, row.cells)
28
28
  end
29
29
  end
30
30
 
31
31
  # Gets the column headers of the table
32
32
  # @return [string[]]
33
- # @deprecated Use [] accessor instead
34
33
  def columns
35
34
  @columns
36
35
  end
37
36
 
38
37
  # Gets the rows of the table. The rows are two dimensional arrays.
39
38
  # @return [string[][]]
40
- # @deprecated Use {#[]} accessor instead
41
39
  def rows
42
40
  @rows
43
41
  end
@@ -53,18 +51,38 @@ module Gauge
53
51
  # table["Col1"] => ["Row1.Cell1", "Row1.Cell1", ...]
54
52
  # table["Invalid_Col_Name"] => nil
55
53
  def [](index)
56
- return row_values_as_hash(@rows[index]) if index.is_a?(Integer)
54
+ return @rows[index] if index.is_a?(Integer)
57
55
  column_values_as_array(index)
58
56
  end
59
57
 
60
58
  private
61
- def row_values_as_hash(row)
62
- row.nil? ? nil : Hash[@columns.zip(row)]
63
- end
64
59
 
65
60
  def column_values_as_array(col_name)
66
61
  i = @columns.index col_name
67
62
  i.nil? ? nil : @rows.map { |r| r[i] }
68
63
  end
69
64
  end
65
+
66
+ # Holds a row of a table.
67
+ # @api public
68
+ class Row
69
+ # @api private
70
+ def initialize(columns, values)
71
+ @values = values
72
+ @columns = columns
73
+ end
74
+
75
+ # Gets the row cell.
76
+ # @param index Either cell index, or Column name.
77
+ # @return [string] value of the row cell
78
+ # @example
79
+ # row[0] => 'value'
80
+ # row['column'] => 'value'
81
+ # row[i] => nil # when index is out of range
82
+ def [](index)
83
+ return @values[index] if index.is_a?(Integer)
84
+ columns_index = @columns.index(index)
85
+ columns_index.nil? ? nil : @values[columns_index]
86
+ end
87
+ end
70
88
  end
data/lib/util.rb ADDED
@@ -0,0 +1,37 @@
1
+ # Copyright 2015 ThoughtWorks, Inc.
2
+
3
+ # This file is part of Gauge-Ruby.
4
+
5
+ # Gauge-Ruby is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # Gauge-Ruby is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Gauge-Ruby. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Gauge
19
+ class Util
20
+ def self.valid_variable_name?(var_name)
21
+ Object.new.instance_variable_set ('@'+var_name).to_sym, nil
22
+ true
23
+ rescue NameError
24
+ !!(var_name =~ /^[0-9]+$/)
25
+ end
26
+
27
+ def self.remove_special_chars(param)
28
+ new_param = ''
29
+ param.each_char { |c|
30
+ if valid_variable_name? c
31
+ new_param += c
32
+ end
33
+ }
34
+ return new_param
35
+ end
36
+ end
37
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gauge-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gauge Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-15 00:00:00.000000000 Z
11
+ date: 2016-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-protocol-buffers
@@ -96,6 +96,7 @@ files:
96
96
  - lib/processors/step_validation_request_processor.rb
97
97
  - lib/spec.pb.rb
98
98
  - lib/table.rb
99
+ - lib/util.rb
99
100
  homepage: http://www.getgauge.io
100
101
  licenses:
101
102
  - GPL-3.0
@@ -116,8 +117,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  version: '1.9'
117
118
  requirements: []
118
119
  rubyforge_project:
119
- rubygems_version: 2.4.6
120
+ rubygems_version: 2.5.1
120
121
  signing_key:
121
122
  specification_version: 4
122
123
  summary: Ruby support for Gauge
123
124
  test_files: []
125
+ has_rdoc: yard