lopata 0.1.0 → 0.1.1

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: 4ad9bc72f5e0429f18b12bc247e3fbf4346278b5c6b487a02c665e3c020bd5f7
4
- data.tar.gz: bde38469c56e1ef03b1480fa09d9d879867660983fcd9abe807ee8be553aaaed
3
+ metadata.gz: 9233d9fba2a55749f02037d5ca106c0cb9249debda448aac58ccc2cc724a378e
4
+ data.tar.gz: 65ea743e92f5084b6f04b52595296cb80a3d4540f4cb8ba8bc2c774cbc448aaf
5
5
  SHA512:
6
- metadata.gz: ba6f140682c330ca68eb2a8d3f27aed552bd376c1a1c773ebe1914b4738da39adfe500a4254e06c2ea3865bd5fedc7246e5301eca6e130683bc4119e7db30071
7
- data.tar.gz: 0d6b7e1f4ae029539a1c65fd0e9ca4546610bbe6e8da8b37250ec71a106cc3cfe0445b4a6b299de9cbd5a2b1a5e4949b7bad6f178af32e702252755553b69474
6
+ metadata.gz: a706fde4a5acc83b27400ce50c19137b7fd9f296bfb2ac4baeec55e50e5fe48b4bf6e90110611f4f69cd2dc9571a15d1de34e54e8bec094f0c2c2d5cc5ca1a87
7
+ data.tar.gz: 2d0764e801260489815f30b8572ffdff7bdf6572fc64b55d0e53c091f8f125925374ae9cf706b1fe0bc956a6d56ef23b6dd1bd767b7ce13de550b4878dc86f4f
data/README.md CHANGED
@@ -14,7 +14,7 @@ Create new lopata project:
14
14
 
15
15
  Setup environment: edit <project-name>/config/environments/qa.yml for setup project for testing.
16
16
 
17
- Write tests: puts RSpec tests in <project-name>/spec folder.
17
+ Write tests: puts tests in <project-name>/scenarios folder. Define shared steps in <project-name>/shared_steps folder.
18
18
 
19
19
  Run tests:
20
20
 
@@ -10,8 +10,8 @@ module Lopata
10
10
  Lopata::ScenarioBuilder.define(*args, &block)
11
11
  end
12
12
 
13
+ # Skip scenario definition. Option to temporary ignore scenario
13
14
  def self.xdefine(*args, &block)
14
- Lopata::ScenarioBuilder.xdefine(*args, &block)
15
15
  end
16
16
 
17
17
  def self.shared_step(name, &block)
@@ -0,0 +1,30 @@
1
+ module Lopata
2
+ class Condition
3
+ attr_reader :condition, :positive
4
+ def initialize(condition, positive: true)
5
+ @condition, @positive = condition, positive
6
+ end
7
+
8
+ EMPTY = new({})
9
+
10
+ alias positive? positive
11
+
12
+ def match?(scenario)
13
+ matched = match_metadata?(scenario)
14
+ positive? ? matched : !matched
15
+ end
16
+
17
+ def match_metadata?(scenario)
18
+ metadata = scenario.metadata
19
+ case condition
20
+ when Hash
21
+ condition.keys.all? { |k| metadata[k] == condition[k] }
22
+ when Array
23
+ condition.map { |key| metadata[key] }.none?(&:nil?)
24
+ else
25
+ metadata[condition]
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -49,10 +49,8 @@ module Lopata
49
49
 
50
50
  def init_lopata_logging(build)
51
51
  self.build_number = build
52
- ::RSpec.configure do |c|
53
- require 'lopata/rspec/formatter' # class cross-loading, avoid auto-loading
54
- c.add_formatter Lopata::RSpec::Formatter
55
- end
52
+ require 'lopata/observers/web_logger'
53
+ add_observer Lopata::Observers::WebLogger.new
56
54
  end
57
55
 
58
56
  def init_rerun
@@ -95,5 +93,9 @@ module Lopata
95
93
  def world
