lopata 0.1.6 → 0.1.7

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: 51ff4a162c7617388f8856b342449e1475f2438d8a44a6c58c6168373b144969
4
- data.tar.gz: 10580190d2a63826f971d1730523eacc34ed818b634329da1635db07d2627d27
3
+ metadata.gz: 7f4b4814d88cd3b9da3a34159e3c1c977d05cbb0504d3dc0b2ab8034044dfbf0
4
+ data.tar.gz: 378e5a3c346c64cb4430577dcfab31cfefd54a2c8e8ee30046609cf10e1bdba4
5
5
  SHA512:
6
- metadata.gz: 76f4fffc7d6755eb63d45a3297177c25b2e947c101dfad38b7a39e8bb474f00e3874d3b3fcf939a81d3ad550cc7d18335ac998104f0b0436db239d1f4688a0f5
7
- data.tar.gz: '086e6cb580e94035e78607daa4a5ba6a5caf2211e37bc0e5cd9aa7cb1e2579fc22889e6fb90e17e6b4f290016a70d76f86d1d93d307d19e964b7584a3bee0451'
6
+ metadata.gz: ff0498d9c9b665d52f5a8d1e65cdc6dc9078f0df1cd4f7fd831393af04ee564a5cf9a9f55305bd4423ff92062cdb7fd4a728bb2be657f196f91447faddffa941
7
+ data.tar.gz: 063a3914c5e5dd088ad56e37ea527c540e8dc82f0d56e7dca4564e61699541000e4d801a80898b2d89eb6719cfd4d1a887d3884a52335f0e6339ffc9a91569fb
@@ -0,0 +1 @@
1
+ --no-private
@@ -6,6 +6,7 @@ require 'lopata/scenario'
6
6
  require 'lopata/step'
7
7
  require 'lopata/shared_step'
8
8
 
9
+ # Namespace for all Lopata code.
9
10
  module Lopata
10
11
  # Define the scenario.
11
12
  # @see Lopata::ScenarioBuilder.define
@@ -34,7 +35,7 @@ module Lopata
34
35
  # end
35
36
  # end
36
37
  # @param name [String] shared step unique name
37
- # @param block shared step action sequence definition
38
+ # @param block [Block] shared step action sequence definition
38
39
  def self.shared_step(name, &block)
39
40
  Lopata::SharedStep.register(name, &block)
40
41
  end
@@ -71,6 +71,39 @@ module Lopata
71
71
  def reload(*objects)
72
72
  objects.flatten.compact.each(&:reload)
73
73
  end
74
+
75
+ # Marks object to be destroyed at the end of scenario
76
+ #
77
+ # @param object [ActiveRecord::Base] the object to be destoryed at the end of scenario
78
+ # @return the given object, so chains can be build
79
+ def cleanup_later(object)
80
+ return nil unless object
81
+ @created_objects ||= []
82
+ @created_objects << object
83
+ object
84
+ end
85
+
86
+ # Find ActiveRecord object of given class by params.
87
+ # Marks the returned object to be destroyed at the end of scenario.
88
+ #
89
+ # @example
90
+ # action do
91
+ # # UI actions creating the user
92
+ # @user = find_created(User, username: 'testuser')
93
+ # end
94
+ # it 'created' do
95
+ # expect(@user).to_not be_nil
96
+ # end
97
+ # # No cleanup needed
98
+ # # cleanup :user
99
+ #
100
+ # @param cls [Class] active record model class
101
+ # @param params [Hash] options for record finding
102
+ # @return [ActiveRecord::Base, nil] the object or nil if not found
103
+ # @see #cleanup_later called on the hood
104
+ def find_created(cls, params)
105
+ cleanup_later cls.where(params).take
106
+ end
74
107
  end
75
108
 
76
109
  # To be included in Lopata::ScenarioBuilder. The methods may be used in build time.
@@ -92,6 +125,10 @@ module Lopata
92
125
  end
93
126
  end
94
127
 
128
+ Lopata.configure do |c|
129
+ c.after_scenario { cleanup @created_objects }
130
+ end
131
+
95
132
  params = Lopata.environment['db']
96
133
  ActiveRecord::Base.establish_connection(params) if params
