lopata 0.1.1 → 0.1.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.
@@ -2,16 +2,15 @@ module Lopata
2
2
  class SharedStep
3
3
  attr_reader :name, :block
4
4
 
5
- class SharedStepNotFound < StandardError; end
5
+ class NotFound < StandardError; end
6
6
 
7
7
  def self.register(name, &block)
8
8
  raise ArgumentError, "Comma is not allowed in shared step name: '%s'" % name if name =~ /,/
9
- @shared_steps ||= {}
10
- @shared_steps[name] = new(name, &block)
9
+ registry[name] = new(name, &block)
11
10
  end
12
11
 
13
12
  def self.find(name)
14
- @shared_steps[name] or raise StandardError, "Shared step '%s' not found" % name
13
+ registry[name] or raise NotFound, "Shared step '%s' not found" % name
15
14
  end
16
15
 
17
16
  def initialize(name, &block)
@@ -24,8 +23,15 @@ module Lopata
24
23
 
25
24
  def build_steps
26
25
  builder = Lopata::ScenarioBuilder.new(name)
26
+ builder.shared_step = self
27
27
  builder.instance_exec(&block)
28
28
  builder.steps
29
29
  end
30
+
31
+ private
32
+
33
+ def self.registry
34
+ @shared_steps ||= {}
35
+ end
30
36
  end
31
37
  end
@@ -1,69 +1,48 @@
1
1
  module Lopata
2
2
  class Step
3
- attr_reader :block, :status, :exception, :args, :condition
3
+ attr_reader :block, :args, :condition, :method_name, :shared_step
4
+ # metadata overrien by the step.
5
+ attr_accessor :metadata
4
6
 
5
- def initialize(method_name, *args, condition: nil, &block)
7
+ def initialize(method_name, *args, condition: nil, shared_step: nil, &block)
6
8
  @method_name = method_name
7
9
  @args = args
8
- @status = :not_started
9
10
  @block = block
10
- @exception = nil
11
- @condition = condition || Lopata::Condition::EMPTY
12
- end
13
-
14
- def run(scenario)
15
- @status = :running
16
- world.notify_observers(:step_started, self)
17
- begin
18
- run_step(scenario)
19
- @status = :passed
20
- rescue Exception => e
21
- @status = :failed
22
- @exception = e
23
- end
24
- world.notify_observers(:step_finished, self)
25
- end
26
-
27
- def run_step(scenario)
28
- scenario.instance_exec(&block) if block
29
- end
30
-
31
- def world
32
- @world ||= Lopata::Config.world
11
+ @shared_step = shared_step
12
+ @condition = condition
13
+ initialized! if defined? initialized!
33
14
  end
34
15
 
35
- def failed?
36
- status == :failed
16
+ def title
17
+ base_title = args.first
18
+ base_title ||= shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
19
+ base_title
37
20
  end
38
21
 
39
- def passed?
40
- status == :passed
41
- end
42
-
43
- def teardown?
44
- %i{ teardown cleanup }.include?(@method_name)
45
- end
46
-
47
- def pre_steps(scenario)
48
- []
22
+ def execution_steps(scenario, groups: [])
23
+ return [] if condition && !condition.match?(scenario)
24
+ return [] unless block
25
+ [StepExecution.new(self, groups, &block)]
49
26
  end
50
27
  end
51
28
 
52
29
  # Used for action, setup, teardown
53
30
  class ActionStep < Step
54
- def pre_steps(scenario)
31
+ def execution_steps(scenario, groups: [])
55
32
  steps = []
33
+ return steps if condition && !condition.match?(scenario)
56
34
  convert_args(scenario).each do |step|
57
35
  if step.is_a?(String)
58
36
  Lopata::SharedStep.find(step).steps.each do |shared_step|
59
- steps += shared_step.pre_steps(scenario)
60
- steps << shared_step
37
+ next if shared_step.condition && !shared_step.condition.match?(scenario)
38
+ steps += shared_step.execution_steps(scenario, groups: groups)
61
39
  end
62
40
  elsif step.is_a?(Proc)
63
- steps << Lopata::Step.new(method_name, &step)
41
+ steps << StepExecution.new(self, groups, &step)
64
42
  end
65
43
  end
66
- steps
44
+ steps << StepExecution.new(self, groups, &block) if block
45
+ steps.reject { |s| !s.block }
67
46
  end
68
47
 
69
48
  def separate_args(args)
@@ -82,5 +61,125 @@ module Lopata
82
61
  end.flatten
83
62
  end
84
63
 
