lopata 0.1.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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