97
134
 
@@ -1,23 +1,63 @@
1
1
  require_relative 'active_record'
2
2
 
3
3
  module Lopata
4
+ # Helpers for FactoryBot usage in tests.
5
+ #
6
+ # Make helpers available in scenarios by
7
+ #
8
+ # require 'lopata/factory_bot'
9
+ #
10
+ # Automatically adds ActiveRecord helpers.
11
+ # @see Lopata::ActiveRecord
12
+ #
13
+ # Allows to create ActiveRecord object by FactoryBot definitions.
14
+ # All the objects created by FactoryBot helpers will be destroyed automatically
15
+ # at the end of scenario.
16
+ # @see Lopata::ActiveRecord::Methods#cleanup
17
+ #
18
+ # @example
19
+ #
20
+ # # Configure db connection at config/environments/qa.yml like rails:
21
+ # # db:
22
+ # # adapter: postgresql
23
+ # # host: your.database.host
24
+ # # username: username
25
+ # # password: password
26
+ # # database: database
27
+ # require 'active_record'
28
+ # require 'factory_bot'
29
+ # require 'lopata/facotory_bot'
30
+ #
31
+ # class User < ActiveRecord::Base; end
32
+ #
33
+ # FactoryBot.define do
34
+ # factory :user do
35
+ # username { 'testuser' }
36
+ # end
37
+ # end
38
+ #
39
+ # Lopata.define 'User creation' do
40
+ # setup do
41
+ # @user = create(:user)
42
+ # end
43
+ # # No cleanup needed - @user will be destroyed automatically
44
+ # # cleanup :user
45
+ #
46
+ # it 'works' do
47
+ # expect(@user).to_not be_nil
48
+ # end
49
+ # end
50
+ #
4
51
  module FactoryBot
5
52
  # To be included in Lopata::Scenario
6
53
  module Methods
54
+ # Wrapper for FactoryBot#create
55
+ # Calls the FactoryBot#create with given paramters and returns it result.
56
+ # Additionally store the created object for destroying at the end of scenario.
57
+ # @see Lopata::ActiveRecord::Methods#cleanup
7
58
  def create(*params)
8
59
  cleanup_later ::FactoryBot.create(*params)
9
60
  end
10
-
11
- def find_created(cls, params)
12
- cleanup_later cls.where(params).take
13
- end
14
-
15
- def cleanup_later(object)
16
- return nil unless object
17
- @created_objects ||= []
18
- @created_objects << object
19
- object
20
- end
21
61
  end
22
62
 
23
63
  # To be included in Lopata::ScenarioBuilder
@@ -29,8 +69,4 @@ end
29
69
  Lopata::Scenario.include Lopata::FactoryBot::Methods
30
70
  Lopata::ScenarioBuilder.include Lopata::FactoryBot::DSL
31
71
 
32
- Lopata.configure do |c|
33
- c.after_scenario { cleanup @created_objects }
34
- end
35
-
36
72
  ::FactoryBot.find_definitions
@@ -1,5 +1,7 @@
1
1
  module Lopata
2
+ # @private
2
3
  module Generators
4
+ # @private
3
5
  class App < Thor::Group
4
6
  include Thor::Actions
5
7
  argument :name
@@ -1,4 +1,5 @@
1
1
  module Lopata
2
+ # @private
2
3
  module Id
3
4
  extend self
4
5
 
@@ -1,3 +1,4 @@
1
+ # @private
1
2
  module Lopata::Loader
2
3
  extend self
3
4
 
@@ -20,6 +21,7 @@ module Lopata::Loader
20
21
  Dir["scenarios/**/*.rb"].each { |f| load File.expand_path(f) }
21
22
  end
22
23
 
24
+ # Loads all shared steps from predefined paths
23
25
  def load_shared_steps
24
26
  Dir["shared_steps/**/*rb"].each { |f| load File.expand_path(f) }
25
27
  end
@@ -1,3 +1,4 @@
1
+ # @private
1
2
  module Lopata::Observers
2
3
  autoload :BaseObserver, 'lopata/observers/base_observer.rb'
3
4
  autoload :ConsoleOutputObserver, 'lopata/observers/console_output_observer.rb'
