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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70e042bc80bb14342ec6b0f516df0934007677e8dd98ba04f2d65034ca6acbce
4
- data.tar.gz: 5afff5a8553b777f02b0ee838f304d0d660afdc60042113423b52f08e91342db
3
+ metadata.gz: 51ff4a162c7617388f8856b342449e1475f2438d8a44a6c58c6168373b144969
4
+ data.tar.gz: 10580190d2a63826f971d1730523eacc34ed818b634329da1635db07d2627d27
5
5
  SHA512:
6
- metadata.gz: 0f87e65d52c3bf6a15c85bfd5f900a48a576f256be20264a6df2360f8633694e88267f7cbd348325822b927538c5ad4407a55bd0ce3837c6ef630d685eec9074
7
- data.tar.gz: 2d4c9fe43e2283e210e6c30e882941f99975e9e2b62a00d9a23b7f59208e02726c66b9c72bb2d612e117bd79c82f9fb3aa88e711ed4d3022226d9137f27b76e0
6
+ metadata.gz: 76f4fffc7d6755eb63d45a3297177c25b2e947c101dfad38b7a39e8bb474f00e3874d3b3fcf939a81d3ad550cc7d18335ac998104f0b0436db239d1f4688a0f5
7
+ data.tar.gz: '086e6cb580e94035e78607daa4a5ba6a5caf2211e37bc0e5cd9aa7cb1e2579fc22889e6fb90e17e6b4f290016a70d76f86d1d93d307d19e964b7584a3bee0451'
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,14 @@
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
 
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::Config
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
@@ -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::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)
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
@@ -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
@@ -33,4 +33,4 @@ Lopata.configure do |c|
33
33
  c.after_scenario { cleanup @created_objects }
34
34
  end
35
35
 
36
- ::FactoryBot.find_definitions unless Lopata::Config.readonly
36
+ ::FactoryBot.find_definitions
@@ -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,5 @@
1
1
  source 'https://rubygems.org'
2
2
  gem 'selenium-webdriver'
3
- gem 'rspec', :require => 'spec'
4
- gem 'rake'
5
3
  gem 'activerecord', '~> 6.0.2'
6
4
  gem 'capybara', '~> 3.11.1'
7
5
  gem 'thor'
@@ -1,5 +1,4 @@
1
1
  url: http://yourapp.com
2
- name: QA
3
2
  # db:
4
3
  # adapter: postgresql
5
4
  # host: localhost
@@ -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)