elastic_results 1.0.2
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 +7 -0
- data/.gitignore +86 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/LICENSE +22 -0
- data/README.md +124 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/elastic_results.gemspec +33 -0
- data/lib/elastic_results/cucumber.rb +70 -0
- data/lib/elastic_results/result.rb +50 -0
- data/lib/elastic_results/rspec.rb +52 -0
- data/lib/elastic_results/setup/coverage.json +86 -0
- data/lib/elastic_results/setup/test_results.json +95 -0
- data/lib/elastic_results/simplecov.rb +49 -0
- data/lib/elastic_results/version.rb +4 -0
- data/lib/elastic_results.rb +176 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 99161c14e7dbbdf95b0b78a312fb3c2c4e1cc7de
|
4
|
+
data.tar.gz: 3db34b799da012ecc7912dbc3bdff3f4675d94a2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b505765a9fd4d5600e2eb33b2808cc252d6b0badce330a6fe08178ff551446a7381ffa1435e5f3bf316b2b5679bb0b49818a72c00ec4905f93a7d29682c80899
|
7
|
+
data.tar.gz: 352701d01b84d4a9c6db7d79aba5f220f796f7bc2be5872f2934fb92ec59ef250f4c2cdd71507008f670d889ee4efa0484bba4930959a6a7de49fe7a7e625fb0
|
data/.gitignore
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
### JetBrains template
|
2
|
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
3
|
+
|
4
|
+
*.iml
|
5
|
+
|
6
|
+
## Directory-based project format:
|
7
|
+
.idea/
|
8
|
+
# if you remove the above rule, at least ignore the following:
|
9
|
+
|
10
|
+
# User-specific stuff:
|
11
|
+
# .idea/workspace.xml
|
12
|
+
# .idea/tasks.xml
|
13
|
+
# .idea/dictionaries
|
14
|
+
|
15
|
+
# Sensitive or high-churn files:
|
16
|
+
# .idea/dataSources.ids
|
17
|
+
# .idea/dataSources.xml
|
18
|
+
# .idea/sqlDataSources.xml
|
19
|
+
# .idea/dynamic.xml
|
20
|
+
# .idea/uiDesigner.xml
|
21
|
+
|
22
|
+
# Gradle:
|
23
|
+
# .idea/gradle.xml
|
24
|
+
# .idea/libraries
|
25
|
+
|
26
|
+
# Mongo Explorer plugin:
|
27
|
+
# .idea/mongoSettings.xml
|
28
|
+
|
29
|
+
## File-based project format:
|
30
|
+
*.ipr
|
31
|
+
*.iws
|
32
|
+
|
33
|
+
## Plugin-specific files:
|
34
|
+
|
35
|
+
# IntelliJ
|
36
|
+
/out/
|
37
|
+
|
38
|
+
# mpeltonen/sbt-idea plugin
|
39
|
+
.idea_modules/
|
40
|
+
|
41
|
+
# JIRA plugin
|
42
|
+
atlassian-ide-plugin.xml
|
43
|
+
|
44
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
45
|
+
com_crashlytics_export_strings.xml
|
46
|
+
crashlytics.properties
|
47
|
+
crashlytics-build.properties
|
48
|
+
### Ruby template
|
49
|
+
*.gem
|
50
|
+
*.rbc
|
51
|
+
/.config
|
52
|
+
/coverage/
|
53
|
+
/InstalledFiles
|
54
|
+
/pkg/
|
55
|
+
/spec/reports/
|
56
|
+
/spec/examples.txt
|
57
|
+
/test/tmp/
|
58
|
+
/test/version_tmp/
|
59
|
+
/tmp/
|
60
|
+
|
61
|
+
## Specific to RubyMotion:
|
62
|
+
.dat*
|
63
|
+
.repl_history
|
64
|
+
build/
|
65
|
+
|
66
|
+
## Documentation cache and generated files:
|
67
|
+
/.yardoc/
|
68
|
+
/_yardoc/
|
69
|
+
/doc/
|
70
|
+
/rdoc/
|
71
|
+
|
72
|
+
## Environment normalisation:
|
73
|
+
/.bundle/
|
74
|
+
/vendor/bundle
|
75
|
+
/lib/bundler/man/
|
76
|
+
|
77
|
+
# for a library or gem, you might want to ignore these files since the code is
|
78
|
+
# intended to run in multiple environments; otherwise, check them in:
|
79
|
+
# Gemfile.lock
|
80
|
+
# .ruby-version
|
81
|
+
# .ruby-gemset
|
82
|
+
|
83
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
84
|
+
.rvmrc
|
85
|
+
|
86
|
+
ru# Created by .ignore support plugin (hsz.mobi)
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
elastic_results (0.1.0)
|
5
|
+
elasticsearch
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
elasticsearch (1.0.15)
|
11
|
+
elasticsearch-api (= 1.0.15)
|
12
|
+
elasticsearch-transport (= 1.0.15)
|
13
|
+
elasticsearch-api (1.0.15)
|
14
|
+
multi_json
|
15
|
+
elasticsearch-transport (1.0.15)
|
16
|
+
faraday
|
17
|
+
multi_json
|
18
|
+
faraday (0.9.1)
|
19
|
+
multipart-post (>= 1.2, < 3)
|
20
|
+
multi_json (1.11.2)
|
21
|
+
multipart-post (2.0.0)
|
22
|
+
rake (10.4.2)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
bundler (~> 1.10)
|
29
|
+
elastic_results!
|
30
|
+
rake (~> 10.0)
|
31
|
+
|
32
|
+
BUNDLED WITH
|
33
|
+
1.10.6
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 CoverMyMeds
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# ElasticResults
|
2
|
+
|
3
|
+
Store the results of your test runs in Elasticsearch via custom formatters.
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'elastic_results'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install elastic_results
|
21
|
+
|
22
|
+
## Cucumber Usage
|
23
|
+
Add this line to your features/support/env.rb file:
|
24
|
+
```ruby
|
25
|
+
require 'elastic_results/cucumber'
|
26
|
+
```
|
27
|
+
|
28
|
+
Tell cucumber to use elastic_results:
|
29
|
+
```
|
30
|
+
bundle exec cucumber --format ElasticResults::Cucumber::Formatter
|
31
|
+
```
|
32
|
+
|
33
|
+
Tell cucumber to use elastic_results but still give normal output:
|
34
|
+
```
|
35
|
+
bundle exec cucumber --format pretty --format ElasticResults::Cucumber::Formatter -o /dev/null
|
36
|
+
```
|
37
|
+
|
38
|
+
Make this the default by adding the following to config/cucumber.yml
|
39
|
+
```
|
40
|
+
default: --format pretty --format ElasticResults::Cucumber::Formatter -o /dev/null
|
41
|
+
```
|
42
|
+
|
43
|
+
## RSpec Usage
|
44
|
+
Add this line to your spec_helper.rb file:
|
45
|
+
```ruby
|
46
|
+
require 'elastic_results/rspec'
|
47
|
+
```
|
48
|
+
|
49
|
+
Tell rspec to use elastic_results:
|
50
|
+
```
|
51
|
+
bundle exec rspec -r 'elastic_results/rspec' --format ElasticResults::RSpec::Formatter
|
52
|
+
```
|
53
|
+
|
54
|
+
Tell rspec to use elastic_results but still give normal output:
|
55
|
+
```
|
56
|
+
bundle exec rspec -r 'elastic_results/rspec' --format ElasticResults::RSpec::Formatter --format progress
|
57
|
+
```
|
58
|
+
|
59
|
+
Make this the default by adding the following to spec_helper.rb
|
60
|
+
```ruby
|
61
|
+
RSpec.configure do |config|
|
62
|
+
config.add_formatter 'ElasticResults::RSpec::Formatter'
|
63
|
+
config.add_formatter 'progress'
|
64
|
+
# the rest of your rspec configuration
|
65
|
+
end
|
66
|
+
```
|
67
|
+
Then run rspec as normal.
|
68
|
+
|
69
|
+
|
70
|
+
## SimpleCov Usage
|
71
|
+
Add this lines to your spec_helper.rb file:
|
72
|
+
```ruby
|
73
|
+
require 'elastic_results/simplecov'
|
74
|
+
SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, ElasticResults::SimpleCov::Formatter]
|
75
|
+
```
|
76
|
+
Then run simplecov as normal.
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
## Configuration
|
81
|
+
elastic_results exposes several configuration points that can be set via environment variables or by accssing them on the ElasticResults module:
|
82
|
+
|
83
|
+
| ENV | ElasticResults | Default | Notes |
|
84
|
+
|--------------------|-------------------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
85
|
+
| ES_URL | es_url | http://localhost | The URL where elasticsearch can be reached |
|
86
|
+
| ES_INDEX_RESULT | es_index_result | test_results-YYYY-MM-DD | The index to post test results to. The default uses a prefix of test_results and a suffix of today's date |
|
87
|
+
| ES_TYPE_RESULT | es_type_result | test_result | The data type to use for test results. |
|
88
|
+
| ES_INDEX_COVERAGE | es_index_coverage | coverage-YYYY-MM-DD | The index to post coverage data to. The default uses a prefix of coverage and a suffix of today's date |
|
89
|
+
| ES_TYPE_COVERAGE | es_type_coverage | simplecov | The data type to use for coverage data. |
|
90
|
+
| ES_LOG | es_log | ENV['DEBUG'] | Log calls to elasticsearch to STDOUT? (useful for debugging elastic_results) |
|
91
|
+
| SUITE_NAME | suite_name | Dir.pwd | The name of your suite. If not given, it will be guessed using the name of the current folder when you launch your tests. |
|
92
|
+
| SUITE_TYPE | suite_type | integration | The type of suite you're running. i.e. unit, integration, regression, etc |
|
93
|
+
| GIT_COMMIT | | Output of: git rev-parse HEAD | The git revision being tested. Jenkins will set this in CI, otherwise it's pulled from git. |
|
94
|
+
| GIT_URL | | Output of: git config --get remote.origin.url | The url to the git repo being used. Jenkins will set this in CI, otherwise it's pulled from git. |
|
95
|
+
| GIT_BRANCH | | Output of: git rev-parse --abbrev-ref HEAD | The git branch being used. Jenkins will set this in CI, otherwise it's pulled from git. |
|
96
|
+
| TEAM_NAME | team_name | ??? | The name of your team. This makes it possible to slice your results easier. |
|
97
|
+
| BUILD_URL | | | The url to your Jenkins build if any. Set by Jenkins. |
|
98
|
+
| NODE_NAME | | Socket.gethostname | The node that ran the test. Set by Jenkins, or pulled from the machine. |
|
99
|
+
| BUILD_NUMBER | | MMDDYYHHMMSSUU | The jenkins build number. If not present, a fake build number will be built using the current date/time down to the millisecond. |
|
100
|
+
| JOB_NAME | | | The jenkins job name. |
|
101
|
+
| BUILD_TAG | | | The jenkins build tag. |
|
102
|
+
| TEST_ENV/RAILS_ENV | | | The enivironment the tests were run against. Will use TEST_ENV if present, otherwise will use RAILS_ENV |
|
103
|
+
| | use_unsafe_index | true if WebMock is defined, otherwise false | If true, validation of the SSL cert for the elasticsearch host will be skipped. Useful when your testing tools break things. |
|
104
|
+
|
105
|
+
|
106
|
+
## Example config block:
|
107
|
+
```ruby
|
108
|
+
ElasticResults.team_name = 'MyTeam - MySubTeam'
|
109
|
+
ElasticResults.suite_type = 'unit'
|
110
|
+
ElasticResults.kibana_url = 'https://kibana.mycompany.com'
|
111
|
+
ElasticResults.es_url = %w(https://es1.mycompany.net:9200 https://es1.mycompany.net:9200).sample
|
112
|
+
```
|
113
|
+
|
114
|
+
|
115
|
+
## Development
|
116
|
+
|
117
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
118
|
+
|
119
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/covermymeds/elastic_results
|
124
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'elastic_results'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'elastic_results/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'elastic_results'
|
8
|
+
spec.version = ElasticResults::VERSION
|
9
|
+
spec.authors = ['Donavan Stanley']
|
10
|
+
spec.email = ['dstanley@covermymeds.com']
|
11
|
+
|
12
|
+
spec.summary = 'Formatters to shove test results into elastic search'
|
13
|
+
spec.homepage = 'https://github.com/covermymeds/elastic_results'
|
14
|
+
|
15
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
16
|
+
# delete this section to allow pushing this gem to any host.
|
17
|
+
if spec.respond_to?(:metadata)
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
19
|
+
else
|
20
|
+
fail 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
21
|
+
end
|
22
|
+
|
23
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'pry'
|
31
|
+
spec.add_dependency 'elasticsearch'
|
32
|
+
spec.add_dependency 'googl'
|
33
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'cucumber/formatter/gherkin_formatter_adapter'
|
2
|
+
require 'gherkin/formatter/argument'
|
3
|
+
require 'gherkin/formatter/json_formatter'
|
4
|
+
require 'elastic_results'
|
5
|
+
require 'elasticsearch'
|
6
|
+
require 'time'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
module ElasticResults
|
10
|
+
# Namespace for cucumber related stuff
|
11
|
+
module Cucumber
|
12
|
+
# Replacement for the stock Json formatter that outputs to elasticsearch
|
13
|
+
class JSONFormatter < ::Gherkin::Formatter::JSONFormatter
|
14
|
+
def initialize
|
15
|
+
@feature_hashes = []
|
16
|
+
@current_step_or_hook = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def eof
|
20
|
+
feature_hash = @feature_hashes.last
|
21
|
+
feature_hash['elements'].each do |scenario_hash|
|
22
|
+
record_scenario feature_hash, scenario_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def done
|
27
|
+
ElasticResults.write_urls
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def record_scenario(feature_hash, scenario_hash)
|
33
|
+
ElasticResults.index_result result_for(feature_hash, scenario_hash)
|
34
|
+
end
|
35
|
+
|
36
|
+
def result_for(feature_hash, scenario_hash)
|
37
|
+
Result.new.tap do |res|
|
38
|
+
res.id = scenario_hash['id']
|
39
|
+
res.feature_name = feature_hash['name']
|
40
|
+
res.scenario_name = scenario_hash['name']
|
41
|
+
res.uri = feature_hash['uri']
|
42
|
+
|
43
|
+
|
44
|
+
res.tags.append(feature_hash['tags'].map { |t| t['name'] }) unless feature_hash['tags'].nil?
|
45
|
+
|
46
|
+
|
47
|
+
res.tags.append(scenario_hash['tags'].map { |t| t['name'] }) unless scenario_hash['tags'].nil?
|
48
|
+
|
49
|
+
# Cucumber stores times in nanoseconds for each step, because that's SUPER useful!
|
50
|
+
res.runtime = scenario_hash['steps'].map { |s| s['result']['duration'] }.reduce { |a, e| a + e } / 1_000_000_000.0
|
51
|
+
|
52
|
+
failing_step = scenario_hash['steps'].find { |step| !step['result'].nil? && step['result']['status'] == :failed }
|
53
|
+
unless failing_step.nil?
|
54
|
+
res.exception_msg = failing_step['result']['error_message']
|
55
|
+
res.exception_class = res.exception_msg =~ /ExpectationNotMetError/ ? 'ExpectationNotMetError' : 'RuntimeError'
|
56
|
+
res.exception_stacktrace = "#{failing_step['name']}\n#{failing_step['match']['location']}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# A format adapter that uses our special JSON formatter
|
63
|
+
class Formatter < ::Cucumber::Formatter::GherkinFormatterAdapter
|
64
|
+
def initialize(_runtime, _io, options)
|
65
|
+
options[:expand] = true
|
66
|
+
super(ElasticResults::Cucumber::JSONFormatter.new, false, options)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
module ElasticResults
|
5
|
+
# A common data format for test results. The Cucumber and Rspec formatters populate this class.
|
6
|
+
class Result
|
7
|
+
attr_accessor :outcome, :exception_class, :exception_msg, :exception_stacktrace, :runtime
|
8
|
+
attr_accessor :id, :uri, :feature_name, :scenario_name, :build_number
|
9
|
+
|
10
|
+
def to_hash
|
11
|
+
result_hash = base_info
|
12
|
+
|
13
|
+
[:outcome, :exception_class, :exception_msg, :exception_stacktrace, :runtime,
|
14
|
+
:id, :uri, :feature_name, :scenario_name, :tags].each do |field|
|
15
|
+
result_hash[field] = send field
|
16
|
+
end
|
17
|
+
result_hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def tags
|
21
|
+
@tags ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def outcome
|
25
|
+
@outcome ||= exception_class.nil? ? 'pass' : fail_type
|
26
|
+
end
|
27
|
+
|
28
|
+
def fail_type
|
29
|
+
exception_class =~ /ExpectationNotMet/ ? :fail : :broke
|
30
|
+
end
|
31
|
+
|
32
|
+
def base_info
|
33
|
+
{
|
34
|
+
'@timestamp' => Time.now.iso8601(3),
|
35
|
+
build_number: ENV['BUILD_NUMBER'] ? ENV['BUILD_NUMBER'] : ElasticResults.build_id,
|
36
|
+
build_url: ENV['BUILD_URL'],
|
37
|
+
node_name: ENV['NODE_NAME'] ? ENV['NODE_NAME'] : Socket.gethostname,
|
38
|
+
job_name: ENV['JOB_NAME'],
|
39
|
+
build_tag: ENV['BUILD_TAG'],
|
40
|
+
environment: ENV['TEST_ENV'] || ENV['RAILS_ENV'],
|
41
|
+
git_commit: ElasticResults.git_commit,
|
42
|
+
git_url: ElasticResults.git_url,
|
43
|
+
git_branch: ElasticResults.git_branch,
|
44
|
+
suite_name: ElasticResults.suite_name,
|
45
|
+
suite_type: ElasticResults.suite_type,
|
46
|
+
team: ElasticResults.team_name
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
RSpec::Support.require_rspec_core 'formatters/base_formatter'
|
2
|
+
require 'elastic_results'
|
3
|
+
require 'json'
|
4
|
+
require 'elasticsearch'
|
5
|
+
require 'time'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
module ElasticResults
|
9
|
+
module RSpec
|
10
|
+
# @private
|
11
|
+
class Formatter < ::RSpec::Core::Formatters::BaseFormatter
|
12
|
+
::RSpec::Core::Formatters.register self, :example_passed, :example_failed, :close
|
13
|
+
|
14
|
+
def initialize(output)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def example_passed(notification)
|
19
|
+
record_example notification.example
|
20
|
+
end
|
21
|
+
|
22
|
+
def example_failed(notification)
|
23
|
+
record_example notification.example
|
24
|
+
end
|
25
|
+
|
26
|
+
def record_example(example)
|
27
|
+
ElasticResults.index_result result_for(example)
|
28
|
+
end
|
29
|
+
|
30
|
+
def close(_notification)
|
31
|
+
ElasticResults.write_urls
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def result_for(example)
|
37
|
+
Result.new.tap do |res|
|
38
|
+
res.id = example.id
|
39
|
+
res.feature_name = example.description
|
40
|
+
res.scenario_name = example.full_description
|
41
|
+
res.uri = example.location
|
42
|
+
res.runtime = example.metadata[:execution_result].run_time
|
43
|
+
unless example.exception.nil?
|
44
|
+
res.exception_class = example.exception.class.name
|
45
|
+
res.exception_msg = example.exception.message
|
46
|
+
res.exception_stacktrace = example.exception.backtrace
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
{
|
2
|
+
"mappings": {
|
3
|
+
"simplecov": {
|
4
|
+
"_timestamp": {
|
5
|
+
"enabled": true
|
6
|
+
},
|
7
|
+
"properties": {
|
8
|
+
"@timestamp": {
|
9
|
+
"type": "date",
|
10
|
+
"format": "dateOptionalTime"
|
11
|
+
},
|
12
|
+
"environment":{
|
13
|
+
"type": "string",
|
14
|
+
"index" : "not_analyzed",
|
15
|
+
"null_value" : "na"
|
16
|
+
},
|
17
|
+
"suite_name":{
|
18
|
+
"type": "string",
|
19
|
+
"null_value" : "na"
|
20
|
+
},
|
21
|
+
"suite_type":{
|
22
|
+
"type": "string",
|
23
|
+
"index" : "not_analyzed",
|
24
|
+
"null_value" : "na"
|
25
|
+
},
|
26
|
+
"team":{
|
27
|
+
"type": "string",
|
28
|
+
"null_value" : "na"
|
29
|
+
},
|
30
|
+
"build_number": {
|
31
|
+
"type": "string",
|
32
|
+
"index" : "not_analyzed",
|
33
|
+
"null_value" : "na"
|
34
|
+
},
|
35
|
+
"build_url": {
|
36
|
+
"type": "string",
|
37
|
+
"index" : "not_analyzed",
|
38
|
+
"null_value" : "na"
|
39
|
+
},
|
40
|
+
"node_name": {
|
41
|
+
"type": "string",
|
42
|
+
"index" : "not_analyzed",
|
43
|
+
"null_value" : "na"
|
44
|
+
},
|
45
|
+
"job_name": {
|
46
|
+
"type": "string",
|
47
|
+
"index" : "not_analyzed",
|
48
|
+
"null_value" : "na"
|
49
|
+
},
|
50
|
+
"build_tag": {
|
51
|
+
"type": "string",
|
52
|
+
"index" : "not_analyzed",
|
53
|
+
"null_value" : "na"
|
54
|
+
},
|
55
|
+
"git_commit": {
|
56
|
+
"type": "string",
|
57
|
+
"index" : "not_analyzed",
|
58
|
+
"null_value" : "na"
|
59
|
+
},
|
60
|
+
"git_url": {
|
61
|
+
"type": "string",
|
62
|
+
"index" : "not_analyzed",
|
63
|
+
"null_value" : "na"
|
64
|
+
},
|
65
|
+
"git_branch": {
|
66
|
+
"type": "string",
|
67
|
+
"null_value" : "na"
|
68
|
+
},
|
69
|
+
"metrics": {
|
70
|
+
"properties": {
|
71
|
+
"covered_strength": {
|
72
|
+
"type": "float"
|
73
|
+
},
|
74
|
+
"covered_lines": {
|
75
|
+
"type": "integer"
|
76
|
+
},
|
77
|
+
"total_lines": {
|
78
|
+
"type": "integer"
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
{
|
2
|
+
"mappings": {
|
3
|
+
"test_result": {
|
4
|
+
"_timestamp": {
|
5
|
+
"enabled": true
|
6
|
+
},
|
7
|
+
"properties": {
|
8
|
+
"@timestamp": {
|
9
|
+
"type": "date",
|
10
|
+
"format": "dateOptionalTime"
|
11
|
+
},
|
12
|
+
"environment":{
|
13
|
+
"type": "string",
|
14
|
+
"index" : "not_analyzed",
|
15
|
+
"null_value" : "na"
|
16
|
+
},
|
17
|
+
"suite_name":{
|
18
|
+
"type": "string",
|
19
|
+
"null_value" : "na"
|
20
|
+
},
|
21
|
+
"suite_type": {
|
22
|
+
"type": "string",
|
23
|
+
"index": "not_analyzed",
|
24
|
+
"null_value" : "na"
|
25
|
+
},
|
26
|
+
"team":{
|
27
|
+
"type": "string",
|
28
|
+
"null_value" : "na"
|
29
|
+
},
|
30
|
+
"outcome": {
|
31
|
+
"type": "string",
|
32
|
+
"index" : "not_analyzed",
|
33
|
+
"null_value" : "na"
|
34
|
+
},
|
35
|
+
"exception_msg": {
|
36
|
+
"type": "string"
|
37
|
+
},
|
38
|
+
"exception_class": {
|
39
|
+
"type": "string",
|
40
|
+
"null_value" : "na"
|
41
|
+
},
|
42
|
+
"exception_stacktrace": {
|
43
|
+
"type": "string",
|
44
|
+
"null_value" : "na"
|
45
|
+
},
|
46
|
+
"runtime" : {
|
47
|
+
"type": "float"
|
48
|
+
},
|
49
|
+
"build_number": {
|
50
|
+
"type": "string",
|
51
|
+
"index" : "not_analyzed",
|
52
|
+
"null_value" : "na"
|
53
|
+
},
|
54
|
+
"build_url": {
|
55
|
+
"type": "string",
|
56
|
+
"index" : "not_analyzed",
|
57
|
+
"null_value" : "na"
|
58
|
+
},
|
59
|
+
"node_name": {
|
60
|
+
"type": "string",
|
61
|
+
"index" : "not_analyzed",
|
62
|
+
"null_value" : "na"
|
63
|
+
},
|
64
|
+
"job_name": {
|
65
|
+
"type": "string",
|
66
|
+
"index" : "not_analyzed",
|
67
|
+
"null_value" : "na"
|
68
|
+
},
|
69
|
+
"build_tag": {
|
70
|
+
"type": "string",
|
71
|
+
"index" : "not_analyzed",
|
72
|
+
"null_value" : "na"
|
73
|
+
},
|
74
|
+
"git_commit": {
|
75
|
+
"type": "string",
|
76
|
+
"index" : "not_analyzed",
|
77
|
+
"null_value" : "na"
|
78
|
+
},
|
79
|
+
"git_url": {
|
80
|
+
"type": "string",
|
81
|
+
"index" : "not_analyzed",
|
82
|
+
"null_value" : "na"
|
83
|
+
},
|
84
|
+
"git_branch": {
|
85
|
+
"type": "string",
|
86
|
+
"index" : "not_analyzed",
|
87
|
+
"null_value" : "na"
|
88
|
+
},
|
89
|
+
"tags": {
|
90
|
+
"type": "string"
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'elastic_results'
|
3
|
+
|
4
|
+
module ElasticResults
|
5
|
+
module SimpleCov
|
6
|
+
# A simple formatter that converts a SimpleCov Result to a hash to be stored in elastic search
|
7
|
+
class Formatter
|
8
|
+
def format(result)
|
9
|
+
data = base_info
|
10
|
+
|
11
|
+
data[:command_name] = result.command_name
|
12
|
+
data[:metrics] = {
|
13
|
+
covered_percent: result.covered_percent,
|
14
|
+
covered_strength: result.covered_strength.nan? ? 0.0 : result.covered_strength,
|
15
|
+
covered_lines: result.covered_lines,
|
16
|
+
total_lines: result.total_lines
|
17
|
+
}
|
18
|
+
|
19
|
+
ElasticResults.with_disabled_mocks {
|
20
|
+
if ElasticResults.use_unsafe_index
|
21
|
+
ElasticResults.unsafe_index ElasticResults.es_index_coverage, ElasticResults.es_type_coverage, data
|
22
|
+
else
|
23
|
+
ElasticResults.client.index index: ElasticResults.es_index_coverage, type: ElasticResults.es_type_coverage, body: data
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def base_info
|
31
|
+
{
|
32
|
+
'@timestamp' => Time.now.iso8601(3),
|
33
|
+
build_number: ENV['BUILD_NUMBER'] ? ENV['BUILD_NUMBER'] : ElasticResults.build_id,
|
34
|
+
build_url: ENV['BUILD_URL'],
|
35
|
+
node_name: ENV['NODE_NAME'] ? ENV['NODE_NAME'] : Socket.gethostname,
|
36
|
+
job_name: ENV['JOB_NAME'],
|
37
|
+
build_tag: ENV['BUILD_TAG'],
|
38
|
+
environment: ENV['TEST_ENV'] || ENV['RAILS_ENV'],
|
39
|
+
git_commit: ElasticResults.git_commit,
|
40
|
+
git_url: ElasticResults.git_url,
|
41
|
+
git_branch: ElasticResults.git_branch,
|
42
|
+
suite_name: ElasticResults.suite_name,
|
43
|
+
suite_type: ElasticResults.suite_type,
|
44
|
+
team: ElasticResults.team_name
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'elastic_results/version'
|
2
|
+
require 'elastic_results/result'
|
3
|
+
require 'elasticsearch'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require "net/https"
|
7
|
+
require "uri"
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
# Our root namespace for all objects
|
12
|
+
module ElasticResults
|
13
|
+
class << self
|
14
|
+
attr_accessor :suite_name
|
15
|
+
attr_accessor :suite_type
|
16
|
+
attr_accessor :es_url
|
17
|
+
attr_accessor :es_index_result
|
18
|
+
attr_accessor :es_index_coverage
|
19
|
+
attr_accessor :es_type_result
|
20
|
+
attr_accessor :es_type_coverage
|
21
|
+
attr_accessor :es_log
|
22
|
+
attr_accessor :team_name
|
23
|
+
attr_accessor :build_id
|
24
|
+
attr_accessor :google_api_key
|
25
|
+
attr_accessor :kibana_url
|
26
|
+
attr_accessor :use_unsafe_index
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return the mapping JSON for used in creating indicies
|
30
|
+
# the which paramter should map to to a filename in the setup folder
|
31
|
+
def self.mapping_for(which)
|
32
|
+
setup_folder = File.expand_path('./elastic_results/setup', File.dirname(__FILE__))
|
33
|
+
File.read("#{setup_folder}/#{which.to_s}.json")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Memoized instance of the elasticsearch client
|
37
|
+
def self.client
|
38
|
+
@@client ||= Elasticsearch::Client.new url: ElasticResults.es_url, log: ElasticResults.es_log
|
39
|
+
end
|
40
|
+
|
41
|
+
# Given a payload store it as a test result
|
42
|
+
def self.index_result(payload)
|
43
|
+
index ElasticResults.es_index_result, ElasticResults.es_type_result, payload
|
44
|
+
end
|
45
|
+
|
46
|
+
# Given a payload store it as coverage data
|
47
|
+
def self.index_coverage(payload)
|
48
|
+
index ElasticResults.es_index_coverage, ElasticResults.es_type_coverage, payload
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generic index function that knows when to use the elasticsearch API.
|
52
|
+
def self.index(index, type, payload)
|
53
|
+
begin
|
54
|
+
with_disabled_mocks {
|
55
|
+
if ElasticResults.use_unsafe_index
|
56
|
+
unsafe_index index, type, payload.to_hash
|
57
|
+
else
|
58
|
+
client.index index: index, type: type, body: payload.to_hash
|
59
|
+
end
|
60
|
+
}
|
61
|
+
rescue Exception => ex
|
62
|
+
puts "#{ex.message} while storing results in Elasticsearch"
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# An "unsafe" index routine which uses Net:HTTP with SSL validation turned off. Needed for when WebMock is in use
|
69
|
+
# as it breaks SSL cert validations.
|
70
|
+
def self.unsafe_index(index, type, payload)
|
71
|
+
uri = URI.parse(ElasticResults.es_url)
|
72
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
73
|
+
|
74
|
+
if ElasticResults.es_url =~ /https/
|
75
|
+
http.use_ssl = true
|
76
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
77
|
+
end
|
78
|
+
|
79
|
+
request = Net::HTTP::Post.new("/#{index}/#{type}")
|
80
|
+
request.body = payload.to_json
|
81
|
+
response = http.request(request)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Write out a tab deliminated file containing links to the build information
|
85
|
+
def self.write_urls(filename = 'build_links.txt')
|
86
|
+
File.open(filename, 'w') { |file| file.write("View failures in Kibana\t#{ElasticResults.fails_url}\t\nView all results in Kibana\t#{ElasticResults.results_url}\t") }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a link to the results. shortened URL if possible otherwise the full URL from long_results_url.
|
90
|
+
def self.results_url
|
91
|
+
if ElasticResults.google_api_key.nil?
|
92
|
+
long_results_url
|
93
|
+
else
|
94
|
+
require 'googl'
|
95
|
+
Googl.shorten(long_results_url, '127.0.0.1', ElasticResults.google_api_key).short_url
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns a link to the failures. shortened URL if possible otherwise the full URL from long_fails_url.
|
100
|
+
def self.fails_url
|
101
|
+
if ElasticResults.google_api_key.nil?
|
102
|
+
long_fails_url
|
103
|
+
else
|
104
|
+
require 'googl'
|
105
|
+
Googl.shorten(long_fails_url, '127.0.0.1', ElasticResults.google_api_key).short_url
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Set up defaults for the meta data
|
111
|
+
ElasticResults.team_name ||= ENV['TEAM_NAME'].nil? ? '???' : ENV['TEAM_NAME']
|
112
|
+
ElasticResults.suite_name ||= ENV['SUITE_NAME'].nil? ? File.basename(Dir.pwd) : ENV['SUITE_NAME']
|
113
|
+
ElasticResults.suite_type ||= ENV['SUITE_TYPE'].nil? ? 'integration' : ENV['SUITE_TYPE']
|
114
|
+
ElasticResults.es_url ||= ENV['ES_HOST'].nil? ? 'http://localhost' : ENV['ES_HOST']
|
115
|
+
ElasticResults.es_index_result ||= ENV['ES_INDEX_RESULT'].nil? ? "test_results-#{DateTime.now.strftime('%F')}" : ENV['ES_INDEX_RESULT']
|
116
|
+
ElasticResults.es_type_result ||= ENV['ES_TYPE_RESULT'].nil? ? 'test_result' : ENV['ES_TYPE_RESULT']
|
117
|
+
ElasticResults.es_log ||= ENV['DEBUG'].nil? ? false : true
|
118
|
+
ElasticResults.build_id ||= DateTime.now.strftime('%Y%m%d%H%M%S%L')
|
119
|
+
ElasticResults.es_index_coverage ||= ENV['ES_INDEX_COVERAGE'].nil? ? "coverage-#{DateTime.now.strftime('%F')}" : ENV['ES_INDEX_COVERAGE']
|
120
|
+
ElasticResults.es_type_coverage ||= ENV['ES_TYPE_COVERAGE'].nil? ? 'simplecov' : ENV['ES_TYPE_COVERAGE']
|
121
|
+
ElasticResults.google_api_key ||= ENV['GOOGLE_API_KEY']
|
122
|
+
ElasticResults.kibana_url ||= ENV['KIBANA_URL'].nil? ? 'http://localhost:5601' : ENV['KIBANA_URL']
|
123
|
+
ElasticResults.use_unsafe_index ||= defined?(WebMock) ? true : false
|
124
|
+
|
125
|
+
|
126
|
+
private
|
127
|
+
# Returns a full link to the discover page showing the test results for the current build
|
128
|
+
def self.long_results_url
|
129
|
+
build_id = ENV['BUILD_NUMBER'] ? ENV['BUILD_NUMBER'] : ElasticResults.build_id
|
130
|
+
"#{ElasticResults.kibana_url}/#/discover/?_g=(refreshInterval:(display:Off,pause:!f,section:0,value:0),time:(from:now%2Fd,mode:quick,to:now%2Fd))&_a=(columns:!(team,suite_name,build_number,environment,runtime,outcome,feature_name,scenario_name,exception_class,exception_msg,exception_stacktrace),filters:!(),index:'test_results-*',interval:auto,query:(query_string:(analyze_wildcard:!t,query:'build_number:#{build_id}')),sort:!('@timestamp',desc))"
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns a full link to the discover page showing the test failures for the current build
|
134
|
+
def self.long_fails_url
|
135
|
+
build_id = ENV['BUILD_NUMBER'] ? ENV['BUILD_NUMBER'] : ElasticResults.build_id
|
136
|
+
"#{ElasticResults.kibana_url}/#/discover/?_g=(refreshInterval:(display:Off,pause:!f,section:0,value:0),time:(from:now%2Fd,mode:quick,to:now%2Fd))&_a=(columns:!(team,suite_name,build_number,environment,runtime,outcome,feature_name,scenario_name,exception_class,exception_msg,exception_stacktrace),filters:!(),index:'test_results-*',interval:auto,query:(query_string:(analyze_wildcard:!t,query:'build_number:#{build_id}%20AND%20(outcome:broke%20OR%20outcome:fail)')),sort:!('@timestamp',desc))"
|
137
|
+
end
|
138
|
+
|
139
|
+
# Memoize the git_commit to avoid hitting git for each result
|
140
|
+
def self.git_commit
|
141
|
+
@@git_commit ||= ENV['GIT_COMMIT'] ? ENV['GIT_COMMIT'] : `git rev-parse HEAD`.chomp
|
142
|
+
end
|
143
|
+
|
144
|
+
# Memoize the git_url to avoid hitting git for each result
|
145
|
+
def self.git_url
|
146
|
+
@@git_url ||= ENV['GIT_URL'] ? ENV['GIT_URL'] : `git config --get remote.origin.url`.chomp
|
147
|
+
end
|
148
|
+
|
149
|
+
# Memoize the git_branch to avoid hitting git for each result
|
150
|
+
def self.git_branch
|
151
|
+
@@git_branch ||= ENV['GIT_BRANCH'] ? ENV['GIT_BRANCH'] : `git rev-parse --abbrev-ref HEAD`.chomp
|
152
|
+
end
|
153
|
+
|
154
|
+
# Helper function to disable mocks before calling out to the web (and getting blocked)
|
155
|
+
def self.with_disabled_mocks
|
156
|
+
should_reenable_webmock = false
|
157
|
+
if defined? WebMock
|
158
|
+
if !WebMock.net_connect_allowed?
|
159
|
+
should_reenable_webmock = true
|
160
|
+
WebMock.disable!
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
if defined? VCR
|
165
|
+
VCR.turned_off {
|
166
|
+
yield
|
167
|
+
}
|
168
|
+
else
|
169
|
+
yield
|
170
|
+
end
|
171
|
+
|
172
|
+
if should_reenable_webmock
|
173
|
+
WebMock.enable!
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: elastic_results
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Donavan Stanley
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: elasticsearch
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: googl
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- dstanley@covermymeds.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- Gemfile.lock
|
93
|
+
- LICENSE
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- bin/console
|
97
|
+
- bin/setup
|
98
|
+
- elastic_results.gemspec
|
99
|
+
- lib/elastic_results.rb
|
100
|
+
- lib/elastic_results/cucumber.rb
|
101
|
+
- lib/elastic_results/result.rb
|
102
|
+
- lib/elastic_results/rspec.rb
|
103
|
+
- lib/elastic_results/setup/coverage.json
|
104
|
+
- lib/elastic_results/setup/test_results.json
|
105
|
+
- lib/elastic_results/simplecov.rb
|
106
|
+
- lib/elastic_results/version.rb
|
107
|
+
homepage: https://github.com/covermymeds/elastic_results
|
108
|
+
licenses: []
|
109
|
+
metadata:
|
110
|
+
allowed_push_host: https://rubygems.org
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 2.0.14
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Formatters to shove test results into elastic search
|
131
|
+
test_files: []
|