@@ -39,7 +39,7 @@ module Lopata
39
39
 
40
40
  # Extracts error message from excetion
41
41
  #
42
- # @param exeption [Exception]
42
+ # @param exception [Exception]
43
43
  # @param include_backtrace [Boolean] whether to add formatted backtrace to output
44
44
  # @return [String] error message from excetion, incuding source code line.
45
45
  def error_message(exception, include_backtrace: false)
@@ -21,12 +21,12 @@ module Lopata
21
21
  end
22
22
 
23
23
  # Called before single scenario execution.
24
- # @param world [Lopata::Scenario::Execution]
24
+ # @param scenario [Lopata::Scenario::Execution]
25
25
  def scenario_started(scenario)
26
26
  end
27
27
 
28
28
  # Called after single scenario execution.
29
- # @param world [Lopata::Scenario::Execution]
29
+ # @param scenario [Lopata::Scenario::Execution]
30
30
  def scenario_finished(scenario)
31
31
  end
32
32
  end
@@ -19,9 +19,13 @@ module Lopata
19
19
  end
20
20
  end
21
21
 
22
+ # @private
22
23
  PASSED = 0
24
+ # @private
23
25
  FAILED = 1
26
+ # @private
24
27
  PENDING = 2
28
+ # @private
25
29
  SKIPPED = 5
26
30
 
27
31
  # @private
@@ -1,9 +1,33 @@
1
1
  module Lopata
2
+ # Adds ability to run scenarios by given user roles
3
+ #
4
+ # @example Usage
5
+ # require 'lopata/role'
6
+ # Lopata.configure do |c|
7
+ # c.role_descriptions = {
8
+ # user: 'User',
9
+ # admin: 'Admin'
10
+ # }
11
+ # c.default_role = :user
12
+ # c.before_scenaro 'setup user'
13
+ # end
14
+ # Lopata.shared_step 'setup user' do
15
+ # setup { @user = User.create(role: current_role) if current_role }
16
+ # cleanup :user
17
+ # end
18
+ # Lopata.define 'login' do
19
+ # # will generate 2 scenarios, one for :user and one for :admin
20
+ # as :user, :admin
21
+ # action 'login'
22
+ # # verify the user is logged in
23
+ # end
24
+ #
2
25
  # @see Lopata::Configuration#role_descriptions
3
26
  # @see Lopata::Configuration#default_role
4
27
  module Role
5
28
  # To be included in Lopata::Scenario
6
29
  module Methods
30
+ # @return [Symbol, nil] user role for current scenario or nil, if scenario is running without user.
7
31
  def current_role
8
32
  metadata[:as]
9
33
  end
@@ -11,30 +35,50 @@ module Lopata
11
35
 
12
36
  # To be included in Lopata::ScenarioBuilder
13
37
  module DSL
38
+ # Enumerate the roles the scenario to be runned under.
39
+ # If not invoked the default role only will be used.
40
+ #
41
+ # The scenario should be set to use the role via before_scenario step using #current_role param.
42
+ #
43
+ # @param args [Array<Symbol>] list of roles the scenario to be runned with.
44
+ # @param block [Block] the block to calculate role from scenario metadata.
14
45
  def as(*args, &block)
15
46
  @roles = args.flatten
16
47
  @roles << Lopata::ScenarioBuilder::CalculatedValue.new(&block) if block_given?
17
48
  @role_options = nil
18
49
  end
19
50
 
51
+ # @private
20
52
  def role_options
21
53
  @role_options ||= build_role_options
22
54
  end
23
55
 
56
+ # Marks scenario to be runned without user.
57
+ #
58
+ # @example
59
+ # Lopata.define 'scenario withou user' do
60
+ # without_user
61
+ # it 'does not define the user' do
62
+ # expect(current_role).to be_nil
63
+ # end
64
+ # end
24
65
  def without_user
25
66
  @without_user = true
26
67
  end
27
68
 
69
+ # @private
28
70
  def build_role_options
29
71
  return [] unless roles
30
72
  [Lopata::ScenarioBuilder::Diagonal.new(:as, roles.map { |r| [Lopata.configuration.role_descriptions[r], r] })]
31
73
  end
32
74
 
75
+ # @private
33
76
  def roles