96
94
  @world ||= Lopata::World.new
97
95
  end
96
+
97
+ def add_observer(observer)
98
+ world.observers << observer
99
+ end
98
100
  end
99
101
  end
@@ -0,0 +1,26 @@
1
+ module Lopata::Loader
2
+ extend self
3
+
4
+ # Loads scenarios for running in current session
5
+ #
6
+ # @param args [Array<String>] files to be load.
7
+ # All files from default location to be loaded if empty.
8
+ def load_scenarios(*args)
9
+ if args.empty?
10
+ load_all_scenarios
11
+ else
12
+ args.each do |file|
13
+ load File.expand_path(file)
14
+ end
15
+ end
16
+ end
17
+
18
+ # Loads all scenarios from predefined paths
19
+ def load_all_scenarios
20
+ Dir["scenarios/**/*.rb"].each { |f| load File.expand_path(f) }
21
+ end
22
+
23
+ def load_shared_steps
24
+ Dir["shared_steps/**/*rb"].each { |f| load File.expand_path(f) }
25
+ end
26
+ end
@@ -0,0 +1,129 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module Lopata
5
+ module Observers
6
+ class WebLogger < BaseObserver
7
+ def started(world)
8
+ raise "Build number is not initailzed in Lopata::Config" unless Lopata::Config.build_number
9
+ @client = Lopata::Client.new(Lopata::Config.build_number)
10
+ @client.start(world.scenarios.count)
11
+ end
12
+
13
+ def scenario_finished(scenario)
14
+ if scenario.failed?
15
+ backtrace = backtrace_for(scenario)
16
+ @client.add_attempt(scenario, Lopata::FAILED, error_message_for(scenario), backtrace)
17
+ else
18
+ @client.add_attempt(scenario, Lopata::PASSED)
19
+ end
20
+ end
21
+
22
+ # def example_pending(notification)
23
+ # example = notification.example
24
+ # @client.add_attempt(example, Lopata::PENDING, example.execution_result.pending_message)
25
+ # end
26
+
27
+ private
28
+
29
+ def error_message_for(scenario)
30
+ exception = scenario.steps.map(&:exception).compact.last
31
+ msg = ''
32
+ if exception
33
+ msg << "#{exception.class.name}: " unless exception.class.name =~ /RSpec/
34
+ msg << "#{exception.message.to_s}" if exception.message
35
+ end
36
+ (msg.length == 0) ? 'Empty message' : msg
37
+ end
38
+
39
+ def backtrace_for(scenario)
40
+ exception = scenario.steps.map(&:exception).compact.last
41
+ msg = ''
42
+ if exception
43
+ msg = exception.backtrace.join("\n")
44
+ msg << "\n"
45
+ end
46
+ msg
47
+ end
48
+ end
49
+ end
50
+
51
+ PASSED = 0
52
+ FAILED = 1
53
+ PENDING = 2
54
+
55
+ class Client
56
+ include HTTParty
57
+ base_uri Lopata::Config.lopata_host
58
+
59
+ attr_accessor :build_number
60
+
61
+ def initialize(build_number)
62
+ @build_number = build_number
63
+ end
64
+
65
+ def start(count)
66
+ @launch_id = JSON.parse(post("/projects/#{project_code}/builds/#{build_number}/launches.json", body: {total: count}).body)['id']
67
+ end
68
+
69
+ def add_attempt(scenario, status, msg = nil, backtrace = nil)
70
+ test = test_id(scenario)
71
+ request = { status: status}
72
+ request[:message] = msg if msg
73
+ request[:backtrace] = backtrace if backtrace
74
+ post("/tests/#{test}/attempts.json", body: request)
75
+ inc_finished
76
+ end
77
+
78
+ def test_id(scenario)
79
+ request = {
80
+ test: {
81
+ project_code: project_code,
82
+ title: scenario.title,
83
+ scenario: scenario.title,
84
+ build_number: build_number
85
+ }
86
+ }
87
+ response = post("/tests.json", body: request)
88
+ JSON.parse(response.body)["id"]
89
+ end
90
+
91
+ def to_rerun
92
+ get_json("/projects/#{project_code}/builds/#{build_number}/suspects.json")
93
+ end
94
+
95
+ def to_full_rescan
96
+ to_rerun + get_json("/projects/#{project_code}/builds/#{build_number}/failures.json")
97
+ end
98
+
99
+ private
100
+
101
+ def get_json(url)
102
+ JSON.parse(self.class.get(url).body)
103
+ end
104
+
105
+ def post(*args)
106
+ self.class.post(*args)
107
+ end
108
+
109
+ def patch(*args)
110
+ self.class.patch(*args)
111
+ end
112
+
113
+ def inc_finished
114
+ @finished ||= 0
115
+ @finished += 1
116
+ response = patch("/launches/#{@launch_id}",
117
+ body: { finished: @finished }.to_json,
118
+ headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
119
+ if response.code == 404
120
+ puts 'Launch has been cancelled. Exit.'
121
+ exit!
122
+ end
123
+ end
124
+
125
+ def project_code
126
+ Lopata::Config.lopata_code
127
+ end
128
+ end
129
+ end
@@ -2,8 +2,10 @@ require 'thor'
2
2
  require_relative 'generators/app'
3
3
  require_relative 'config'
4
4
  require_relative 'world'
5
+ require_relative 'loader'
5
6
  require_relative '../lopata'
6
7
  require_relative 'observers'
8
+ require_relative 'condition'
7
9
 
8
10
  module Lopata
9
11
  class Runner < Thor
@@ -18,12 +20,10 @@ module Lopata
18
20
  option :text, aliases: 't'
19
21
  def test(*args)
20
22
  configure_from_options
21
-
22
- # Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
23
+ Lopata::Loader.load_shared_steps
24
+ Lopata::Loader.load_scenarios(*args)
23
25
  world = Lopata::Config.world
24
- world.setup_observers
25
- world.load_shared_steps
26
- world.load_scenarios(*args)
26
+ world.start
27
27
  world.scenarios.each { |s| s.run }
28
28
  world.finish
29
29
  end
@@ -49,8 +49,6 @@ module Lopata
49
49
  }