64
+ def title
65
+ shared_step && "#{method_name.capitalize} #{shared_step.name}" || "Untitled #{method_name}"
66
+ end
67
+ end
68
+
69
+ # Used for context
70
+ class GroupStep < Step
71
+
72
+ def execution_steps(scenario, groups: [])
73
+ steps = []
74
+ return steps if condition && !condition.match?(scenario)
75
+ @steps.each do |step|
76
+ steps += step.execution_steps(scenario, groups: groups + [self])
77
+ end
78
+ steps.reject! { |s| !s.block }
79
+ steps.reject { |s| s.teardown_group?(self) } + steps.select { |s| s.teardown_group?(self) }
80
+ end
81
+
82
+ def let_methods
83
+ @let_methods ||= {}
84
+ end
85
+
86
+ private
87
+
88
+ # Group step's block is a block in context of builder, not scenario. So hide the @block to not be used in scenario.
89
+ def initialized!
90
+ builder = Lopata::ScenarioBuilder.new(title)
91
+ builder.instance_exec(&@block)
92
+ @steps = builder.steps
93
+ @block = nil
94
+ end
95
+ end
96
+
97
+ class StepExecution
98
+ attr_reader :step, :status, :exception, :block, :pending_message, :groups
99
+ extend Forwardable
100
+ def_delegators :step, :method_name
101
+
102
+ class PendingStepFixedError < StandardError; end
103
+
104
+ def initialize(step, groups, &block)
105
+ @step = step
106
+ @status = :not_runned
107
+ @exception = nil
108
+ @block = block
109
+ @groups = groups
110
+ end
111
+
112
+ def title
113
+ group_title = groups.map { |g| "#{g.title}: " }.join
114
+ "#{group_title}#{step.title}"
115
+ end
116
+
117
+ def run(scenario)
118
+ @status = :running
119
+ begin
120
+ run_step(scenario)
121
+ if pending?
122
+ @status = :failed
123
+ raise PendingStepFixedError, 'Expected step to fail since it is pending, but it passed.'
124
+ else
125
+ @status = :passed
126
+ end
127
+ rescue Exception => e
128
+ @status = :failed unless pending?
129
+ @exception = e
130
+ end
131
+ end
132
+
133
+ def run_step(scenario)
134
+ return unless block
135
+ scenario.instance_exec(&block)
136
+ end
137
+
138
+ def failed?
139
+ status == :failed
140
+ end
141
+
142
+ def passed?
143
+ status == :passed
144
+ end
145
+
146
+ def skipped?
147
+ status == :skipped
148
+ end
149
+
150
+ def skip!
151
+ @status = :skipped
152
+ end
153
+
154
+ def pending?
155
+ status == :pending
156
+ end
157
+
158
+ def pending!(message = nil)
159
+ @status = :pending
160
+ @pending_message = message
161
+ end
162
+
163
+ def teardown?
164
+ %i{ teardown cleanup }.include?(method_name)
165
+ end
166
+
167
+ def teardown_group?(group = nil)
168
+ teardown? && self.groups.last == group
169
+ end
170
+
171
+ def skip_rest_on_failure?
172
+ %i{ setup action }.include?(method_name)
173
+ end
174
+
175
+ # Step metadata is a combination of metadata given for step and all contexts (groups) the step included
176
+ def metadata
177
+ (groups + [step]).compact.inject({}) { |merged, part| merged.merge(part.metadata) }
178
+ end
179
+
180
+ # Step methods is a combination of let_methods for all contexts (group) the step included
181
+ def let_methods
182
+ (groups).compact.inject({}) { |merged, part| merged.merge(part.let_methods) }
183
+ end
85
184
  end
86
- end
185
+ end
@@ -1,5 +1,5 @@
1
1
  module Lopata
2
2
  module Version
3
- STRING = '0.1.1'
3
+ STRING = '0.1.6'
4
4
  end
5
5
  end
@@ -22,8 +22,10 @@ class Lopata::World
22
22
  end
23
23
  end
24
24
 
25
+ private
26
+
25
27
  # Define observers based on configuration
26
28
  def observers
27
- @observers ||= [Lopata::Observers::ConsoleOutputObserver.new]
29
+ Lopata.configuration.observers
28
30
  end
29
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lopata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Volochnev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-14 00:00:00.000000000 Z
11
+ date: 2020-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.0'
83
- description: Functional acceptance tesging
83
+ description: Functional acceptance testing
84
84
  email: alexey.volochnev@gmail.com
85
85
  executables:
86
86
  - lopata
@@ -90,24 +90,24 @@ files:
90
90
  - README.md
91
91
  - exe/lopata
92
92
  - lib/lopata.rb
93
+ - lib/lopata/active_record.rb
93
94
  - lib/lopata/condition.rb
94
- - lib/lopata/config.rb
95
+ - lib/lopata/configuration.rb
96
+ - lib/lopata/environment.rb
97
+ - lib/lopata/factory_bot.rb
95
98
  - lib/lopata/generators/app.rb
96
- - lib/lopata/generators/templates/.rspec
97
99
  - lib/lopata/generators/templates/Gemfile
98
100
  - lib/lopata/generators/templates/Lopatafile
99
101
  - lib/lopata/generators/templates/config/environments/qa.yml
100
102
  - lib/lopata/generators/templates/config/initializers/capybara.rb
101
- - lib/lopata/generators/templates/spec/spec_helper.rb
102
103
  - lib/lopata/id.rb
103
104
  - lib/lopata/loader.rb
104
105
  - lib/lopata/observers.rb