34
77
  return false if @without_user
35
78
  @roles ||= [Lopata.configuration.default_role].compact
36
79
  end
37
80
 
81
+ # @private
38
82
  def diagonals
39
83
  super + role_options
40
84
  end
@@ -43,4 +87,5 @@ module Lopata
43
87
  end
44
88
 
45
89
  Lopata::Scenario.include Lopata::Role::Methods
90
+ # Prepend the module to overload #diagonals method
46
91
  Lopata::ScenarioBuilder.prepend Lopata::Role::DSL
@@ -7,6 +7,7 @@ require_relative 'observers'
7
7
  require_relative 'condition'
8
8
 
9
9
  module Lopata
10
+ # @private
10
11
  class Runner < Thor
11
12
  desc 'test', 'Run tests'
12
13
  option :env, default: :qa, aliases: 'e'
@@ -14,13 +15,14 @@ module Lopata
14
15
  option :keep, type: :boolean, aliases: 'k'
15
16
  option :text, aliases: 't'
16
17
  def test(*args)
18
+ trap_interrupt
17
19
  configure_from_options
18
20
  Lopata::Loader.load_shared_steps
19
21
  Lopata::Loader.load_scenarios(*args)
20
22
  world = Lopata.world
21
- world.start
23
+ world.notify_observers(:started, world)
22
24
  world.scenarios.each { |s| s.run }
23
- world.finish
25
+ world.notify_observers(:finished, world)
24
26
  end
25
27
 
26
28
  default_task :test
@@ -51,6 +53,10 @@ module Lopata
51
53
  to_rerun = Lopata::Client.new.to_rerun
52
54
  Lopata.configuration.filters << -> (scenario) { to_rerun.include?(scenario.title) }
53
55
  end
56
+
57
+ def trap_interrupt
58
+ trap('INT') { exit!(1) }
59
+ end
54
60
  end
55
61
  end
56
62
  end
@@ -1,25 +1,41 @@
1
1
  require 'rspec/expectations'
2
2
 
3
+ # Scenario runtime class.
4
+ #
5
+ # All the scenarios are running in context of separate Lopata::Scenario object.
6
+ #
3
7
  class Lopata::Scenario
4
8
  include RSpec::Matchers
5
9
 
10
+ # @private
6
11
  attr_reader :execution
7
12
 
13
+ # @private
8
14
  def initialize(execution)
9
15
  @execution = execution
10
16
  end
11
17
 
12
18
  # Marks current step as pending
19
+ # @example
20
+ # it 'pending step' do
21
+ # pending
22
+ # expect(1).to eq 2
23
+ # end
24
+ #
25
+ # Pending steps wont be failed
13
26
  def pending(message = nil)
14
27
  execution.current_step.pending!(message)
15
28
  end
16
29
 
30
+ # @return [Hash] metadata available for current step
31
+ # @note The metadata keys also availalbe as methods (via method_missing)
17
32
  def metadata
18
33
  execution.metadata
19
34
  end
20
35
 
21
36
  private
22
37
 
38
+ # @private
23
39
  def method_missing(method, *args, &block)
24
40
  if execution.let_methods.include?(method)
25
41
  instance_exec(*args, &execution.let_methods[method])
@@ -30,10 +46,13 @@ class Lopata::Scenario
30
46
  end
31
47
  end
32
48
 
49
+ # @private
33
50
  def respond_to_missing?(method, *)
34
51
  execution.let_methods.include?(method) or metadata.keys.include?(method) or super
35
52
  end
36
53
 
54
+ # @private
55
+ # Scenario execution and live-cycle information
37
56
  class Execution
38
57
  attr_reader :scenario, :status, :steps, :title, :current_step
39
58
 
@@ -1,19 +1,39 @@
1
+ # Context for scenario creation.
1
2
  class Lopata::ScenarioBuilder
3
+ # @private
2
4
  attr_reader :title, :common_metadata, :options, :diagonals
5
+ # @private
3
6
  attr_accessor :shared_step, :group
4
7
 