50
50
  Lopata::Config.init(options[:env])
51
51
  Lopata::Config.initialize_test
52
- # ENV['HOME'] = File.absolute_path('.') # disable warning on rspec loading on windows
53
- # Lopata::Config.init_rspec
54
52
  end
55
53
  end
56
54
  end
@@ -5,9 +5,9 @@ class Lopata::Scenario
5
5
 
6
6
  attr_reader :title, :metadata, :steps, :status
7
7
 
8
- def initialize(*args)
9
- @title = args.first
10
- @metadata = args.last.is_a?(Hash) ? args.last : {}
8
+ def initialize(title, options_title, metadata = {})
9
+ @title = [title, options_title].compact.reject(&:empty?).join(' ')
10
+ @metadata = metadata
11
11
  @steps = []
12
12
  @status = :not_runned
13
13
  end
@@ -33,29 +33,10 @@ class Lopata::Scenario
33
33
  end
34
34
  end
35
35
 
36
- def run_step(method_name, *args, &block)
37
- instance_exec(&block)
38
- end
39
-
40
36
  def world
41
37
  @world ||= Lopata::Config.world
42
38
  end
43
39
 
44
- def convert_args(*args)
45
- args.map do |arg|
46
- case arg
47
- # trait symbols as link to metadata.
48
- when Symbol then metadata[arg]
49
- else
50
- arg
51
- end
52
- end.flatten
53
- end
54
-
55
- def separate_args(args)
56
- args.map { |a| a.is_a?(String) && a =~ /,/ ? a.split(',').map(&:strip) : a }.flatten
57
- end
58
-
59
40
  def failed?
