lopata 0.1.2 → 0.1.7

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
  SHA256:
3
- metadata.gz: 996fe5f1c16b6fed5daadff4ce365a778c2f09d79562c221e497c541541e9012
4
- data.tar.gz: 7200a98d6bead7fb3baed82bbdffbf1c6aca805d999a563f3ada78026344dfed
3
+ metadata.gz: 7f4b4814d88cd3b9da3a34159e3c1c977d05cbb0504d3dc0b2ab8034044dfbf0
4
+ data.tar.gz: 378e5a3c346c64cb4430577dcfab31cfefd54a2c8e8ee30046609cf10e1bdba4
5
5
  SHA512:
6
- metadata.gz: 037ccc6d687292186b752de6924a2f3373d0934569f9e2d01567cac1a4607aa33ce70f53473ad0d737d07cdb1da231bb8b526f6c24f8c2e73d494978dfc94179
7
- data.tar.gz: 7c90f679400d64d7ab676807cea167947cee47114cf9ea8daed84c517888bf5e7e64b475c1841f9e6cb886cf08184ca3acedaf6dc5af68a3518e74e4130f91b7
6
+ metadata.gz: ff0498d9c9b665d52f5a8d1e65cdc6dc9078f0df1cd4f7fd831393af04ee564a5cf9a9f55305bd4423ff92062cdb7fd4a728bb2be657f196f91447faddffa941
7
+ data.tar.gz: 063a3914c5e5dd088ad56e37ea527c540e8dc82f0d56e7dca4564e61699541000e4d801a80898b2d89eb6719cfd4d1a887d3884a52335f0e6339ffc9a91569fb
@@ -0,0 +1 @@
1
+ --no-private
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Lopata - functional acceptance testing
1
+ # Lopata
2
2
 
3
- Motivation: use RSpec for functional testing.
3
+ Functional acceptance testing using Ruby.
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,3 +20,7 @@ Run tests:
20
20
 
21
21
  cd <project-name>
22
22
  lopata