8
+ # Defines one or more scenarios.
9
+ #
10
+ # @example
11
+ # Lopata.define 'scenario' do
12
+ # setup 'test user'
13
+ # action 'login'
14
+ # verify 'home page displayed'
15
+ # end
16
+ #
17
+ # Given block will be calculated in context of the ScenarioBuilder
18
+ #
19
+ # @param title [String] scenario unique title
20
+ # @param metadata [Hash] metadata to be used within the scenario
21
+ # @param block [Block] the scenario definition
22
+ # @see Lopata.define
5
23
  def self.define(title, metadata = {}, &block)
6
24
  builder = new(title, metadata)
7
25
  builder.instance_exec &block
8
26
  builder.build
9
27
  end
10
28
 
29
+ # @private
11
30
  def initialize(title, metadata = {})
12
31
  @title, @common_metadata = title, metadata
13
32
  @diagonals = []
14
33
  @options = []
15
34
  end
16
35
 
36
+ # @private
17
37
  def build
18
38
  filters = Lopata.configuration.filters
19
39
  option_combinations.each do |option_set|
@@ -33,21 +53,104 @@ class Lopata::ScenarioBuilder
33
53
  end
34
54
  end
35
55
 
56
+ # @!group Defining variants
57
+
58
+ # Define option for the scenario.
59
+ #
60
+ # The scenario will be generated for all the options.
61
+ # If more then one option given, the scenarios for all options combinations will be generated.
62
+ #
63
+ # @param metadata_key [Symbol] the key to access option data via metadata.
64
+ # @param variants [Hash{String => Object}] variants for the option
65
+ # Keys are titles of the variant, values are metadata values.
66
+ #
67
+ # @example
68
+ # Lopata.define 'scenario' do
69
+ # option :one, 'one' => 1, 'two' => 2
70
+ # option :two, 'two' => 2, 'three' => 3
71
+ # # will generate 4 scenarios:
72
+ # # - 'scenario one two'
73
+ # # - 'scenario one three'
74
+ # # - 'scenario two two'
75
+ # # - 'scenario two three'
76
+ # end
77
+ #
78
+ # @see #diagonal
79
+ def option(metadata_key, variants)
80
+ @options << Option.new(metadata_key, variants)
81
+ end
82
+
83
+ # Define diagonal for the scenario.
84
+ #
85
+ # The scenario will be generated for all the variants of the diagonal.
86
+ # Each variant of diagonal will be selected for at least one scenario.
87
+ # It may be included in more then one scenario when other diagonal or option has more variants.
88
+ #
89
+ # @param metadata_key [Symbol] the key to access diagonal data via metadata.
90
+ # @param variants [Hash{String => Object}] variants for the diagonal.
91
+ # Keys are titles of the variant, values are metadata values.
92
+ #
93
+ # @example
94
+ # Lopata.define 'scenario' do
95
+ # option :one, 'one' => 1, 'two' => 2
96
+ # diagonal :two, 'two' => 2, 'three' => 3
97
+ # diagonal :three, 'three' => 3, 'four' => 4, 'five' => 5
98
+ # # will generate 3 scenarios:
99
+ # # - 'scenario one two three'
100
+ # # - 'scenario two three four'
101
+ # # - 'scenario one two five'
102
+ # end
103
+ #
104
+ # @see #option
105
+ def diagonal(metadata_key, variants)
106
+ @diagonals << Diagonal.new(metadata_key, variants)
107
+ end
108
+
109
+ # Define additional metadata for the scenario
110
+ #
111
+ # @example
112
+ # Lopata.define 'scenario' do
113
+ # metadata key: 'value'
114
+ # it 'metadata available' do
115
+ # expect(metadata[:key]).to eq 'value'
116
+ # end
117
+ # end
36
118
  def metadata(hash)
37
119
  raise 'metadata expected to be a Hash' unless hash.is_a?(Hash)
38
120
  @common_metadata ||= {}
39
121
  @common_metadata.merge! hash
40
122
  end
41
123
 
124
+ # Skip scenario for given variants combination
125
+ #
126
+ # @example
127
+ # Lopata.define 'multiple options' do
128
+ # option :one, 'one' => 1, 'two' => 2
129
+ # option :two, 'two' => 2, 'three' => 3
130
+ # skip_when { |opt| opt.metadata[:one] == opt.metadata[:two] }
131
+ # it 'not equal' do
132
+ # expect(one).to_not eq two
133
+ # end
134
+ # end
135
+ #
42
136
  def skip_when(&block)