60
41
  status == :failed
61
42
  end
@@ -1,28 +1,30 @@
1
1
  class Lopata::ScenarioBuilder
2
- def self.define(title, metadata = nil, &block)
3
- builder = new
4
- builder.title(title)
5
- builder.metadata(metadata) if metadata
2
+ attr_reader :title, :common_metadata
3
+
4
+ def self.define(title, metadata = {}, &block)
5
+ builder = new(title, metadata)
6
6
  builder.instance_exec &block
7
7
  builder.build
8
8
  end
9
9
 
10
- # Do noting. Exclude defined scenario from suite.
11
- def self.xdefine(*attrs)
10
+ def initialize(title, metadata = {})
11
+ @title, @common_metadata = title, metadata
12
12
  end
13
13
 
14
14
  def build
15
- world = Lopata::Config.world
16
- option_combinations.map do |option_set|
17
- args = prepare_args(option_set)
18
- raise "scenario required a name in first argument" unless args.first.is_a? String
19
- scenario = Lopata::Scenario.new(*args)
15
+ option_combinations.each do |option_set|
16
+ metadata = common_metadata.merge(option_set.metadata)
17
+ scenario = Lopata::Scenario.new(title, option_set.title, metadata)
20
18
 
21
19
  steps.each do |step|
20
+ next if step.condition && !step.condition.match?(scenario)
21
+ step.pre_steps(scenario).each { |s| scenario.steps << s }
22
22
  scenario.steps << step
23
23
  end
24
24
 
25
- scenario.steps << Lopata::Config.after_scenario if Lopata::Config.after_scenario
25
+ if Lopata::Config.after_scenario
26
+ scenario.steps << Lopata::Step.new(:after_scenario, &Lopata::Config.after_scenario)
27
+ end
26
28
 
27
29
  world.scenarios << scenario
28
30
  end
@@ -56,36 +58,22 @@ class Lopata::ScenarioBuilder
56
58
  @skip_when && @skip_when.call(option_set)
57
59
  end
58
60
 
59
- %i{setup action it teardown}.each do |name|
61
+ %i{ setup action it teardown }.each do |name|
60
62
  name_if = "%s_if" % name
61
63
  name_unless = "%s_unless" % name
62
64
  define_method name, ->(*args, &block) { add_step(name, *args, &block) }
63
- define_method name_if, ->(condition, *args, &block) { add_step(name, *args, if_cond: condition, &block) }
64
- define_method name_unless, ->(condition, *args, &block) { add_step(name, *args, unless_cond: condition, &block) }
65
+ define_method name_if, ->(condition, *args, &block) { add_step(name, *args, condition: Lopata::Condition.new(condition), &block) }
66
+ define_method name_unless, ->(condition, *args, &block) { add_step(name, *args, condition: Lopata::Condition.new(condition, positive: false), &block) }
65
67
  end
66
68
 
67
- def add_step(method_name, *args, if_cond: nil, unless_cond: nil, &block)
68
- steps << Lopata::Step.new(method_name, *args) do
69
- # will be called in context of scenario
70
- next if if_cond && !match_metadata?(if_cond)
71
- next if unless_cond && match_metadata?(unless_cond)
72
-
73
- flat_args = args.flatten
74
- flat_args = separate_args(flat_args) if method_name =~ /^(setup|action)/
75
- converted_args = convert_args(*flat_args)
76
- converted_args.shift if method_name =~ /^it$/
77
- converted_args.each do |step|
78
- if step.is_a?(String)
79
- Lopata::SharedStep.find(step).steps.each do |shared_step|
80
- instance_exec(&shared_step.block)
81
- end
82
- elsif step.is_a?(Proc)
83
- instance_exec(&step)
84
- end
69
+ def add_step(method_name, *args, condition: nil, &block)
70
+ step_class =
71
+ if method_name =~ /^(setup|action|teardown)/
72
+ Lopata::ActionStep
73
+ else
74
+ Lopata::Step
85
75
  end