106
+ - lib/lopata/observers/backtrace_formatter.rb
105
107
  - lib/lopata/observers/base_observer.rb
106
108
  - lib/lopata/observers/console_output_observer.rb
107
109
  - lib/lopata/observers/web_logger.rb
108
- - lib/lopata/rspec/ar_dsl.rb
109
- - lib/lopata/rspec/dsl.rb
110
- - lib/lopata/rspec/role.rb
110
+ - lib/lopata/role.rb
111
111
  - lib/lopata/runner.rb
112
112
  - lib/lopata/scenario.rb
113
113
  - lib/lopata/scenario_builder.rb
@@ -137,5 +137,5 @@ requirements: []
137
137
  rubygems_version: 3.0.3
138
138
  signing_key:
139
139
  specification_version: 4
140
- summary: lopata-0.1.1
140
+ summary: lopata-0.1.6
141
141
  test_files: []
@@ -1,101 +0,0 @@
1
- module Lopata
2
- module Config
3
- extend self
4
-
5
- attr_accessor :build_number, :lopata_host, :lopata_code, :only_roles, :role_descriptions, :after_as,
6
- :default_role, :ops, :after_scenario
7
-
8
- def init(env)
9
- require 'yaml'
10
- @config = {}
11
- config_filename = "./config/environments/#{env}.yml"
12
- @config = YAML::load(File.open(config_filename)) if File.exists?(config_filename)
13
- init_db
14
- @role_descriptions ||= {}
15
- # init_includes
16
- end
17
-
18
- def [](key)
19
- @config[key]
20
- end
21
-
22
- %w{url name readonly}.each do |opt|
23
- define_method opt do
24
- raise "Lopata::Config unititlalized, use Lopata::Config#init(env) to set environment" unless @config
25
- @config[opt]
26
- end
27
- end
28
-
29
- def init_db
30
- ActiveRecord::Base.establish_connection(@config['db']) if @config['db']
31
- end
32
-
33
- def init_rspec
34
- require 'lopata/rspec/dsl'
35
- require 'lopata/rspec/role'
36
- ::RSpec.configure do |c|
37
- c.include Lopata::RSpec::DSL
38
- c.include Lopata::RSpec::Role
39
- end
40
- init_rspec_filters
41
- end
42
-
43
- def init_active_record
44
- require 'lopata/rspec/ar_dsl'
45
- ::RSpec.configure do |c|
46
- c.include Lopata::RSpec::AR::DSL
47
- end
48
- end
49
-
50
- def init_lopata_logging(build)
51
- self.build_number = build
52
- require 'lopata/observers/web_logger'
53
- add_observer Lopata::Observers::WebLogger.new
54
- end
55
-
56
- def init_rerun
57
- ::RSpec.configure do |c|
58
- c.inclusion_filter = { full_description: build_rerun_filter_proc }
59
- end
60
- end
61
-
62
- def init_rspec_filters
63
- filters = {}
64
- filters[:focus] = true if ops[:focus]
65
- if ops[:rerun]
66
- filters[:full_description] = build_rerun_filter_proc
67
- end
68
- if ops[:text]
69
- filters[:full_description] = ->(desc) { desc.include?(ops[:text]) }
70
- end
71
- unless filters.blank?
72
- ::RSpec.configure do |c|
73
- c.inclusion_filter = filters
74
- end
75
- end
76
- end
77
-
78
- def build_rerun_filter_proc
79
- to_rerun = Lopata::Client.new(Lopata::Config.build_number).to_rerun
80
- Proc.new do |desc|
81
- to_rerun.include?(desc)
82
- end
83
- end
84
-
85
- def before_start(&block)
86
- @before_start = block
87
- end
88
-
89
- def initialize_test
90
- @before_start.call if @before_start
91
- end
92
-
93
- def world
94
- @world ||= Lopata::World.new
95
- end
96
-
97
- def add_observer(observer)
98
- world.observers << observer
99
- end
100
- end
101
- end
@@ -1,3 +0,0 @@
1
- --color
2
- --format documentation
3
- --require spec_helper
@@ -1,2 +0,0 @@
1
- Lopata::Config.role_descriptions = { user: 'User' }
2
- Lopata::Config.default_role = :user
@@ -1,38 +0,0 @@
1
- module Lopata
2
- module RSpec
3
- module AR
4
- module DSL
5
- def self.included(base)
6
- base.extend(ClassMethods)
7
- end
8
-
9
- def cleanup(*objects)
10
- return if Lopata::Config.ops[:keep]
11
- objects.flatten.compact.each do |o|
12
- begin
13
- o.reload.destroy!
14
- rescue ActiveRecord::RecordNotFound
15
- # Already destroyed
16
- end
17
- end
18
- end
19
-
20
- def reload(*objects)
21
- objects.flatten.each(&:reload)
22
- end
23
-
24
-
25
- module ClassMethods
26
- def cleanup(*vars, &block)
27
- unless vars.empty?
28
- teardown do
29
- cleanup vars.map { |v| instance_variable_get "@#{v}" }
30
- end
31
- end
32
- teardown &block if block_given?
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end