23
+
24
+ ## Documentation
25
+
26
+ See [features description](https://github.com/avolochnev/lopata/tree/master/features) for documentation.
data/exe/lopata CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'bundler/setup'
3
- require_relative '../lib/lopata/runner'
3
+ require 'lopata/runner'
4
4
 
5
5
  # use default command with arguments if given command is unknown.
6
6
  argv = ARGV.dup
@@ -1,11 +1,15 @@
1
1
  require 'lopata/id'
2
- require 'lopata/config'
2
+ require 'lopata/configuration'
3
+ require 'lopata/environment'
3
4
  require 'lopata/scenario_builder'
4
5
  require 'lopata/scenario'
5
6
  require 'lopata/step'
6
7
  require 'lopata/shared_step'
7
8
 
9
+ # Namespace for all Lopata code.
8
10
  module Lopata
11
+ # Define the scenario.
12
+ # @see Lopata::ScenarioBuilder.define
9
13
  def self.define(*args, &block)
10
14
  Lopata::ScenarioBuilder.define(*args, &block)
11
15
  end
@@ -14,11 +18,57 @@ module Lopata
14
18
  def self.xdefine(*args, &block)
15
19
  end
16
20
 
21
+ # Register the shared step
22
+ #
23
+ # @example
24
+ # Lopata.shared_step 'test user' do
25
+ # setup { @user = create(:user) }
26
+ # end
27
+ #
28
+ # Shared step may be used in scenarios by name:
29
+ # @example
30
+ # Lopata.define 'user' do
31
+ # setup 'test user'
32
+ #
33
+ # it 'exists' do
34
+ # expect(@user).to_not be_nil
35
+ # end
36
+ # end
37
+ # @param name [String] shared step unique name
38
+ # @param block [Block] shared step action sequence definition
17
39
  def self.shared_step(name, &block)
18
40
  Lopata::SharedStep.register(name, &block)
19
41
  end
20
42
 
43
+ # Yields the global configuration to a block.
44
+ # @yield [Lopata::Configuration] global configuration
45
+ #
46
+ # @example
47
+ # Lopata.configure do |config|
48
+ # config.before_scenario 'setup test user'
49
+ # end
50
+ # @see Lopata::Configuration
21
51
  def self.configure(&block)
22
- yield Lopata::Config
52
+ yield Lopata.configuration
53
+ end
54
+
55
+ # Returns global configuration object.
56
+ # @return [Lopata::Configuration]
57
+ # @see Lopata.configure
58
+ def self.configuration
59
+ @configuration ||= Lopata::Configuration.new
60
+ end
61
+
62
+ # @private
63
+ # Internal container for global non-configuration data.
64
+ def self.world
65
+ @world ||= Lopata::World.new
66
+ end
67
+
68
+ # Return global environment object
69
+ # @return [Lopata::Environment]
70
+ # @see Lopata::Environment
71
+ def self.environment
72
+ Lopata.configuration.environment
23
73
  end
24
74
  end
@@ -1,25 +1,118 @@
1
1
  module Lopata
2
+ # Helpers for ActiveRecord usage in tests.
3
+ #
4
+ # Make helpers available in scenarios by
5
+ #
6
+ # require 'lopata/active_record'
7
+ #
8
+ # @example
9
+ #
10
+ # # Configure db connection at config/environments/qa.yml like rails:
11
+ # # db:
12
+ # # adapter: postgresql
13
+ # # host: your.database.host
14
+ # # username: username
15
+ # # password: password
16
+ # # database: database
17
+ # require 'active_record'
18
+ # require 'lopata/active_record'
19
+ #
20
+ # class User < ActiveRecord::Base; end
21
+ #
22
+ # Lopata.define 'User creation' do
23
+ # setup do
24
+ # @user = User.create!(username: 'testuser')
25
+ # end
26
+ # # Remove user from database after scenario
27
+ # cleanup :user
28
+ #
29
+ # it 'works' do
30
+ # expect(@user).to_not be_nil
31
+ # end
32
+ # end
33
+ #
2
34
  module ActiveRecord
3
- # To be included in Lopata::Scenario
35
+ # To be included in Lopata::Scenario. The methods may be used in runtime.
4
36
  module Methods
37
+ # Destroy ActiveRecord objects.
38
+ #
39
+ # Does nothing if 'keep' mode is enabled:
40
+ #
41
+ # Lopata.configure do |c|
42
+ # c.keep = true
43
+ # end
44
+ #
45
+ # @param objects [Array<ActiveRecord::Base, Array<ActiveRecord::Base>, nil>] to be destroyed
46
+ # @see Lopata::Configuration#keep
5
47
  def cleanup(*objects)
6
- return if Lopata::Config.ops[:keep]
48
+ return if Lopata.configuration.keep
7
49
  objects.flatten.compact.each do |o|
8
50
  begin
9
51
  o.reload.destroy!
10
52
  rescue ::ActiveRecord::RecordNotFound
11
- # Already destroyed
53
+ # Already destroyed - skip
54
+ rescue ::ActiveRecord::InvalidForeignKey
55
+ # Possible async job created new relationships (e.g. history records). Try again once.
56
+ o.reload.destroy!
12
57
  end
13
58
  end
14
59
  end
15
60
 
61
+ # Reload ActiveRecord objects
62
+ #
63
+ # @example
64
+ #
65
+ # # use in steps
66
+ # reload @a, @b
67
+ # # instead of
68
+ # @a.reload; @b.reload
69
+ #
70
+ # @param objects [Array<ActiveRecord::Base, Array<ActiveRecord::Base>, nil>] to be reloaded
16
71
  def reload(*objects)
17
- objects.flatten.each(&:reload)
72
+ objects.flatten.compact.each(&:reload)
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
18
106
  end
19
107
  end
20
108
 
21
- # To be included in Lopata::ScenarioBuilder
109
+ # To be included in Lopata::ScenarioBuilder. The methods may be used in build time.
22
110
  module DSL
111
+ # Mark instance variables to call #destroy at teardown phase of scenario or context running.
112
+ #
113
+ # Does nothing if 'keep' mode is enabled.
114
+ #
115
+ # @param vars [Array<Symbol, String>] instance variable names to be destroyed on teardown phase.
23
116
  def cleanup(*vars, &block)
24
117
  unless vars.empty?
25
118
  teardown do
@@ -32,5 +125,12 @@ module Lopata
32
125
  end
33
126
  end
34
127
 
128
+ Lopata.configure do |c|
129
+ c.after_scenario { cleanup @created_objects }
130
+ end
131
+
132
+ params = Lopata.environment['db']
133
+ ActiveRecord::Base.establish_connection(params) if params
134
+
35
135
  Lopata::Scenario.include Lopata::ActiveRecord::Methods
36
136
  Lopata::ScenarioBuilder.include Lopata::ActiveRecord::DSL
@@ -1,4 +1,5 @@
1
1
  module Lopata
2
+ # @private
2
3
  class Condition
3
4
  attr_reader :condition, :positive
4
5
  def initialize(condition, positive: true)
@@ -18,7 +19,7 @@ module Lopata
18
19
  when Hash
19
20
  condition.keys.all? { |k| metadata[k] == condition[k] }
20
21
  when Array
21
- condition.map { |key| metadata[key] }.none?(&:nil?)
22
+ condition.map { |key| metadata[key] }.all?
22
23
  else
23
24
  metadata[condition]
24
25
  end
@@ -0,0 +1,126 @@
1
+ module Lopata
2
+ # Stores runtime configuration information
3
+ #
4
+ # @see Lopata.configure
5
+ # @see Lopata.configuration
6
+ class Configuration
7
+ # Build an object to store runtime configuration options and set defaults
8
+ def initialize
9
+ @before_start_hooks = []
10
+ @before_scenario_steps = []
11
+ @after_scenario_steps = []
12
+ @observers = [Lopata::Observers::ConsoleOutputObserver.new]
13
+ @role_descriptions = {}
14
+ @env = :qa
15
+ end
16
+
17
+ # Add the hook to be called before scenarios running
18
+ # The block will be called after framework initialization and before scenarios parsing.
19
+ # It usually allow to require and initialize the libraries used for project testing.
20
+ #
21
+ # @example
22
+ # Lopata.configure do |c|
23
+ # c.before_start do
24
+ # require 'active_record'
25
+ # end
26
+ # end
27
+ def before_start(&block)
28
+ @before_start_hooks << block
29
+ end
30
+
31
+ # @private
32
+ def run_before_start_hooks
33
+ @before_start_hooks.each(&:call)
34
+ end
35
+
36
+ # Defines 'before scenario' steps.
37
+ # Given steps will be runned before each scenario in context of scenario.
38
+ # It may be shared step names, and|or block.
39
+ #
40
+ # @example
41
+ # Lopata.configure do |c|
42
+ # c.before_scenario 'setup test user'
43
+ # end
44
+ #
45
+ # @param steps [Array<String>] name of shared steps
46
+ # @param block [Proc] block of code
47
+ def before_scenario(*steps, &block)
48
+ before_scenario_steps.append(*steps) unless steps.empty?
49
+ before_scenario_steps.append(block) if block_given?
50
+ end
51
+
52
+ # Defines 'after scenario' steps.
53
+ # Given steps will be runned after each scenario in context of scenario.
54
+ # It may be shared step names, and|or block.
55
+ #
56
+ # @example
57
+ # Lopata.configure do |c|
58
+ # c.after_scenario 'cleanup test user'
59
+ # end
60
+ #
61
+ # @param steps [Array<String>] name of shared steps
62
+ # @param block [Proc] block of code
63
+ def after_scenario(*steps, &block)
64
+ after_scenario_steps.append(*steps) unless steps.empty?
65
+ after_scenario_steps.append(block) if block_given?
66
+ end
67
+
68
+ # @private
69
+ attr_reader :before_scenario_steps, :after_scenario_steps
70
+
71
+ # Add an observer to the set Lopata to be used for this run.
72
+ #
73
+ # @param observer [Lopata::Observers::BaseObserver] a observer instance.
74
+ #
75
+ # @see Lopata::Observers::BaseObserver
76
+ def add_observer(observer)
77
+ @observers << observer
78
+ end
79
+
80
+ # @private
81
+ attr_reader :observers
82
+
83
+ # @private
84
+ def filters
85
+ @filters ||= []
86
+ end
87
+
88
+ # @private
89
+ attr_accessor :web_logging_params
90
+
91
+ # @private
92
+ def init_lopata_logging(url, project_code, build_number)
93
+ require 'lopata/observers/web_logger'
94
+ self.web_logging_params = { url: url, project_code: project_code, build_number: build_number }
95
+ add_observer Lopata::Observers::WebLogger.new
96
+ end
97
+
98
+ # @return [Hash{Symbol => String}] map or role codes to role name.
99
+ # @see Lopata::Role
100
+ attr_accessor :role_descriptions
101
+
102
+ # @return [Symbol,nil] user role to be used in scenario if not specified
103
+ # @see Lopata::Role
104
+ attr_accessor :default_role
105
+
106
+ # @return [Symbol] environment code.
107
+ # Default is :qa
108
+ # @see Lopata::Environment
109
+ attr_accessor :env
110
+
111
+ # @return [Boolean] keep generated test data after scenarios running.
112
+ # Default is false
113
+ # Set to true for keeping generated data.
114
+ # Use 'lopata --keep' modifier to set keep mode on running.
115
+ # @see Lopata::ActiveRecord::Methods#cleanup
116
+ attr_accessor :keep
117
+
118
+ # @private
119
+ attr_accessor :environment
120
+
121
+ # @private
122
+ def load_environment
123
+ self.environment = Lopata::Environment.new(env)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,36 @@
1
+ module Lopata
2
+ # Settings of test enviromnet the scenarios to be runned.
3
+ #
4
+ # Lopata allows to define different environments the scenarios to be runned on.
5
+ # Set environment name via command line 'lopata -e stage' or via configuration:
6
+ #
7
+ # Lopata.configure do |c|
8
+ # c.env = :stage
9
+ # end
10
+ #
11
+ # The environment params are loaded from './config/environments/<env>.yml'.
12
+ class Environment
13
+ # Loads environment configuration for given env
14
+ # @param env [Symbol] environment key
15
+ # Loads golobl configured environment if not given.
16
+ # @see Lopata::Configuration#env
17
+ def initialize(env = Lopata.configuration.env)
18
+ require 'yaml'
19
+ @config = {}
20
+ config_filename = "./config/environments/#{Lopata.configuration.env}.yml"
21
+ @config = YAML::load(File.open(config_filename)) if File.exists?(config_filename)
22
+ end
23
+
24
+ # Access to environment settings
25
+ # @param key [Symbol] environment configuration key is set on yml configuration.
26
+ def [](key)
27
+ @config[key]
28
+ end
29
+
30
+ %w{url}.each do |opt|
31
+ define_method opt do
32
+ @config[opt]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -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
- ::FactoryBot.find_definitions unless Lopata::Config.readonly
72
+ ::FactoryBot.find_definitions