probedock-rspec 0.5.3 → 0.5.4

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
  SHA1:
3
- metadata.gz: 8085834c08513ed1483ffe926f80cf4ebd331652
4
- data.tar.gz: f31f332aea49f4e204f426f502684a3552a6d334
3
+ metadata.gz: 6ba3723d851863c76fd9c4e1b073b20c78d5d0cb
4
+ data.tar.gz: dda7e8ca57d12c7ee6da40a09e50e1e527bc9ef9
5
5
  SHA512:
6
- metadata.gz: 056f30e646719712bd6975d7486882c534a67755af7ae2f4d4184252359f32924b1edc3f262be7e7de5a3157a5b622b155fadb30dcba4d27c7ae8d9605be7ccc
7
- data.tar.gz: 03bfe700e0990b6f8da525f5b191d937acc38794bb715e96a246075635a21e2e2cdde830fbfdfefd1cd7c9d393abf96c8e3a14910a2f28247a15c4b6bd3ca0be
6
+ metadata.gz: d10c9793f2364be0cd064a6283d2fd77834676a090d7add0eda3d537ce716e174d611c53be761f73e32658530c0a266a98c681e5551c8037431cea6a04856ca4
7
+ data.tar.gz: 9c6e27cb99f6ecd5679d68d7a138bf8691156c2c682b5dd70758ea3709f7db2afb2d91eeaa6f012a008401332ba679fbe4f68f92ab792c203df75e04b0603fb0
data/Gemfile CHANGED
@@ -4,10 +4,7 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
6
  gem 'rspec', '~> 3.1'
7
- gem 'oj', '~> 2.1'
8
- gem 'httparty', '~> 0.13'
9
- gem 'paint', '~> 1.0'
10
- gem 'rake', '~> 10.1'
7
+ gem 'probedock-ruby', '~> 0.1'
11
8
 
12
9
  # Add dependencies to develop your gem here.
13
10
  # Include everything needed to run rake, tests, features, etc.
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 ProbeDock
1
+ Copyright (c) 2015 Probe Dock
2
2
  Copyright (c) 2012-2013 Lotaris SA
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # ProbeDock RSpec
1
+ # Probe Dock RSpec
2
2
 