86
- # run_step method_name, *converted_args, &block
87
- instance_exec(&block) if block
88
- end
76
+ steps << step_class.new(method_name, *args, condition: condition, &block)
89
77
  end
90
78
 
91
79
  def steps
@@ -120,10 +108,6 @@ class Lopata::ScenarioBuilder
120
108
  @roles ||= [Lopata::Config.default_role].compact
121
109
  end
122
110
 
123
- def title(value)
124
- @title = value
125
- end
126
-
127
111
  def option(metadata_key, variants)
128
112
  options << Option.new(metadata_key, variants)
129
113
  end
@@ -161,22 +145,8 @@ class Lopata::ScenarioBuilder
161
145
  combine(combinations, rest_options)
162
146
  end
163
147
 
164
- def prepare_args(option_set, *args)
165
- options_title, metadata = option_set.title, option_set.metadata
166
- if args[0].is_a? String
167
- args[0] = [@title, options_title, args[0]].compact.reject(&:empty?).join(' ')
168
- else
169
- args.unshift([@title, options_title].compact.reject(&:empty?).join(' '))
170
- end
171
-
172
- metadata.merge!(@common_metadata) if @common_metadata
173
-
174
- if args.last.is_a? Hash
175
- args.last.merge!(metadata)
176
- else
177
- args << metadata
178
- end
179
- args
148
+ def world
149
+ @world ||= Lopata::Config.world
180
150
  end
181
151
 
182
152
  # Набор вариантов, собранный для одного теста
@@ -1,21 +1,21 @@
1
1
  module Lopata
2
2
  class SharedStep
3
- attr_reader :block
3
+ attr_reader :name, :block
4
4
 
5
5
  class SharedStepNotFound < 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
9
  @shared_steps ||= {}
10
- @shared_steps[name] = new(&block)
10
+ @shared_steps[name] = new(name, &block)
11
11
  end
12
12
 
13
13
  def self.find(name)
14
14
  @shared_steps[name] or raise StandardError, "Shared step '%s' not found" % name
15
15
  end
16
16
 
17
- def initialize(&block)
18
- @block = block
17
+ def initialize(name, &block)
18
+ @name, @block = name, block
19
19
  end
20
20
 
21
21
  def steps
@@ -23,7 +23,7 @@ module Lopata
23
23
  end
24
24
 
25
25
  def build_steps
26
- builder = Lopata::ScenarioBuilder.new
26
+ builder = Lopata::ScenarioBuilder.new(name)
27
27
  builder.instance_exec(&block)
28
28
  builder.steps
29
29
  end
@@ -1,20 +1,21 @@
1
1
  module Lopata
2
2
  class Step
3
- attr_reader :block, :status, :exception
3
+ attr_reader :block, :status, :exception, :args, :condition
4
4
 
5
- def initialize(method_name, *args, &block)
5
+ def initialize(method_name, *args, condition: nil, &block)
6
6
  @method_name = method_name
7
7
  @args = args
8
8
  @status = :not_started
9
9
  @block = block
10
10
  @exception = nil
11
+ @condition = condition || Lopata::Condition::EMPTY
11
12
  end
12
13
 
13
14
  def run(scenario)
14
15
  @status = :running
15
16
  world.notify_observers(:step_started, self)
16
17
  begin
17
- scenario.instance_exec(&block)
18
+ run_step(scenario)
18
19
  @status = :passed
19
20
  rescue Exception => e
20
21
  @status = :failed
@@ -23,6 +24,10 @@ module Lopata
23
24
  world.notify_observers(:step_finished, self)
24
25
  end
25
26
 
27
+ def run_step(scenario)
28
+ scenario.instance_exec(&block) if block
29
+ end
30
+
26
31
  def world
27
32
  @world ||= Lopata::Config.world
28
33
  end
@@ -38,5 +43,44 @@ module Lopata
38
43
  def teardown?