43
137
  @skip_when = block
44
138
  end
45
139
 
140
+ # @private
46
141
  def skip?(option_set)
47
142
  @skip_when && @skip_when.call(option_set)
48
143
  end
49
144
 
50
- %i{ setup action it teardown verify context }.each do |name|
145
+ # @!endgroup
146
+
147
+ # @!group Defining Steps
148
+
149
+ # @private
150
+ # @macro [attach] define_step_method
151
+ # @!scope instance
152
+ # @method $1
153
+ def self.define_step_method(name)
51
154
  name_if = "%s_if" % name
52
155
  name_unless = "%s_unless" % name
53
156
  define_method name, ->(*args, **metadata, &block) { add_step(name, *args, metadata: metadata, &block) }
@@ -59,6 +162,124 @@ class Lopata::ScenarioBuilder
59
162
  }
60
163
  end
61
164
 
165
+ # Define setup step.
166
+ # @example
167
+ # setup do
168
+ # end
169
+ #
170
+ # # setup from named shared step
171
+ # setup 'create user'
172
+ #
173
+ # # setup with both shared step and code block
174
+ # setup 'create user' do
175
+ # @user.update(admin: true)
176
+ # end
177
+ #
178
+ # Setup step used for set test data.
179
+ # @overload setup(*steps, &block)
180
+ # @param steps [Array<String, Symbol, Proc>] the steps to be runned as a part of setup.
181
+ # String - name of shared step to be called.
182
+ # Symbol - metadata key, referenced to shared step name.
183
+ # Proc - in-place step implementation.
184
+ # @param block [Block] The implementation of the step.
185
+ define_step_method :setup
186
+
187
+ # Define action step.
188
+ # @example
189
+ # action do
190
+ # end
191
+ #
192
+ # # action from named shared step
193
+ # action 'login'
194
+ #
195
+ # # setup with both shared step and code block
196
+ # action 'login', 'go dashboard' do
197
+ # @user.update(admin: true)
198
+ # end
199
+ #
200
+ # Action step is used for emulate user or external system action
201
+ #
202
+ # @overload action(*steps, &block)
203
+ # @param steps [Array<String, Symbol, Proc>] the steps to be runned as a part of action.
204
+ # String - name of shared step to be called.
205
+ # Symbol - metadata key, referenced to shared step name.
206
+ # Proc - in-place step implementation.
207
+ # @param block [Block] The implementation of the step.
208
+ define_step_method :action
209
+
210
+ # Define teardown step.
211
+ # @example
212
+ # setup { @user = User.create! }
213
+ # teardown { @user.destroy }
214
+ # Teardown step will be called at the end of scenario running.
215
+ # But it suggested to be decared right after setup or action step which require teardown.
216
+ #
217
+ # @overload teardown(*steps, &block)
218
+ # @param steps [Array<String, Symbol, Proc>] the steps to be runned as a part of teardown.
219
+ # String - name of shared step to be called.
220
+ # Symbol - metadata key, referenced to shared step name.
221
+ # Proc - in-place step implementation.
222
+ # @param block [Block] The implementation of the step.
223
+ define_step_method :teardown
224
+
225
+ # Define verify steps.
226
+ # @example
227
+ # verify 'home page displayed' # call shared step.
228
+ # Usually for validation shared steps inclusion
229
+ #
230
+ # @overload verify(*steps, &block)
231
+ # @param steps [Array<String, Symbol, Proc>] the steps to be runned as a part of verification.
232
+ # String - name of shared step to be called.
233
+ # Symbol - metadata key, referenced to shared step name.
234
+ # Proc - in-place step implementation.
235
+ # @param block [Block] The implementation of the step.
236
+ define_step_method :verify
237
+
238
+ # Define group of steps.
239
+ # The metadata for the group may be overriden
240
+ # @example
241
+ # context 'the task', task: :created do
242
+ # verify 'task setup'
243
+ # it 'created' do
244
+ # expect(metadata[:task]).to eq :created
245
+ # end
246
+ # end
247
+ # Teardown steps within group will be called at the end of the group, not scenario
248
+ # @overload context(title, **metadata, &block)
249
+ # @param title [String] context title
250
+ # @param metadata [Hash] the step additional metadata
251
+ # @param block [Block] The implementation of the step.
252
+ define_step_method :context
253
+
254
+ # Define single validation step.
255
+ # @example
256
+ # it 'works' do
257
+ # expect(1).to eq 1
258
+ # end
259
+ # @overload it(title, &block)
260
+ # @param title [String] validation title
261
+ # @param block [Block] The implementation of the step.
262
+ define_step_method :it
263
+
264
+ # Define runtime method for the scenario.
265
+ #
266
+ # @note
267
+ # The method to be called via #method_missing, so it wont override already defined methods.
268
+ #
269
+ # @example
270
+ # let(:square) { |num| num * num }
271
+ # it 'calculated' do
272
+ # expect(square(4)).to eq 16
273
+ # end
274
+ def let(method_name, &block)
275
+ steps << Lopata::Step.new(:let) do
276
+ execution.let(method_name, &block)
277
+ end
278
+ end
279
+
280
+ # @!endgroup
281
+
282
+ # @private
62
283
  def add_step(method_name, *args, condition: nil, metadata: {}, &block)