3
- **RSpec probe for [ProbeDock](https://github.com/probedock/probedock).**
3
+ **RSpec probe for [Probe Dock](https://github.com/probedock/probedock).**
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/probedock-rspec.svg)](http://badge.fury.io/rb/probedock-rspec)
6
6
  [![Dependency Status](https://gemnasium.com/probedock/probedock-rspec.svg)](https://gemnasium.com/probedock/probedock-rspec)
@@ -17,7 +17,7 @@
17
17
  In your Gemfile:
18
18
 
19
19
  ```rb
20
- gem 'probedock-rspec', '~> 0.4.1'
20
+ gem 'probedock-rspec', '~> 0.5.4'
21
21
  ```
22
22
 
23
23
  Manually:
@@ -28,7 +28,7 @@ Manually:
28
28
 
29
29
  If you haven't done it already, follow the [setup procedure](#setup) below.
30
30
 
31
- To track a test with a ProbeDock test key, use RSpec metadata:
31
+ To track a test with a Probe Dock test key, use RSpec metadata:
32
32
 
33
33
  ```rb
34
34
  it "should work", probe_dock: { key: 'abcdefghijkl' } do
@@ -56,7 +56,7 @@ ProbeDockRSpec.configure do |config|
56
56
  end
57
57
  ```
58
58
 
59
- The next time you run your test suite, the RSpec probe will send the results to your ProbeDock server.
59
+ The next time you run your test suite, the RSpec probe will send the results to your Probe Dock server.
60
60
 
61
61
  ## Contributing
62
62
 
@@ -69,5 +69,5 @@ Please add a [changelog](CHANGELOG.md) entry with your name for new features and
69
69
 
70
70
  ## License
71
71
 
72
- ProbeDock RSpec is licensed under the [MIT License](http://opensource.org/licenses/MIT).
72
+ Probe Dock RSpec is licensed under the [MIT License](http://opensource.org/licenses/MIT).
73
73
  See [LICENSE.txt](LICENSE.txt) for the full license.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.3
1
+ 0.5.4
@@ -1,8 +1,9 @@
1
1
  # encoding: UTF-8
2
2
  require 'rspec'
3
+ require 'probedock-ruby'
3
4
 
4
5
  module ProbeDockRSpec
5
- VERSION = '0.5.3'
6
+ VERSION = '0.5.4'
6
7
 
7
8
  class Error < StandardError; end
8
9
  class PayloadError < Error; end
@@ -1,198 +1,19 @@
1
- require 'yaml'
2
-
3
- # Utilities to send test results to ProbeDock.
4
1
  module ProbeDockRSpec
5
2
 
6
- def self.config
7
- @config ||= Config.new.tap(&:load!)
3
+ def self.configure options = {}, &block
4
+ ProbeDockProbe.config.load! &block
5
+ setup! if options.fetch :setup, true
6
+ ProbeDockProbe.config
8
7
  end
9
8
 
10
- def self.configure options = {}
11
-
12
- yield config if block_given?
13
-
14
- config.check!
15
- config.load_warnings.each{ |w| warn Paint["ProbeDock - #{w}", :yellow] }
16
-
17
- config.setup! if options[:setup] != false
18
-
19
- config
20
- end
21
-
22
- class Config
23
- # TODO: add silent/verbose option(s)
24
- class Error < ProbeDockRSpec::Error; end
25
- attr_writer :publish, :local_mode, :cache_payload, :print_payload, :save_payload
26
- attr_reader :project, :server, :workspace, :load_warnings
27
-
28
- def initialize
29
- @servers = []
30
- @server = Server.new
31
- @project = Project.new
32
- @publish, @local_mode, @cache_payload, @print_payload, @save_payload = false, false, false, false, false
33
- @load_warnings = []
34
- end
35
-
36
- def workspace= dir
37
- @workspace = dir ? File.expand_path(dir) : nil
38
- end
9
+ private
39
10
 
40
- def servers
41
- @servers.dup
42
- end
43
-
44
- # Plugs ProbeDock utilities into RSpec.
45
- def setup!
11
+ def self.setup!
12
+ unless @setup
13
+ @setup = true
46
14
  ::RSpec.configure do |c|
47
15
  c.add_formatter Formatter
48
16
  end
49
17
  end
50
-
51
- %w(publish local_mode cache_payload print_payload save_payload).each do |name|
52
- define_method("#{name}?"){ instance_variable_get("@#{name}") }
53
- end
54
-
55
- def client_options
56
- {
57
- publish: @publish,
58
- local_mode: @local_mode,
59
- workspace: @workspace,
60
- cache_payload: @cache_payload,
61
- print_payload: @print_payload,
62
- save_payload: @save_payload
63
- }.select{ |k,v| !v.nil? }
64
- end
65
-
66
- def load!
67
-
68
- @server.clear
69
- @servers.clear
70
-
71
- @load_warnings = []
72
- return unless config = load_config_files
73
-
74
- @publish = parse_env_flag :publish, !!config[:publish]
75
- @server_name = parse_env_option(:server) || config[:server]
76
- @local_mode = parse_env_flag(:local) || !!config[:local]
77
-
78
- self.workspace = parse_env_option(:workspace) || config[:workspace]
79
- @cache_payload = parse_env_flag :cache_payload, !!config[:payload][:cache]
80
- @print_payload = parse_env_flag :print_payload, !!config[:payload][:print]
81
- @save_payload = parse_env_flag :save_payload, !!config[:payload][:save]
82
-
83
- @servers, server = build_servers config
84
-
85
- if server
86
- @server = server
87
- else
88
- @server.name = @server_name
89
- end
90
-
91
- {
92
- api_url: parse_env_option(:server_api_url),
93
- api_token: parse_env_option(:server_api_token),
94
- project_api_id: parse_env_option(:server_project_api_id)
95
- }.each{ |k,v| @server.send "#{k}=", v if v }
96
-
97
- project_options = config[:project]
98
- project_options.merge! api_id: @server.project_api_id if @server and @server.project_api_id
99
- @project.update project_options
100
-
101
- self
102
- end
103
-
104
- def check!
105
-
106
- configs = [ home_config_file, working_config_file ]
107
- actual_configs = configs.select{ |f| File.exists? f }
108
-
109
- if actual_configs.empty?
110
- @load_warnings << %|no config file found, looking for:\n #{configs.join "\n "}|
111
- end
112
-
113
- if @servers.empty?
114
- @load_warnings << "No server defined"
115
- elsif !@server_name && !@server.name
116
- @load_warnings << "No server name given"
117
- end
118
- end
119
-
120
- private
121
-
122
- def build_servers config
123
-
124
- default_server_options = { project_api_id: config[:project][:api_id] }
125
- servers = config[:servers].inject({}) do |memo,(name, options)|
126
- memo[name] = Server.new default_server_options.merge(options).merge(name: name)
127
- memo
128
- end
129
-
130
- [ servers.values, servers[@server_name.to_s.strip] ]
131
- end
132
-
133
- def load_config_files
134
-
135
- configs = [ home_config_file, working_config_file ]
136
- actual_configs = configs.select{ |f| File.exists? f }
137
- return false if actual_configs.empty?
138
-
139
- actual_configs.collect!{ |f| YAML.load_file f }
140
-
141
- actual_configs.inject({ servers: {} }) do |memo,yml|
142
- memo.merge! parse_general_options(yml)
143
-
144
- if yml['servers'].kind_of? Hash
145
- yml['servers'].each_pair do |k,v|
146
- if v.kind_of? Hash
147
- memo[:servers][k] = (memo[:servers][k] || {}).merge(parse_server_options(v))
148
- end
149
- end
150
- end
151
-
152
- memo[:payload] = (memo[:payload] || {}).merge parse_payload_options(yml['payload'])
153
- memo[:project] = (memo[:project] || {}).merge parse_project_options(yml['project'])
154
-
155
- memo
156
- end
157
- end
158
-
159
- def home_config_file
160
- File.join File.expand_path('~'), '.probedock', 'config.yml'
161
- end
162
-
163
- def working_config_file
164
- File.expand_path ENV['PROBE_DOCK_CONFIG'] || 'probedock.yml', Dir.pwd
165
- end
166
-
167
- def parse_env_flag name, default = false
168
- val = parse_env_option name
169
- val ? !!val.to_s.strip.match(/\A(1|y|yes|t|true)\Z/i) : default
170
- end
171
-
172
- def parse_env_option name
173
- var = "PROBE_DOCK_#{name.upcase}"
174
- ENV.key?(var) ? ENV[var] : nil
175
- end
176
-
177
- def parse_general_options h
178
- parse_options h, %w(publish server local workspace)
179
- end
180
-
181
- def parse_server_options h
182
- parse_options h, %w(name apiUrl apiToken apiVersion projectApiId)
183
- end
184
-
185
- def parse_payload_options h
186
- parse_options h, %w(save cache print)
187
- end
188
-
189
- def parse_project_options h
190
- parse_options h, %w(version apiId category tags tickets)
191
- end
192
-
193
- def parse_options h, keys
194
- return {} unless h.kind_of? Hash
195
- keys.inject({}){ |memo,k| memo[k.gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym] = h[k] if h.key?(k); memo }
196
- end
197
18
  end
198
19
  end
@@ -11,9 +11,9 @@ module ProbeDockRSpec
11
11
 
12
12
  def initialize output
13
13
 
14
- config = ProbeDockRSpec.config
15
- @client = Client.new config.server, config.client_options
16
- @test_run = TestRun.new config.project
14
+ config = ProbeDockProbe.config
15
+ @client = ProbeDockProbe::Client.new config.server, config.client_options
16
+ @test_run = ProbeDockProbe::TestRun.new config.project
17
17
 
18
18
  @groups = []
19
19
  end
@@ -55,14 +55,11 @@ module ProbeDockRSpec
55
55
 
56
56
  def add_result example_notification, successful
57
57
 
58
- options = {
59
- passed: successful,
60
- duration: ((Time.now - @current_time) * 1000).round
61
- }
62
-
58
+ options = MetaParser.parse example_notification.example, @groups
59
+ options.merge! passed: successful, duration: ((Time.now - @current_time) * 1000).round
63
60
  options[:message] = failure_message example_notification unless successful
64
61
 
65
- @test_run.add_result example_notification.example, @groups, options
62
+ @test_run.add_result options
66
63
  end
67
64
 
68
65
  def failure_message example_notification
@@ -74,9 +71,5 @@ module ProbeDockRSpec
74
71
  m << example_notification.formatted_backtrace.collect{ |l| " # #{l}" }.join("\n")
75
72
  end
76
73
  end
77
-
78
- def full_example_name example
79
- (@groups.collect{ |g| g.description.strip } << example.description.strip).join ' '
80
- end
81
74
  end
82
75
  end
@@ -0,0 +1,68 @@
1
+ require 'digest/sha1'
2
+
3
+ module ProbeDockRSpec
4
+ class MetaParser
5
+
6
+ def self.parse example, groups = []
7
+
8
+ options = {}
9
+
10
+ %i(key category tags tickets data).each do |attr|
11
+ options[attr] = send "extract_#{attr}", example, groups
12
+ end
13
+
14
+ name_parts = extract_name_parts example, groups
15
+ options[:name] = name_parts.join ' '
16
+ options[:fingerprint] = Digest::SHA1.hexdigest name_parts.join('|||')
17
+
18
+ # TODO: remove once Probe Dock has been migrated to use fingerprints
19
+ options[:data][:fingerprint] = options[:fingerprint]
20
+
21
+ options
22
+ end
23
+
24
+ private
25
+
26
+ def self.extract_key example, groups = []
27
+ (groups.collect{ |g| meta(g)[:key] } << meta(example)[:key]).compact.reject{ |k| k.strip.empty? }.last
28
+ end
29
+
30
+ def self.meta holder
31
+
32
+ meta = holder.metadata[:probe_dock] || {}
33
+
34
+ if meta.kind_of? String
35
+ { key: meta }
36
+ elsif meta.kind_of? Hash
37
+ meta
38
+ else
39
+ {}
40
+ end
41
+ end
42
+
43
+ def self.extract_name_parts example, groups = []
44
+ (groups.collect(&:description) << example.description).compact.collect(&:strip).reject{ |p| p.empty? }
45
+ end
46
+
47
+ def self.extract_category example, groups = []
48
+ cat = (groups.collect{ |g| meta(g)[:category] } << meta(example)[:category]).compact.last
49
+ cat ? cat.to_s : nil
50
+ end
51
+
52
+ def self.extract_tags example, groups = []
53
+ (groups.collect{ |g| wrap meta(g)[:tags] } + (wrap meta(example)[:tags])).flatten.compact.uniq.collect(&:to_s)
54
+ end
55
+
56
+ def self.extract_tickets example, groups = []
57
+ (groups.collect{ |g| wrap meta(g)[:tickets] } + (wrap meta(example)[:tickets])).flatten.compact.uniq.collect(&:to_s)
58
+ end
59
+
60
+ def self.extract_data example, groups = []
61
+ meta(example)[:data] || {}
62
+ end
63
+
64
+ def self.wrap a
65
+ a.kind_of?(Array) ? a : [ a ]
66
+ end
67
+ end
68
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: probedock-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Oulevay (Alpha Hydrae)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-27 00:00:00.000000000 Z
11
+ date: 2015-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -25,61 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: oj
28
+ name: probedock-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.1'
33
+ version: '0.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.1'
41
- - !ruby/object:Gem::Dependency
42
- name: httparty
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.13'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.13'
55
- - !ruby/object:Gem::Dependency
56
- name: paint
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '10.1'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '10.1'
40
+ version: '0.1'
83
41
  - !ruby/object:Gem::Dependency
84
42
  name: jeweler
85
43
  requirement: !ruby/object:Gem::Requirement
@@ -178,33 +136,23 @@ dependencies:
178
136
  - - "~>"
179
137
  - !ruby/object:Gem::Version
180
138
  version: '0.8'
181
- description: RSpec client to publish test results to ProbeDock, a test tracking and
139
+ description: RSpec client to publish test results to Probe Dock, a test tracking and
182
140
  analysis server.
183
141
  email: simon.oulevay@gmail.com
184
142
  executables: []
185
143
  extensions: []
186
144
  extra_rdoc_files:
187
- - CHANGELOG.md
188
145
  - LICENSE.txt
189
146
  - README.md
190
147
  files:
191
- - CHANGELOG.md
192
148
  - Gemfile
193
149
  - LICENSE.txt
194
150
  - README.md
195
151
  - VERSION
196
152
  - lib/probe_dock_rspec.rb
197
- - lib/probe_dock_rspec/cache.rb
198
- - lib/probe_dock_rspec/client.rb
199
153
  - lib/probe_dock_rspec/config.rb
200
154
  - lib/probe_dock_rspec/formatter.rb
201
- - lib/probe_dock_rspec/project.rb
202
- - lib/probe_dock_rspec/server.rb
203
- - lib/probe_dock_rspec/tasks.rb
204
- - lib/probe_dock_rspec/test_payload.rb
205
- - lib/probe_dock_rspec/test_result.rb
206
- - lib/probe_dock_rspec/test_run.rb
207
- - lib/probe_dock_rspec/uid.rb
155
+ - lib/probe_dock_rspec/meta_parser.rb
208
156
  - lib/probedock-rspec.rb
209
157
  homepage: https://github.com/probedock/probedock-rspec
210
158
  licenses:
@@ -226,8 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
174
  version: '0'
227
175
  requirements: []
228
176
  rubyforge_project:
229
- rubygems_version: 2.4.6
177
+ rubygems_version: 2.4.8
230
178
  signing_key:
231
179
  specification_version: 4
232
- summary: RSpec client to publish test results to ProbeDock.
180
+ summary: RSpec client to publish test results to Probe Dock.
233
181
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,13 +0,0 @@
1
- # Changelog
2
-
3
- ## v0.4.0 - September 11, 2014
4
-
5
- * Upgraded to RSpec 3.1.
6
-
7
- ## v0.3.1 - December 13, 2013
8
-
9
- * The `servers` key in the YAML configuration file is now a hash instead of an array.
10
-
11
- ## v0.3.0 - October 25, 2013
12
-
13
- * First open source version.
@@ -1,61 +0,0 @@
1
-
2
- module ProbeDockRSpec
3
-
4
- class Cache
5
-
6
- class Error < ProbeDockRSpec::Error; end
7
-
8
- def initialize options = {}
9
- @tests = {}
10
- @workspace, @server_name, @project_api_id = options[:workspace], options[:server_name], options[:project_api_id]
11
- end
12
-
13
- def save test_run
14
- validate!
15
-
16
- @tests = { @project_api_id => @tests[@project_api_id] || {} }
17
- test_run.results.select(&:key).each{ |r| @tests[@project_api_id][r.key] = test_result_hash(r) }
18
-
19
- FileUtils.mkdir_p File.dirname(cache_file)
20
- File.open(cache_file, 'w'){ |f| f.write Oj.dump(@tests, mode: :strict) }
21
-
22
- self
23
- end
24
-
25
- def load
26
- validate!
27
-
28
- @tests = if File.exists? cache_file
29
- Oj.load(File.read(cache_file), mode: :strict) rescue {}
30
- else
31
- {}
32
- end
33
-
34
- self
35
- end
36
-
37
- def known? test_result
38
- test_result.key && !!@tests[@project_api_id] && !!@tests[@project_api_id][test_result.key]
39
- end
40
-
41
- def stale? test_result
42
- !!@tests[@project_api_id] && test_result_hash(test_result) != @tests[@project_api_id][test_result.key]
43
- end
44
-
45
- private
46
-
47
- def validate!
48
- required = { "workspace" => @workspace, "server name" => @server_name, "project API identifier" => @project_api_id }
49
- missing = required.keys.select{ |k| !required[k] }
50
- raise Error.new("Missing cache options: #{missing.join ', '}") if missing.any?
51
- end
52
-
53
- def test_result_hash r
54
- Digest::SHA2.hexdigest "#{r.name} || #{r.category} || #{r.tags.collect(&:to_s).sort.join(' ')} || #{r.tickets.collect(&:to_s).sort.join(' ')}"
55
- end
56
-
57
- def cache_file
58
- @cache_file ||= File.join(@workspace, 'rspec', 'servers', @server_name, 'cache.json')
59
- end
60
- end
61
- end
@@ -1,120 +0,0 @@
1
-
2
- module ProbeDockRSpec
3
-
4
- class Client
5
-
6
- def initialize server, options = {}
7
-
8
- @server = server
9
- @publish, @local_mode, @workspace = options[:publish], options[:local_mode], options[:workspace]
10
- @cache_payload, @print_payload, @save_payload = options[:cache_payload], options[:print_payload], options[:save_payload]
11
-
12
- cache_options = { workspace: @workspace }
13
- cache_options.merge! server_name: @server.name, project_api_id: @server.project_api_id if @server
14
- @cache = Cache.new cache_options
15
-
16
- @uid = UID.new workspace: @workspace
17
- end
18
-
19
- def process test_run
20
-
21
- return fail "No server to publish results to" if !@server
22
-
23
- test_run.uid = @uid.load_uid
24
-
25
- payload_options = {}
26
-
27
- cache_enabled = @cache_payload && load_cache
28
- payload_options[:cache] = @cache if cache_enabled
29
-
30
- return false unless payload = build_payload(test_run, payload_options)
31
-
32
- published = if !@publish
33
- puts Paint["ProbeDock - Publishing disabled", :yellow]
34
- false
35
- elsif publish_payload payload
36
- @cache.save test_run if cache_enabled
37
- true
38
- else
39
- false
40
- end
41
-
42
- save_payload payload if @save_payload
43
- print_payload payload if @print_payload
44
-
45
- puts
46
-
47
- published
48
- end
49
-
50
- private
51
-
52
- def build_payload test_run, options = {}
53
- begin
54
- TestPayload.new(test_run).to_h options
55
- rescue PayloadError => e
56
- fail e.message
57
- end
58
- end
59
-
60
- def fail msg, type = :error
61
- styles = { warning: [ :yellow ], error: [ :bold, :red ] }
62
- warn Paint["ProbeDock - #{msg}", *styles[type]]
63
- false
64
- end
65
-
66
- def load_cache
67
- begin
68
- @cache.load
69
- rescue Cache::Error => e
70
- warn Paint["ProbeDock - #{e.message}", :yellow]
71
- false
72
- end
73
- end
74
-
75
- def print_payload payload
76
- puts Paint['ProbeDock - Printing payload...', :yellow]
77
- begin
78
- puts JSON.pretty_generate(payload)
79
- rescue
80
- puts payload.inspect
81
- end
82
- end
83
-
84
- def save_payload payload
85
-
86
- missing = { "workspace" => @workspace, "server" => @server }.inject([]){ |memo,(k,v)| !v ? memo << k : memo }
87
- return fail "Cannot save payload without a #{missing.join ' and '}" if missing.any?
88
-
89
- FileUtils.mkdir_p File.dirname(payload_file)
90
- File.open(payload_file, 'w'){ |f| f.write Oj.dump(payload, mode: :strict) }
91
- end
92
-
93
- def payload_file
94
- @payload_file ||= File.join(@workspace, 'rspec', 'servers', @server.name, 'payload.json')
95
- end
96
-
97
- def publish_payload payload
98
-
99
- puts Paint["ProbeDock - Sending payload to #{@server.api_url}...", :magenta]
100
-
101
- begin
102
- if @local_mode
103
- puts Paint['ProbeDock - LOCAL MODE: not actually sending payload.', :yellow]
104
- else
105
- @server.upload payload
106
- end
107
- puts Paint["ProbeDock - Done!", :green]
108
- true
109
- rescue Server::Error => e
110
- warn Paint["ProbeDock - Upload failed!", :red, :bold]
111
- warn Paint["ProbeDock - #{e.message}", :red, :bold]
112
- if e.response
113
- warn Paint["ProbeDock - Dumping response body...", :red, :bold]
114
- warn e.response.body
115
- end
116
- false
117
- end
118
- end
119
- end
120
- end
@@ -1,30 +0,0 @@
1
- module ProbeDockRSpec
2
-
3
- class Project
4
- attr_accessor :version, :api_id, :category, :tags, :tickets
5
-
6
- def initialize options = {}
7
- update options
8
- end
9
-
10
- def update options = {}
11
- %w(version api_id category).each do |k|
12
- instance_variable_set "@#{k}", options[k.to_sym] ? options[k.to_sym].to_s : nil if options.key? k.to_sym
13
- end
14
- @tags = wrap(options[:tags]).compact if options.key? :tags
15
- @tickets = wrap(options[:tickets]).compact if options.key? :tickets
16
- end
17
-
18
- def validate!
19
- required = { "version" => @version, "API identifier" => @api_id }
20
- missing = required.inject([]){ |memo,(k,v)| v.to_s.strip.length <= 0 ? memo << k : memo }
21
- raise PayloadError.new("Missing project options: #{missing.join ', '}") if missing.any?
22
- end
23
-
24
- private
25
-
26
- def wrap a
27
- a.kind_of?(Array) ? a : [ a ]
28
- end
29
- end
30
- end
@@ -1,59 +0,0 @@
1
- require 'oj'
2
- require 'httparty'
3
-
4
- module ProbeDockRSpec
5
-
6
- class Server
7
- attr_accessor :name, :api_url, :api_token, :project_api_id
8
-
9
- class Error < ProbeDockRSpec::Error
10
- attr_reader :response
11
-
12
- def initialize msg, response = nil
13
- super msg
14
- @response = response
15
- end
16
- end
17
-
18
- def initialize options = {}
19
- @name = options[:name].to_s.strip if options[:name]
20
- @api_url = options[:api_url].to_s if options[:api_url]
21
- @api_token = options[:api_token].to_s if options[:api_token]
22
- @project_api_id = options[:project_api_id].to_s if options[:project_api_id]
23
- end
24
-
25
- def clear
26
- @name = nil
27
- @api_url = nil
28
- @api_token = nil
29
- @project_api_id = nil
30
- end
31
-
32
- def upload payload
33
- validate!
34
-
35
- body = Oj.dump payload, mode: :strict
36
- res = HTTParty.post payload_uri, body: body, headers: payload_headers
37
-
38
- if res.code != 202
39
- raise Error.new("Expected HTTP 202 Accepted when submitting payload, got #{res.code}", res)
40
- end
41
- end
42
-
43
- private
44
-
45
- def validate!
46
- required = { "name" => @name, "apiUrl" => @api_url, "apiToken" => @api_token }
47
- missing = required.inject([]){ |memo,(k,v)| v.to_s.strip.length <= 0 ? memo << k : memo }
48
- raise Error.new("Server #{@name} is missing the following options: #{missing.join ', '}") if missing.any?
49
- end
50
-
51
- def payload_headers
52
- { 'Authorization' => "Bearer #{@api_token}", 'Content-Type' => 'application/vnd.probedock.payload.v1+json' }
53
- end
54
-
55
- def payload_uri
56
- "#{@api_url}/publish"
57
- end
58
- end
59
- end
@@ -1,62 +0,0 @@
1
- require 'fileutils'
2
- require 'rake/tasklib'
3
-
4
- module ProbeDockRSpec
5
-
6
- class Tasks < ::Rake::TaskLib
7
-
8
- def initialize
9
-
10
- namespace :spec do
11
-
12
- namespace 'probedock' do
13
-
14
- desc "Generate a test run UID to group test results in ProbeDock (stored in an environment variable)"
15
- task :uid do
16
- trace do
17
- uid = uid_manager.generate_uid_to_env
18
- puts Paint["ProbeDock - Generated UID for test run: #{uid}", :cyan]
19
- end
20
- end
21
-
22
- namespace :uid do
23
-
24
- desc "Generate a test run UID to group test results in ProbeDock (stored in a file)"
25
- task :file do
26
- trace do
27
- uid = uid_manager.generate_uid_to_file
28
- puts Paint["ProbeDock - Generated UID for test run: #{uid}", :cyan]
29
- end
30
- end
31
-
32
- desc "Clean the test run UID (file and environment variable)"
33
- task :clean do
34
- trace do
35
- uid_manager.clean_uid
36
- puts Paint["ProbeDock - Cleaned test run UID", :cyan]
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
43
-
44
- private
45
-
46
- def trace &block
47
- if Rake.application.options.trace
48
- block.call
49
- else
50
- begin
51
- block.call
52
- rescue UID::Error => e
53
- warn Paint["ProbeDock - #{e.message}", :red]
54
- end
55
- end
56
- end
57
-
58
- def uid_manager
59
- UID.new ProbeDockRSpec.config.client_options
60
- end
61
- end
62
- end
@@ -1,18 +0,0 @@
1
- require 'fileutils'
2
- require 'digest/sha2'
3
-
4
- module ProbeDockRSpec
5
-
6
- class TestPayload
7
-
8
- class Error < ProbeDockRSpec::Error; end
9
-
10
- def initialize run
11
- @run = run
12
- end
13
-
14
- def to_h options = {}
15
- @run.to_h options
16
- end
17
- end
18
- end
@@ -1,119 +0,0 @@
1
-
2
- module ProbeDockRSpec
3
-
4
- class TestResult
5
- attr_reader :key, :name, :category, :tags, :tickets, :data, :duration, :message
6
-
7
- def initialize project, example, groups = [], options = {}
8
-
9
- @category = project.category
10
- @tags = project.tags
11
- @tickets = project.tickets
12
-
13
- @grouped = extract_grouped example, groups
14
-
15
- [ :key, :name, :category, :tags, :tickets, :data ].each do |attr|
16
- instance_variable_set "@#{attr}".to_sym, send("extract_#{attr}".to_sym, example, groups)
17
- end
18
-
19
- @passed = !!options[:passed]
20
- @duration = options[:duration]
21
- @message = options[:message]
22
- end
23
-
24
- def passed?
25
- @passed
26
- end
27
-
28
- def grouped?
29
- @grouped
30
- end
31
-
32
- def update options = {}
33
- @passed &&= options[:passed]
34
- @duration += options[:duration]
35
- @message = [ @message, options[:message] ].select{ |m| m }.join("\n\n") if options[:message]
36
- end
37
-
38
- def to_h options = {}
39
- {
40
- 'p' => @passed,
41
- 'd' => @duration
42
- }.tap do |h|
43
-
44
- h['k'] = @key if @key
45
- h['m'] = @message if @message
46
-
47
- cache = options[:cache]
48
- first = !cache || !cache.known?(self)
49
- stale = !first && cache.stale?(self)
50
- h['n'] = @name if stale or first
51
- h['c'] = @category if stale or (first and @category)
52
- h['g'] = @tags if stale or (first and !@tags.empty?)
53
- h['t'] = @tickets if stale or (first and !@tickets.empty?)
54
- h['a'] = @data if @data # FIXME: cache custom data
55
- end
56
- end
57
-
58
- def self.extract_grouped example, groups = []
59
- !!groups.collect{ |g| meta(g)[:grouped] }.compact.last
60
- end
61
-
62
- def self.extract_key example, groups = []
63
- (groups.collect{ |g| meta(g)[:key] } << meta(example)[:key]).compact.reject{ |k| k.strip.empty? }.last
64
- end
65
-
66
- def self.meta holder
67
- meta = holder.metadata[:probe_dock] || {}
68
- if meta.kind_of? String
69
- { key: meta }
70
- elsif meta.kind_of? Hash
71
- meta
72
- else
73
- {}
74
- end
75
- end
76
-
77
- private
78
-
79
- def meta *args
80
- self.class.meta *args
81
- end
82
-
83
- def extract_grouped *args
84
- self.class.extract_grouped *args
85
- end
86
-
87
- def extract_key *args
88
- self.class.extract_key *args
89
- end
90
-
91
- def extract_name example, groups = []
92
- parts = groups.dup
93
- parts = parts[0, parts.index{ |p| meta(p)[:grouped] } + 1] if @grouped
94
- parts << example unless @grouped
95
- parts.collect{ |p| p.description.strip }.join ' '
96
- end
97
-
98
- def extract_category example, groups = []
99
- cat = (groups.collect{ |g| meta(g)[:category] }.unshift(@category) << meta(example)[:category]).compact.last
100
- cat ? cat.to_s : nil
101
- end
102
-
103
- def extract_tags example, groups = []
104
- (wrap(@tags) + groups.collect{ |g| wrap meta(g)[:tags] } + (wrap meta(example)[:tags])).flatten.compact.uniq.collect(&:to_s)
105
- end
106
-
107
- def extract_tickets example, groups = []
108
- (wrap(@tickets) + groups.collect{ |g| wrap meta(g)[:tickets] } + (wrap meta(example)[:tickets])).flatten.compact.uniq.collect(&:to_s)
109
- end
110
-
111
- def extract_data example, groups = []
112
- meta(example)[:data]
113
- end
114
-
115
- def wrap a
116
- a.kind_of?(Array) ? a : [ a ]
117
- end
118
- end
119
- end
@@ -1,85 +0,0 @@
1
-
2
- module ProbeDockRSpec
3
-
4
- class TestRun
5
- attr_reader :results, :project
6
- attr_accessor :duration, :uid
7
-
8
- def initialize project
9
- @results = []
10
- @project = project
11
- end
12
-
13
- def add_result example, groups = [], options = {}
14
- if TestResult.extract_grouped(example, groups) and (existing_result = @results.find{ |r| r.grouped? && r.key == TestResult.extract_key(example, groups) })
15
- existing_result.update options
16
- else
17
- @results << TestResult.new(@project, example, groups, options)
18
- end
19
- end
20
-
21
- def results_without_key
22
- @results.select{ |r| !r.key or r.key.to_s.strip.empty? }
23
- end
24
-
25
- def results_by_key
26
- @results.inject({}) do |memo,r|
27
- (memo[r.key] ||= []) << r unless !r.key or r.key.to_s.strip.empty?
28
- memo
29
- end
30
- end
31
-
32
- def to_h options = {}
33
- validate!
34
-
35
- {
36
- 'projectId' => @project.api_id,
37
- 'version' => @project.version,
38
- 'duration' => @duration,
39
- 'results' => @results.collect{ |r| r.to_h options }
40
- }.tap do |h|
41
- h['reports'] = [ { 'uid' => @uid } ] if @uid
42
- end
43
- end
44
-
45
- private
46
-
47
- def validate!
48
- # TODO: validate duration
49
-
50
- raise PayloadError.new("Missing project") if !@project
51
- @project.validate!
52
-
53
- # FIXME: log info/warnings
54
- #validate_no_results_without_key
55
- #validate_no_duplicate_keys
56
- end
57
-
58
- def validate_no_duplicate_keys
59
-
60
- results_with_duplicate_key = results_by_key.select{ |k,r| r.length >= 2 }
61
- return if results_with_duplicate_key.none?
62
-
63
- msg = "the following keys are used by multiple test results".tap do |s|
64
- results_with_duplicate_key.each_pair do |key,results|
65
- s << "\n - #{key}"
66
- results.each{ |r| s << "\n - #{r.name}" }
67
- end
68
- end
69
-
70
- raise PayloadError.new(msg)
71
- end
72
-
73
- def validate_no_results_without_key
74
-
75
- keyless = results_without_key
76
- return if keyless.empty?
77
-
78
- msg = "the following test results are missing a key".tap do |s|
79
- keyless.each{ |r| s << "\n - #{r.name}" }
80
- end
81
-
82
- raise PayloadError.new(msg)
83
- end
84
- end
85
- end
@@ -1,60 +0,0 @@
1
- require 'securerandom'
2
-
3
- module ProbeDockRSpec
4
-
5
- class UID
6
- ENVIRONMENT_VARIABLE = 'PROBE_DOCK_TEST_REPORT_UID'
7
-
8
- class Error < ProbeDockRSpec::Error; end
9
-
10
- def initialize options = {}
11
- @workspace = options[:workspace]
12
- end
13
-
14
- def load_uid
15
- if env_var
16
- return env_var
17
- elsif @workspace
18
- current_uid
19
- end
20
- end
21
-
22
- def generate_uid_to_file
23
- raise Error.new("No workspace specified; cannot save test run UID") if !@workspace
24
- generate_uid.tap{ |uid| save_uid uid }
25
- end
26
-
27
- def generate_uid_to_env
28
- raise Error.new("$PROBE_DOCK_TEST_REPORT_UID is already defined") if env_var
29
- ENV[ENVIRONMENT_VARIABLE] = generate_uid
30
- end
31
-
32
- def clean_uid
33
- ENV.delete ENVIRONMENT_VARIABLE
34
- FileUtils.remove_entry_secure uid_file if @workspace and File.exists?(uid_file)
35
- end
36
-
37
- private
38
-
39
- def save_uid uid
40
- FileUtils.mkdir_p File.dirname(uid_file)
41
- File.open(uid_file, 'w'){ |f| f.write uid }
42
- end
43
-
44
- def env_var
45
- ENV[ENVIRONMENT_VARIABLE]
46
- end
47
-
48
- def current_uid
49
- File.file?(uid_file) ? File.read(uid_file) : nil
50
- end
51
-
52
- def uid_file
53
- @uid_file ||= File.join(@workspace, 'uid')
54
- end
55
-
56
- def generate_uid
57
- "#{Time.now.utc.strftime '%Y%m%d%H%M%S'}-#{SecureRandom.uuid}"
58
- end
59
- end
60
- end