lopata 0.1.5 → 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.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/exe/lopata +1 -1
- data/lib/lopata.rb +51 -2
- data/lib/lopata/active_record.rb +68 -5
- data/lib/lopata/condition.rb +2 -1
- data/lib/lopata/configuration.rb +126 -0
- data/lib/lopata/environment.rb +36 -0
- data/lib/lopata/factory_bot.rb +1 -1
- data/lib/lopata/generators/app.rb +0 -2
- data/lib/lopata/generators/templates/Gemfile +0 -2
- data/lib/lopata/generators/templates/config/environments/qa.yml +0 -1
- data/lib/lopata/observers/backtrace_formatter.rb +14 -0
- data/lib/lopata/observers/base_observer.rb +17 -6
- data/lib/lopata/observers/console_output_observer.rb +30 -8
- data/lib/lopata/observers/web_logger.rb +26 -33
- data/lib/lopata/role.rb +46 -0
- data/lib/lopata/runner.rb +10 -19
- data/lib/lopata/scenario.rb +30 -6
- data/lib/lopata/scenario_builder.rb +16 -59
- data/lib/lopata/step.rb +10 -7
- data/lib/lopata/version.rb +1 -1
- data/lib/lopata/world.rb +3 -1
- metadata +6 -8
- data/lib/lopata/config.rb +0 -97
- data/lib/lopata/generators/templates/.rspec +0 -3
- data/lib/lopata/generators/templates/spec/spec_helper.rb +0 -2
- data/lib/lopata/rspec/dsl.rb +0 -39
- data/lib/lopata/rspec/role.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51ff4a162c7617388f8856b342449e1475f2438d8a44a6c58c6168373b144969
|
4
|
+
data.tar.gz: 10580190d2a63826f971d1730523eacc34ed818b634329da1635db07d2627d27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76f4fffc7d6755eb63d45a3297177c25b2e947c101dfad38b7a39e8bb474f00e3874d3b3fcf939a81d3ad550cc7d18335ac998104f0b0436db239d1f4688a0f5
|
7
|
+
data.tar.gz: '086e6cb580e94035e78607daa4a5ba6a5caf2211e37bc0e5cd9aa7cb1e2579fc22889e6fb90e17e6b4f290016a70d76f86d1d93d307d19e964b7584a3bee0451'
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# Lopata
|
1
|
+
# Lopata
|
2
2
|
|
3
|
-
|
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
data/lib/lopata.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'lopata/id'
|
2
|
-
require 'lopata/
|
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
|
|
8
9
|
module Lopata
|
10
|
+
# Define the scenario.
|
11
|
+
# @see Lopata::ScenarioBuilder.define
|
9
12
|
def self.define(*args, &block)
|
10
13
|
Lopata::ScenarioBuilder.define(*args, &block)
|
11
14
|
end
|
@@ -14,11 +17,57 @@ module Lopata
|
|
14
17
|
def self.xdefine(*args, &block)
|
15
18
|
end
|
16
19
|
|
20
|
+
# Register the shared step
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# Lopata.shared_step 'test user' do
|
24
|
+
# setup { @user = create(:user) }
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Shared step may be used in scenarios by name:
|
28
|
+
# @example
|
29
|
+
# Lopata.define 'user' do
|
30
|
+
# setup 'test user'
|
31
|
+
#
|
32
|
+
# it 'exists' do
|
33
|
+
# expect(@user).to_not be_nil
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# @param name [String] shared step unique name
|
37
|
+
# @param block shared step action sequence definition
|
17
38
|
def self.shared_step(name, &block)
|
18
39
|
Lopata::SharedStep.register(name, &block)
|
19
40
|
end
|
20
41
|
|
42
|
+
# Yields the global configuration to a block.
|
43
|
+
# @yield [Lopata::Configuration] global configuration
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# Lopata.configure do |config|
|
47
|
+
# config.before_scenario 'setup test user'
|
48
|
+
# end
|
49
|
+
# @see Lopata::Configuration
|
21
50
|
def self.configure(&block)
|
22
|
-
yield Lopata
|
51
|
+
yield Lopata.configuration
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns global configuration object.
|
55
|
+
# @return [Lopata::Configuration]
|
56
|
+
# @see Lopata.configure
|
57
|
+
def self.configuration
|
58
|
+
@configuration ||= Lopata::Configuration.new
|
59
|
+
end
|
60
|
+
|
61
|
+
# @private
|
62
|
+
# Internal container for global non-configuration data.
|
63
|
+
def self.world
|
64
|
+
@world ||= Lopata::World.new
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return global environment object
|
68
|
+
# @return [Lopata::Environment]
|
69
|
+
# @see Lopata::Environment
|
70
|
+
def self.environment
|
71
|
+
Lopata.configuration.environment
|
23
72
|
end
|
24
73
|
end
|
data/lib/lopata/active_record.rb
CHANGED
@@ -1,25 +1,85 @@
|
|
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
|
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)
|
18
73
|
end
|
19
74
|
end
|
20
75
|
|
21
|
-
# To be included in Lopata::ScenarioBuilder
|
76
|
+
# To be included in Lopata::ScenarioBuilder. The methods may be used in build time.
|
22
77
|
module DSL
|
78
|
+
# Mark instance variables to call #destroy at teardown phase of scenario or context running.
|
79
|
+
#
|
80
|
+
# Does nothing if 'keep' mode is enabled.
|
81
|
+
#
|
82
|
+
# @param vars [Array<Symbol, String>] instance variable names to be destroyed on teardown phase.
|
23
83
|
def cleanup(*vars, &block)
|
24
84
|
unless vars.empty?
|
25
85
|
teardown do
|
@@ -32,5 +92,8 @@ module Lopata
|
|
32
92
|
end
|
33
93
|
end
|
34
94
|
|
95
|
+
params = Lopata.environment['db']
|
96
|
+
ActiveRecord::Base.establish_connection(params) if params
|
97
|
+
|
35
98
|
Lopata::Scenario.include Lopata::ActiveRecord::Methods
|
36
99
|
Lopata::ScenarioBuilder.include Lopata::ActiveRecord::DSL
|
data/lib/lopata/condition.rb
CHANGED
@@ -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] }.
|
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
|
data/lib/lopata/factory_bot.rb
CHANGED
@@ -11,10 +11,8 @@ module Lopata
|
|
11
11
|
def create_root_files
|
12
12
|
template 'Lopatafile', "#{name}/Lopatafile"
|
13
13
|
template 'Gemfile', "#{name}/Gemfile"
|
14
|
-
template '.rspec', "#{name}/.rspec"
|
15
14
|
template 'config/environments/qa.yml', "#{name}/config/environments/qa.yml"
|
16
15
|
template 'config/initializers/capybara.rb', "#{name}/config/initializers/capybara.rb"
|
17
|
-
template 'spec/spec_helper.rb', "#{name}/spec/spec_helper.rb"
|
18
16
|
end
|
19
17
|
|
20
18
|
def init_dirs
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module Lopata
|
2
2
|
module Observers
|
3
|
+
# @private
|
3
4
|
# Based on RSpec::Core::BacktraceFormatter
|
5
|
+
#
|
6
|
+
# Provides ability to format backtrace and find source code by file and line number.
|
4
7
|
class BacktraceFormatter
|
8
|
+
# @private
|
5
9
|
attr_accessor :exclusion_patterns, :inclusion_patterns
|
6
10
|
|
7
11
|
def initialize
|
@@ -14,6 +18,10 @@ module Lopata
|
|
14
18
|
inclusion_patterns << Regexp.new(Dir.getwd)
|
15
19
|
end
|
16
20
|
|
21
|
+
# Filter backtrace.
|
22
|
+
#
|
23
|
+
# @param backtrace [Array<String>] exception backtrace
|
24
|
+
# @return [Array<String>] backtrace lines except ruby libraries, gems and executable files.
|
17
25
|
def format(backtrace)
|
18
26
|
return [] unless backtrace
|
19
27
|
return backtrace if backtrace.empty?
|
@@ -28,6 +36,12 @@ module Lopata
|
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
39
|
+
|
40
|
+
# Extracts error message from excetion
|
41
|
+
#
|
42
|
+
# @param exeption [Exception]
|
43
|
+
# @param include_backtrace [Boolean] whether to add formatted backtrace to output
|
44
|
+
# @return [String] error message from excetion, incuding source code line.
|
31
45
|
def error_message(exception, include_backtrace: false)
|
32
46
|
backtrace = format(exception.backtrace)
|
33
47
|
source_line = extract_source_line(backtrace.first)
|