63
284
  step_class =
64
285
  case method_name
@@ -71,10 +292,12 @@ class Lopata::ScenarioBuilder
71
292
  steps << step
72
293
  end
73
294
 
295
+ # @private
74
296
  def steps
75
297
  @steps ||= []
76
298
  end
77
299
 
300
+ # @private
78
301
  def steps_with_hooks
79
302
  s = []
80
303
  unless Lopata.configuration.before_scenario_steps.empty?
@@ -90,20 +313,7 @@ class Lopata::ScenarioBuilder
90
313
  s
91
314
  end
92
315
 
93
- def let(method_name, &block)
94
- steps << Lopata::Step.new(:let) do
95
- execution.let(method_name, &block)
96
- end
97
- end
98
-
99
- def option(metadata_key, variants)
100
- @options << Option.new(metadata_key, variants)
101
- end
102
-
103
- def diagonal(metadata_key, variants)
104
- @diagonals << Diagonal.new(metadata_key, variants)
105
- end
106
-
316
+ # @private
107
317
  def option_combinations
108
318
  combinations = combine([OptionSet.new], options + diagonals)
109
319
  while !diagonals.all?(&:complete?)
@@ -112,6 +322,7 @@ class Lopata::ScenarioBuilder
112
322
  combinations.reject { |option_set| skip?(option_set) }
113
323
  end
114
324
 
325
+ # @private
115
326
  def combine(source_combinations, rest_options)
116
327
  return source_combinations if rest_options.empty?
117
328
  combinations = []
@@ -124,40 +335,50 @@ class Lopata::ScenarioBuilder
124
335
  combine(combinations, rest_options)
125
336
  end
126
337
 
338
+ # @private
127
339
  def world
128
340
  Lopata.world
129
341
  end
130
342
 
131
- # Набор вариантов, собранный для одного теста
343
+ # Set of options for scenario
132
344
  class OptionSet
345
+ # @private
133
346
  attr_reader :variants
347
+
348
+ # @private
134
349
  def initialize(*variants)
135
350
  @variants = {}
136
351
  variants.compact.each { |v| self << v }
137
352
  end
138
353
 
354
+ # @private
139
355
  def +(other_set)
140
356
  self.class.new(*@variants.values).tap do |sum|
141
357
  other_set.each { |v| sum << v }
142
358
  end
143
359
  end
144
360
 
361
+ # @private
145
362
  def <<(variant)
146
363
  @variants[variant.key] = variant
147
364
  end
148
365
 
366
+ # @private
149
367
  def [](key)
150
368
  @variants[key]
151
369
  end
152
370
 
371
+ # @private
153
372
  def each(&block)
154
373
  @variants.values.each(&block)
155
374
  end
156
375
 
376
+ # @private
157
377
  def title
158
378
  @variants.values.map(&:title).compact.join(' ')
159
379
  end
160
380
 
381
+ # @return [Hash{Symbol => Object}] metadata for this option set
161
382
  def metadata