39
44
  %i{ teardown cleanup }.include?(@method_name)
40
45
  end
46
+
47
+ def pre_steps(scenario)
48
+ []
49
+ end
50
+ end
51
+
52
+ # Used for action, setup, teardown
53
+ class ActionStep < Step
54
+ def pre_steps(scenario)
55
+ steps = []
56
+ convert_args(scenario).each do |step|
57
+ if step.is_a?(String)
58
+ Lopata::SharedStep.find(step).steps.each do |shared_step|
59
+ steps += shared_step.pre_steps(scenario)
60
+ steps << shared_step
61
+ end
62
+ elsif step.is_a?(Proc)
63
+ steps << Lopata::Step.new(method_name, &step)
64
+ end
65
+ end
66
+ steps
67
+ end
68
+
69
+ def separate_args(args)
70
+ args.map { |a| a.is_a?(String) && a =~ /,/ ? a.split(',').map(&:strip) : a }.flatten
71
+ end
72
+
73
+ def convert_args(scenario)
74
+ flat_args = separate_args(args.flatten)
75
+ flat_args.map do |arg|
76
+ case arg
77
+ # trait symbols as link to metadata.
78
+ when Symbol then scenario.metadata[arg]
79
+ else
80
+ arg
81
+ end
82
+ end.flatten
83
+ end
84
+
41
85
  end
42
86
  end
@@ -1,5 +1,5 @@
1
1
  module Lopata
2
2
  module Version
3
- STRING = '0.1.0'
3
+ STRING = '0.1.1'
4
4
  end
5
5
  end
@@ -1,32 +1,12 @@
1
1
  class Lopata::World
2
- attr_reader :scenarios, :observers
2
+ attr_reader :scenarios
3
3
 
4
4
  def initialize
5
5
  @scenarios = []
6
- @observers = []
7
6
  end
8
7
 
9
- # Loads scenarios for running in current session
10
- #
11
- # @param args [Array<String>] files to be load.
12
- # All files from default location to be loaded if empty.
13
- def load_scenarios(*args)
14
- if args.empty?
15
- load_all_scenarios
16
- else
17
- args.each do |file|
18
- load File.expand_path(file)
19
- end
20
- end
21
- end
22
-
23
- # Loads all scenarios from predefined paths
24
- def load_all_scenarios
25
- Dir["scenarios/**/*.rb"].each { |f| load File.expand_path(f) }
26
- end
27
-
28
- def load_shared_steps
29
- Dir["shared_steps/**/*rb"].each { |f| load File.expand_path(f) }
8
+ def start
9
+ notify_observers(:started, self)
30
10
  end
31
11
 
32
12
  # Called at the end of test running.
@@ -37,13 +17,13 @@ class Lopata::World
37
17
  end
38
18
 
39
19
  def notify_observers(event, context)
40
- @observers.each do |observer|
20
+ observers.each do |observer|
41
21
  observer.send event, context
42
22
  end
43
23
  end
44
24
 
45
25
  # Define observers based on configuration
46
- def setup_observers
47
- @observers = [Lopata::Observers::ConsoleOutputObserver.new]
26
+ def observers
27
+ @observers ||= [Lopata::Observers::ConsoleOutputObserver.new]
48
28
  end
49
29
  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.0
4
+ version: 0.1.1
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-12 00:00:00.000000000 Z
11
+ date: 2020-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -90,8 +90,8 @@ files:
90
90
  - README.md
91
91
  - exe/lopata
92
92
  - lib/lopata.rb
93
+ - lib/lopata/condition.rb
93
94
  - lib/lopata/config.rb
94
- - lib/lopata/download_dir.rb
95
95
  - lib/lopata/generators/app.rb
96
96
  - lib/lopata/generators/templates/.rspec
97
97
  - lib/lopata/generators/templates/Gemfile
@@ -100,12 +100,13 @@ files:
100
100
  - lib/lopata/generators/templates/config/initializers/capybara.rb