162
383
  @variants.values.inject({}) do |metadata, variant|
163
384
  metadata.merge(variant.metadata(self))
@@ -165,6 +386,7 @@ class Lopata::ScenarioBuilder
165
386
  end
166
387
  end
167
388
 
389
+ # @private
168
390
  class Variant
169
391
  attr_reader :key, :title, :value, :option
170
392
 
@@ -213,6 +435,7 @@ class Lopata::ScenarioBuilder
213
435
  end
214
436
  end
215
437
 
438
+ # @private
216
439
  class CalculatedValue
217
440
  def initialize(&block)
218
441
  @proc = block
@@ -223,6 +446,7 @@ class Lopata::ScenarioBuilder
223
446
  end
224
447
  end
225
448
 
449
+ # @private
226
450
  class Option
227
451
  attr_reader :variants, :key
228
452
  def initialize(key, variants)
@@ -258,6 +482,7 @@ class Lopata::ScenarioBuilder
258
482
  end
259
483
  end
260
484
 
485
+ # @private
261
486
  class Diagonal < Option
262
487
  def level_variants
263
488
  [next_variant]
@@ -1,9 +1,11 @@
1
1
  module Lopata
2
+ # @private
2
3
  class SharedStep
3
4
  attr_reader :name, :block
4
5
 
5
6
  class NotFound < StandardError; end
6
7
 
8
+
7
9
  def self.register(name, &block)
8
10
  raise ArgumentError, "Comma is not allowed in shared step name: '%s'" % name if name =~ /,/
9
11
  registry[name] = new(name, &block)
@@ -1,4 +1,5 @@
1
1
  module Lopata
2
+ # @private
2
3
  class Step
3
4
  attr_reader :block, :args, :condition, :method_name, :shared_step
4
5
  # metadata overrien by the step.
@@ -26,7 +27,8 @@ module Lopata
26
27
  end
27
28
  end
28
29
 
29
- # Used for action, setup, teardown
30
+ # @private
31
+ # Used for action, setup, teardown, verify
30
32
  class ActionStep < Step
31
33
  def execution_steps(scenario, groups: [])
32
34
  steps = []
@@ -66,6 +68,7 @@ module Lopata
66
68
  end
67
69
  end
68
70
 
71
+ # @private
69
72
  # Used for context
70
73
  class GroupStep < Step
71
74
 
@@ -94,6 +97,7 @@ module Lopata
94
97
  end
95
98
  end
96
99
 
100
+ #@private
97
101
  class StepExecution
98
102
  attr_reader :step, :status, :exception, :block, :pending_message, :groups
99
103
  extend Forwardable
@@ -1,5 +1,6 @@
1
1
  module Lopata
2
+ # @private
2
3
  module Version
3
- STRING = '0.1.6'
4
+ STRING = '0.1.7'
4
5
  end
5
6
  end
@@ -1,21 +1,15 @@
1
+ # Container for gobal non-configuration data
1
2
  class Lopata::World
3
+ # Scenarios are selected for current run
4
+ # @return [Array<Lopata::Scenario::Execution>]
2
5
  attr_reader :scenarios
3
6
 
7
+ # @private
4
8
  def initialize
5
9
  @scenarios = []
6
10
  end
7
11
 
8
- def start
9
- notify_observers(:started, self)
10
- end
11
-
12
- # Called at the end of test running.
13
- #
14
- # Notifies observers about testing finish
15
- def finish
16
- notify_observers(:finished, self)
17
- end
18
-
12
+ # @private
19
13
  def notify_observers(event, context)
20
14
  observers.each do |observer|
21
15
  observer.send event, context
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.6
4
+ version: 0.1.7
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-06-01 00:00:00.000000000 Z
11
+ date: 2020-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -87,6 +87,7 @@ executables:
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".yardopts"
90
91
  - README.md
91
92
  - exe/lopata
92
93
  - lib/lopata.rb
@@ -137,5 +138,5 @@ requirements: []
137
138
  rubygems_version: 3.0.3
138
139
  signing_key:
139
140
  specification_version: 4
140
- summary: lopata-0.1.6
141
+ summary: lopata-0.1.7
141
142
  test_files: []