101
101
  - lib/lopata/generators/templates/spec/spec_helper.rb
102
102
  - lib/lopata/id.rb
103
+ - lib/lopata/loader.rb
103
104
  - lib/lopata/observers.rb
104
105
  - lib/lopata/observers/base_observer.rb
105
106
  - lib/lopata/observers/console_output_observer.rb
107
+ - lib/lopata/observers/web_logger.rb
106
108
  - lib/lopata/rspec/ar_dsl.rb
107
109
  - lib/lopata/rspec/dsl.rb
108
- - lib/lopata/rspec/formatter.rb
109
110
  - lib/lopata/rspec/role.rb
110
111
  - lib/lopata/runner.rb
111
112
  - lib/lopata/scenario.rb
@@ -136,5 +137,5 @@ requirements: []
136
137
  rubygems_version: 3.0.3
137
138
  signing_key:
138
139
  specification_version: 4
139
- summary: lopata-0.1.0
140
+ summary: lopata-0.1.1
140
141
  test_files: []
@@ -1,70 +0,0 @@
1
- module Lopata
2
- module DownloadDir
3
- RELATIVE_PATH = File.join('.', 'tmp', 'target')
4
-
5
- extend self
6
-
7
- def path
8
- @path ||= File.absolute_path(RELATIVE_PATH)
9
- end
10
-
11
- def empty!
12
- FileUtils.rm Dir.glob(File.join(path, '*'))
13
- end
14
-
15
- def ensure_exist
16
- FileUtils::mkdir_p path unless Dir.exist?(path)
17
- end
18
-
19
- def has_file?(file_name)
20
- require 'timeout'
21
- target_file = filepath(file_name)
22
- Timeout.timeout(10) do
23
- sleep 0.1 until File.exist?(target_file)
24
- true
25
- end
26
- rescue Timeout::Error
27
- false
28
- end
29
-
30
- def filepath(name)
31
- File.join(path, name)
32
- end
33
-
34
- def init_capybara
35
- target_path = path
36
- target_path = target_path.gsub('/', '\\') if Gem.win_platform?
37
-
38
- profile = Selenium::WebDriver::Firefox::Profile.new
39
- profile['browser.download.folderList'] = 2
40
- profile['browser.download.manager.showWhenStarting'] = false
41
- ensure_exist
42
- profile['browser.download.dir'] = target_path
43
- profile['browser.download.downloadDir'] = target_path
44
- profile['browser.download.defaultFolder'] = target_path
45
- profile['browser.helperApps.alwaysAsk.force'] = false
46
- profile['browser.download.useDownloadDir'] = true
47
- profile['browser.helperApps.neverAsk.saveToDisk'] =
48
- %w{
49
- application/octet-stream
50
- application/msword
51
- application/pdf
52
- application/x-pdf
53
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
54
- application/vnd.ms-excel
55
- application/xml
56
- application/json
57
- }.join(', ')
58
- profile['pdfjs.disabled'] = true
59
- profile['plugin.scan.Acrobat'] = "99.0"
60
- profile['plugin.scan.plid.all'] = false
61
-
62
- Capybara.register_driver :selenium_with_download do |app|
63
- Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
64
- end
65
-
66
- Capybara.default_driver = :selenium_with_download
67
- # Capybara.default_max_wait_time = 10
68
- end
69
- end
70
- end
@@ -1,143 +0,0 @@
1
- require 'rspec/core/formatters/base_formatter'
2
- require 'httparty'
3
- require 'json'
4
- require 'lopata/config'
5
-
6
- module Lopata
7
- module RSpec
8
- class Formatter < ::RSpec::Core::Formatters::BaseFormatter
9
- ::RSpec::Core::Formatters.register self, :start, :example_passed, :example_pending, :example_failed
10
-
11
- def start(notification)
12
- raise "Build number is not initailzed in Lopata::Config" unless Lopata::Config.build_number
13
- @client = Lopata::Client.new(Lopata::Config.build_number)
14
- @client.start(notification.count)
15
- end
16
-
17
- def example_passed(notification)
18
- @client.add_attempt(notification.example, Lopata::PASSED)
19
- end
20
-
21
- def example_failed(notification)
22
- example = notification.example
23
- backtrace = backtrace_for(notification)
24
- @client.add_attempt(example, Lopata::FAILED, error_message_for(example), backtrace)
25
- end
26
-
27
- def example_pending(notification)
28
- example = notification.example
29
- @client.add_attempt(example, Lopata::PENDING, example.execution_result.pending_message)
30
- end
31
-
32
- private
33
-
34
- def error_message_for(example)
35
- exception = example.execution_result.exception
36
- msg = ''
37
- msg << "#{exception.class.name}: " unless exception.class.name =~ /RSpec/
38
- msg << "#{exception.message.to_s}" if exception.message
39
- msg.blank? ? 'Empty message' : msg
40
- end
41
-
42
- def backtrace_for(notification)
43
- example = notification.example
44
- exception = example.execution_result.exception
45
- msg = notification.formatted_backtrace.map(&:strip).join("\n")
46
- msg << "\n"
47
- if shared_group = find_shared_group(example)
48
- msg << "# Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\" called from "
49
- msg << "#{backtrace_line(shared_group.metadata[:example_group][:location])}\n"
50
- end
51
- msg
52
- end
53
-
54
- def find_shared_group(example)
55
- group_and_parent_groups(example).find {|group| group.metadata[:shared_group_name]}
56
- end
57
-
58
- def group_and_parent_groups(example)
59
- example.example_group.parent_groups + [example.example_group]
60
- end
61
- end
62
- end
63
-
64
- PASSED = 0
65
- FAILED = 1
66
- PENDING = 2
67
-
68
- class Client
69
- include HTTParty
70
- base_uri Lopata::Config.lopata_host
71
-
72
- attr_accessor :build_number
73
-
74
- def initialize(build_number)
75
- @build_number = build_number
76
- end
77
-
78
- def start(count)
79
- @launch_id = JSON.parse(post("/projects/#{project_code}/builds/#{build_number}/launches.json", body: {total: count}).body)['id']
80
- end
81
-
82
- def add_attempt(example, status, msg = nil, backtrace = nil)
83
- test = test_id(example)
84
- request = { status: status}
85
- request[:message] = msg if msg
86
- request[:backtrace] = backtrace if backtrace
87
- post("/tests/#{test}/attempts.json", body: request)
88
- inc_finished
89
- end
90
-
91
- def test_id(example)
92
- request = {
93
- test: {
94
- project_code: project_code,
95
- title: example.full_description,
96
- scenario: example.metadata[:example_group][:full_description],
97
- build_number: build_number
98
- }
99
- }
100
- response = post("/tests.json", body: request)
101
- JSON.parse(response.body)["id"]
102
- end
103
-
104
- def to_rerun
105
- get_json("/projects/#{project_code}/builds/#{build_number}/suspects.json")
106
- end
107
-
108
- def to_full_rescan
109
- to_rerun + get_json("/projects/#{project_code}/builds/#{build_number}/failures.json")
110
- end
111
-
112
- private
113
-
114
- def get_json(url)
115
- JSON.parse(self.class.get(url).body)
116
- end
117
-
118
- def post(*args)
119
- self.class.post(*args)
120
- end
121
-
122
- def patch(*args)
123
- self.class.patch(*args)
124
- end
125
-
126
- def inc_finished
127
- @finished ||= 0
128
- @finished += 1
129
- response = patch("/launches/#{@launch_id}",
130
- body: { finished: @finished }.to_json,
131
- headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' })
132
- if response.code == 404
133
- puts 'Launch has been cancelled. Exit.'
134
- exit!
135
- end
136
- end
137
-
138
- def project_code
139
- Lopata::Config.lopata_code
140
- end
141
- end
142
- end
143
-