korinthenkacker 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/README.md +12 -0
- data/Rakefile +5 -1
- data/korinthenkacker.gemspec +1 -0
- data/lib/korinthenkacker/cli.rb +45 -40
- data/lib/korinthenkacker/filters/failed.rb +9 -0
- data/lib/korinthenkacker/filters/flaky.rb +12 -0
- data/lib/korinthenkacker/job_info.rb +4 -1
- data/lib/korinthenkacker/reporters/simple.rb +25 -0
- data/lib/korinthenkacker/reporters/verbose.rb +33 -0
- data/lib/korinthenkacker/test_case.rb +26 -2
- data/lib/korinthenkacker/test_report.rb +10 -12
- data/lib/korinthenkacker/version.rb +1 -1
- data/spec/filters/failed_spec.rb +33 -0
- data/spec/filters/flaky_spec.rb +33 -0
- data/spec/fixtures/test_cases.json +170 -0
- data/spec/spec_helper.rb +89 -0
- data/spec/test_case_spec.rb +85 -0
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8b03b372dfb50d7134c8f789c824613e22ab5fd
|
4
|
+
data.tar.gz: 8613ab7127a2595676f1f6d25723f25f385518dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c1957868677c50eb69b66c5945fe941adbcf6dedecff57609ed15460e7c25386e3e3a3d580304da2a434e413eeb5cbaaf6fa4542c4e31e65a2affd00daefcba
|
7
|
+
data.tar.gz: 2bfcb6c65bd58565879b52cb724a581f60a5b8bada1402ef539b3cf5fe2a71a4bb2b225450087749ad3fd1b516d0863630460aca85e6d9582809c14a4e205dd4
|
data/.rspec
ADDED
data/README.md
CHANGED
@@ -4,6 +4,10 @@ Know your Jenkins
|
|
4
4
|
|
5
5
|
## Setup
|
6
6
|
|
7
|
+
```
|
8
|
+
gem install korinthenkacker
|
9
|
+
```
|
10
|
+
|
7
11
|
Add a `.korinthenkacker.yml` containing the jenkins url:
|
8
12
|
|
9
13
|
```
|
@@ -60,6 +64,14 @@ $> korinthenkacker failed_scenarios soundcloud_rac_acceptance_tests_0 47
|
|
60
64
|
47 80.93447 When a follow request fails, display unfollowed state
|
61
65
|
```
|
62
66
|
|
67
|
+
```
|
68
|
+
$> korinthenkacker flaky_scenarios soundcloud_rac_acceptance_tests -l 20
|
69
|
+
# duration scenario name
|
70
|
+
228 63.409763 'Player.Foreground playback with server errors'
|
71
|
+
225 3.24821 'Player shortcut (Mini waveform).Mini waveform stops animating on track error'
|
72
|
+
223 30.674717 'Player Audio Ads Playback.Going back after playing ad does not show ad again'
|
73
|
+
```
|
74
|
+
|
63
75
|
```
|
64
76
|
$> korinthenkacker report soundcloud_rac_acceptance_tests_{0,1,2,3,4} -l 5
|
65
77
|
soundcloud_rac_acceptance_tests_0
|
data/Rakefile
CHANGED
data/korinthenkacker.gemspec
CHANGED
data/lib/korinthenkacker/cli.rb
CHANGED
@@ -3,79 +3,84 @@ require 'thor'
|
|
3
3
|
require_relative 'api'
|
4
4
|
require_relative 'configuration'
|
5
5
|
require_relative 'test_report'
|
6
|
+
require_relative 'reporters/verbose'
|
7
|
+
require_relative 'reporters/simple'
|
6
8
|
require_relative 'job_info'
|
9
|
+
require_relative 'filters/failed'
|
10
|
+
require_relative 'filters/flaky'
|
7
11
|
|
8
12
|
module Korinthenkacker
|
9
13
|
class CLI < Thor
|
10
14
|
package_name 'korinthenkacker'
|
11
15
|
|
12
16
|
desc 'jobs', 'Show all jobs'
|
17
|
+
method_option :simple, aliases: '-s', type: :boolean, desc: 'simple output formatting'
|
13
18
|
def jobs
|
14
|
-
|
19
|
+
jobs = api.jobs['jobs'].map { |job| JobInfo.new(job) }
|
20
|
+
reporter(options.simple).print_jobs_report(jobs)
|
15
21
|
end
|
16
22
|
|
17
23
|
desc 'builds JOBNAME', 'Display JOBNAME builds and their status'
|
18
|
-
method_option :limit, :
|
24
|
+
method_option :limit, aliases: '-l', type: :numeric
|
25
|
+
method_option :simple, aliases: '-s', type: :boolean, desc: 'simple output formatting'
|
19
26
|
def builds(jobname)
|
20
27
|
reports = test_reports(jobname, options.limit)
|
21
|
-
|
22
|
-
output << "#\tsuccess\tduration"
|
23
|
-
reports.each{ |report|
|
24
|
-
output << "#{report.build}\t#{report.success?}\t#{report.duration}"
|
25
|
-
}
|
26
|
-
puts output.join("\n")
|
28
|
+
reporter(options.simple).print_builds_report(reports)
|
27
29
|
end
|
28
30
|
|
29
31
|
desc 'failed_scenarios JOBNAME [BUILD]', 'Display JOBNAME failing scenarios'
|
30
|
-
method_option :limit, :
|
32
|
+
method_option :limit, aliases: '-l', type: :numeric
|
33
|
+
method_option :simple, aliases: '-s', type: :boolean, desc: 'simple output formatting'
|
31
34
|
def failed_scenarios(jobname, build=nil)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
report.failed_cases.each{ |failed_case|
|
44
|
-
print_scenario_report(report.build, failed_case)
|
45
|
-
}
|
46
|
-
}
|
47
|
-
end
|
35
|
+
failed_cases = failed_cases_for(jobname, build)
|
36
|
+
reporter(options.simple).print_scenario_reports(failed_cases)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'flaky_scenarios JOBNAME', 'Display JOBNAME flaky scenarios'
|
40
|
+
method_option :limit, aliases: '-l', type: :numeric
|
41
|
+
method_option :simple, aliases: '-s', type: :boolean, desc: 'simple output formatting'
|
42
|
+
def flaky_scenarios(jobname)
|
43
|
+
failed_cases = failed_cases_for(jobname)
|
44
|
+
flaky_cases = flaky_filter.filter(failed_cases)
|
45
|
+
reporter(options.simple).print_scenario_reports(flaky_cases)
|
48
46
|
end
|
49
47
|
|
50
48
|
desc 'report [JOBS...]', 'Display failing scenario for jobs'
|
51
|
-
method_option :limit, :
|
49
|
+
method_option :limit, aliases: '-l', type: :numeric
|
52
50
|
def report(*jobs)
|
53
|
-
jobs.each
|
51
|
+
jobs.each do |job|
|
54
52
|
puts job
|
55
53
|
failed_scenarios(job, nil)
|
56
|
-
|
54
|
+
end
|
57
55
|
end
|
58
56
|
|
59
57
|
private
|
60
58
|
|
61
|
-
def
|
62
|
-
|
59
|
+
def failed_cases_for(jobname, build=nil)
|
60
|
+
test_reports = build.nil? ? test_reports(jobname, options.limit) : [test_report(jobname, build)]
|
61
|
+
failed_filter.filter(test_reports.map(&:cases).flatten)
|
63
62
|
end
|
64
63
|
|
65
|
-
def
|
66
|
-
|
64
|
+
def test_report(jobname, build)
|
65
|
+
TestReport.new(jobname, build, api.test_report(jobname, build))
|
67
66
|
end
|
68
67
|
|
69
68
|
def test_reports(jobname, limit=nil)
|
70
69
|
job_info = JobInfo.new(api.job(jobname))
|
71
|
-
builds =
|
72
|
-
builds.map{ |build|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
builds = limit ? job_info.build_numbers.first(limit) : job_info.build_numbers
|
71
|
+
builds.map { |build| test_report(jobname, build) rescue nil }.compact # TODO: proper catching
|
72
|
+
end
|
73
|
+
|
74
|
+
def reporter(simple=false)
|
75
|
+
@reporter ||= simple ? Reporters::Simple.new : Reporters::Verbose.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def failed_filter
|
79
|
+
@failed_filter ||= Filters::Failed.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def flaky_filter
|
83
|
+
@flaky_filter ||= Filters::Flaky.new
|
79
84
|
end
|
80
85
|
|
81
86
|
def api
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Korinthenkacker
|
2
|
+
module Reporters
|
3
|
+
class Simple
|
4
|
+
def print_jobs_report(jobs)
|
5
|
+
puts jobs.map(&:name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_builds_report(reports)
|
9
|
+
reports.map do |report|
|
10
|
+
"#{report.build}\t#{report.success?}\t#{report.duration}"
|
11
|
+
end.join("\n")
|
12
|
+
end
|
13
|
+
|
14
|
+
def print_scenario_reports(test_cases)
|
15
|
+
test_cases.each { |test_case| print_scenario_report(test_case) }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def print_scenario_report(scenario)
|
21
|
+
printf("%s\t%s\t'%s'\n", scenario.build, scenario.duration, scenario.full_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Korinthenkacker
|
2
|
+
module Reporters
|
3
|
+
class Verbose
|
4
|
+
def print_jobs_report(jobs)
|
5
|
+
puts jobs.map(&:name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_builds_report(reports)
|
9
|
+
output = ["#\tsuccess\tduration"]
|
10
|
+
reports.each do |report|
|
11
|
+
output << "#{report.build}\t#{report.success?}\t#{report.duration}"
|
12
|
+
end
|
13
|
+
puts output.join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_scenario_reports(test_cases)
|
17
|
+
print_table_header unless test_cases.empty?
|
18
|
+
|
19
|
+
test_cases.each { |test_case| print_scenario_report(test_case) }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def print_table_header
|
25
|
+
printf("%s\t%-15s\t%s\n", '#', 'duration', 'scenario name')
|
26
|
+
end
|
27
|
+
|
28
|
+
def print_scenario_report(scenario)
|
29
|
+
printf("%s\t%-15s\t'%s'\n", scenario.build, scenario.duration, scenario.full_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,18 +1,42 @@
|
|
1
1
|
module Korinthenkacker
|
2
2
|
class TestCase
|
3
|
-
attr_reader :name, :duration, :failed_since, :status
|
3
|
+
attr_reader :name, :class_name, :duration, :failed_since, :status, :build
|
4
4
|
|
5
|
-
def initialize(json)
|
5
|
+
def initialize(json, build)
|
6
6
|
@name = json['name']
|
7
|
+
@class_name = json['className']
|
7
8
|
@duration = json['duration']
|
8
9
|
@failed_since = json['duration']
|
9
10
|
@status = json['status']
|
11
|
+
@failed_since = json['failedSince']
|
12
|
+
@build = build
|
13
|
+
end
|
14
|
+
|
15
|
+
def full_name
|
16
|
+
[class_name, name].join('. ')
|
10
17
|
end
|
11
18
|
|
12
19
|
def success?
|
13
20
|
!(status == 'REGRESSION' || status == 'FAILED')
|
14
21
|
end
|
15
22
|
|
23
|
+
def failure?
|
24
|
+
!success?
|
25
|
+
end
|
26
|
+
|
27
|
+
def sibling?(other)
|
28
|
+
other == self && other.failed_since != self.failed_since
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
other.class == self.class && other.full_name == self.full_name
|
33
|
+
end
|
34
|
+
alias_method :eql?, :==
|
35
|
+
|
36
|
+
def hash
|
37
|
+
full_name.hash
|
38
|
+
end
|
39
|
+
|
16
40
|
private
|
17
41
|
|
18
42
|
def status_with_json(json)
|
@@ -2,7 +2,7 @@ require_relative 'test_case'
|
|
2
2
|
|
3
3
|
module Korinthenkacker
|
4
4
|
class TestReport
|
5
|
-
attr_reader :jobname, :build
|
5
|
+
attr_reader :jobname, :build, :json
|
6
6
|
|
7
7
|
def initialize(jobname, build, json)
|
8
8
|
@jobname = jobname
|
@@ -11,36 +11,34 @@ module Korinthenkacker
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def duration
|
14
|
-
|
14
|
+
json['duration']
|
15
15
|
end
|
16
16
|
|
17
17
|
def fail_count
|
18
|
-
|
18
|
+
json['failCount']
|
19
19
|
end
|
20
20
|
|
21
21
|
def pass_count
|
22
|
-
|
22
|
+
json['passCount']
|
23
23
|
end
|
24
24
|
|
25
25
|
def skip_count
|
26
|
-
|
26
|
+
json['skipCount']
|
27
27
|
end
|
28
28
|
|
29
29
|
def success?
|
30
30
|
fail_count == 0 && skip_count == 0
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
|
33
|
+
def failure?
|
34
|
+
!success?
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
def all_cases
|
40
|
-
@json['suites']
|
37
|
+
def cases
|
38
|
+
json['suites']
|
41
39
|
.map { |suite| suite['cases'] }
|
42
40
|
.flatten
|
43
|
-
.map { |my_case| TestCase.new(my_case) }
|
41
|
+
.map { |my_case| TestCase.new(my_case, build) }
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'korinthenkacker/filters/failed'
|
3
|
+
require 'korinthenkacker/test_case'
|
4
|
+
|
5
|
+
module Korinthenkacker
|
6
|
+
module Filters
|
7
|
+
describe Failed do
|
8
|
+
describe '#filter' do
|
9
|
+
let(:report_json_path) { File.expand_path('../../fixtures/test_cases.json', __FILE__) }
|
10
|
+
let(:report_json_fixture) { JSON.parse(File.read(report_json_path)) }
|
11
|
+
let(:test_cases) { report_json_fixture.map { |json_case| TestCase.new(json_case, 1) } }
|
12
|
+
|
13
|
+
context 'with empty TestCases' do
|
14
|
+
let(:test_cases) { [] }
|
15
|
+
|
16
|
+
it 'returns and empty array' do
|
17
|
+
expect(subject.filter([])).to be_empty
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with non-empty cases' do
|
22
|
+
it 'returns the correct amount of TestCases' do
|
23
|
+
expect(subject.filter(test_cases).count).to eql(8)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns only failed TestCases' do
|
27
|
+
expect(subject.filter(test_cases).all?(&:failure?)).to be_truthy
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'korinthenkacker/filters/flaky'
|
3
|
+
require 'korinthenkacker/test_case'
|
4
|
+
|
5
|
+
module Korinthenkacker
|
6
|
+
module Filters
|
7
|
+
describe Flaky do
|
8
|
+
let(:json_fixture_path) { File.expand_path('../../fixtures/test_cases.json', __FILE__) }
|
9
|
+
let(:json_fixture) { JSON.parse(File.read(json_fixture_path)) }
|
10
|
+
let(:test_cases) { json_fixture.map { |json_case| TestCase.new(json_case, 1) } }
|
11
|
+
|
12
|
+
context 'with empty TestCases' do
|
13
|
+
let(:test_cases) { [] }
|
14
|
+
|
15
|
+
it 'returns and empty array' do
|
16
|
+
expect(subject.filter([])).to be_empty
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with non-empty cases' do
|
21
|
+
it 'returns the correct number of flaky TestCases' do
|
22
|
+
expect(subject.filter(test_cases).count).to eql(2)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns only the flaky TestCases' do
|
26
|
+
flaky_test_case_names = subject.filter(test_cases).map(&:class_name)
|
27
|
+
expect(flaky_test_case_names).to include('Flaky Spec A')
|
28
|
+
expect(flaky_test_case_names).to include('Flaky Spec B')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"age": 1,
|
4
|
+
"className": "Player",
|
5
|
+
"duration": 63.409763,
|
6
|
+
"errorDetails": "failed Foreground playback with server errors",
|
7
|
+
"errorStackTrace": "\n Scenario: Foreground playback with server errors\n\nGiven explore and player and waveform datasets are loaded\nGiven that the app is started\nAnd that \"Media\" endpoint returns status code 404\nAnd I go to \"Trending Music Track 1\" player_page\nThen I am in error state\n\nMessage:\n\n wait_for_page_animations_to_finish (elapsed time: 15.000691, time 2014-09-25 00:41:27 +0200) (RuntimeError)\n./features/lib/helpers/wait_until.rb:28:in `rescue in wait_until'\n./features/lib/helpers/wait_until.rb:15:in `wait_until'\n./features/lib/helpers/waiter.rb:154:in `wait_for_animations'\n./features/lib/helpers/waiter.rb:94:in `wait_for_page_animations_to_finish'\n./features/step_definitions/player_page_steps.rb:175:in `/^I am in error state$/'\nfeatures/acceptance/player/player.feature:56:in `Then I am in error state'\n ",
|
8
|
+
"failedSince": 228,
|
9
|
+
"name": "Foreground playback with server errors",
|
10
|
+
"skipped": false,
|
11
|
+
"skippedMessage": null,
|
12
|
+
"status": "REGRESSION",
|
13
|
+
"stderr": "",
|
14
|
+
"stdout": ""
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"age": 0,
|
18
|
+
"className": "Playlist deeplinks",
|
19
|
+
"duration": 31.45592,
|
20
|
+
"errorDetails": null,
|
21
|
+
"errorStackTrace": null,
|
22
|
+
"failedSince": 0,
|
23
|
+
"name": "Splash screen is visible while loading",
|
24
|
+
"skipped": false,
|
25
|
+
"skippedMessage": null,
|
26
|
+
"status": "PASSED",
|
27
|
+
"stderr": "",
|
28
|
+
"stdout": ""
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"age": 1,
|
32
|
+
"className": "Liking a track in player",
|
33
|
+
"duration": 86.92972,
|
34
|
+
"errorDetails": "failed Liking an unliked track",
|
35
|
+
"errorStackTrace": "\n Scenario: Liking an unliked track\n\nGiven explore and player and signin and waveform and stream datasets are loaded\nAnd that the app is started\nGiven I am signed in\nAnd I am on feed_picker_page\nAnd I tap on \"Trending Music\" stream_cell\nAnd track_list loaded items\nAnd I go to \"Trending Music Track 1\" player_page\nAnd I tap the player\nWhen I tap the player like button\nThen after a while I should see the player unlike button\n\nMessage:\n\n couldn't open player from feed (RuntimeError)\n./features/lib/page/explore.rb:38:in `block in touch_track_with_title_and_wait_for_player'\n./features/lib/page/explore.rb:57:in `call'\n./features/lib/page/explore.rb:57:in `track_with_title'\n./features/lib/page/explore.rb:24:in `touch_track_with_title_and_wait_for_player'\n./features/step_definitions/explore_page_steps.rb:54:in `/^I tap on track titled \"(.*)\"$/'\n./features/step_definitions/player_page_steps.rb:4:in `/^I go to \"(.*)\" player_page$/'\nfeatures/acceptance/player/player_like.feature:42:in `And I go to \"Trending Music Track 1\" player_page'\n ",
|
36
|
+
"failedSince": 225,
|
37
|
+
"name": "Liking an unliked track",
|
38
|
+
"skipped": false,
|
39
|
+
"skippedMessage": null,
|
40
|
+
"status": "FAILED",
|
41
|
+
"stderr": "",
|
42
|
+
"stdout": ""
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"age": 1,
|
46
|
+
"className": "Flaky Spec A",
|
47
|
+
"duration": 3.24821,
|
48
|
+
"errorDetails": "failed Mini waveform stops animating on track error",
|
49
|
+
"errorStackTrace": "\n Scenario: Mini waveform stops animating on track error\n\nGiven explore and player and waveform datasets are loaded\nAnd that the app is started\nAnd I am on explore_page\nAnd track_list loaded items\nWhen I go to \"Trending Music Track 1\" player_page\nThen I am in play state\nGiven that the network is unreachable\nThen offline_bar should be in unreachable state\nAnd I tap the next_player_page_button until I'm on \"Trending Music Track 3\" player_page\nThen I am in error state\nWhen I close the player\nThen mini waveform view should not be animating\n\nMessage:\n\n expected visible? to return true, got false (RSpec::Expectations::ExpectationNotMetError)\n./features/step_definitions/player_page_steps.rb:192:in `/^I should see the player error retry button$/'\n./features/step_definitions/player_page_steps.rb:177:in `/^I am in error state$/'\nfeatures/acceptance/player/player_shortcut.feature:43:in `Then I am in error state'\n ",
|
50
|
+
"failedSince": 225,
|
51
|
+
"name": "Mini waveform stops animating on track error",
|
52
|
+
"skipped": false,
|
53
|
+
"skippedMessage": null,
|
54
|
+
"status": "REGRESSION",
|
55
|
+
"stderr": "",
|
56
|
+
"stdout": ""
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"age": 1,
|
60
|
+
"className": "Flaky Spec B",
|
61
|
+
"duration": 30.674717,
|
62
|
+
"errorDetails": "failed Going back after playing ad does not show ad again",
|
63
|
+
"errorStackTrace": "\n Scenario: Going back after playing ad does not show ad again\n\nGiven explore and player and waveform and audio_ad datasets are loaded\nAnd that the app is started\nAnd I am on explore_page\nGiven I go to \"Trending Music Track 1\" player_page\nAnd audio ad has loaded after \"Trending Music Track 1\"\nWhen I tap the next_player_page_button\nThen I should be on audio ad page\nAnd I should hear the audio ad \"MONEYZZZZ\"\nGiven I really want to wait for 4 seconds\nWhen I tap the next_player_page_button\nThen I should be on \"Trending Music Track 2\" player_page\nAnd I should hear music for track \"Trending Music Track 2\"\nAnd I should see the leave_behind\nWhen I tap the leave_behind close button\nThen I should not see the leave_behind\nWhen I tap the previous_player_page_button\nThen I should be on \"Trending Music Track 1\" player_page\n\nMessage:\n\n timed out waiting: timeout = 15, poll_sleep = 0.5 (elapsed time: 15.001166, time 2014-09-24 21:18:19 +0200) (RuntimeError)\n./features/lib/helpers/wait_until.rb:28:in `rescue in wait_until'\n./features/lib/helpers/wait_until.rb:15:in `wait_until'\n./features/step_definitions/player_page_steps.rb:63:in `/^I should be on \"(.*)\" player_page$/'\nfeatures/acceptance/player/player_audio_ad_playback.feature:52:in `Then I should be on \"Trending Music Track 1\" player_page'\n ",
|
64
|
+
"failedSince": 223,
|
65
|
+
"name": "Going back after playing ad does not show ad again",
|
66
|
+
"skipped": false,
|
67
|
+
"skippedMessage": null,
|
68
|
+
"status": "REGRESSION",
|
69
|
+
"stderr": "",
|
70
|
+
"stdout": ""
|
71
|
+
},
|
72
|
+
{
|
73
|
+
"age": 0,
|
74
|
+
"className": "Playlist deeplinks",
|
75
|
+
"duration": 32.77258,
|
76
|
+
"errorDetails": null,
|
77
|
+
"errorStackTrace": null,
|
78
|
+
"failedSince": 0,
|
79
|
+
"name": "Opening a valid playlist url (outline example : | soundcloud:playlists:1 |)",
|
80
|
+
"skipped": false,
|
81
|
+
"skippedMessage": null,
|
82
|
+
"status": "PASSED",
|
83
|
+
"stderr": "",
|
84
|
+
"stdout": ""
|
85
|
+
},
|
86
|
+
{
|
87
|
+
"age": 0,
|
88
|
+
"className": "Playlist deeplinks",
|
89
|
+
"duration": 32.77258,
|
90
|
+
"errorDetails": null,
|
91
|
+
"errorStackTrace": null,
|
92
|
+
"failedSince": 0,
|
93
|
+
"name": "Opening a valid playlist url (outline example : | soundcloud:playlists:1 |)",
|
94
|
+
"skipped": false,
|
95
|
+
"skippedMessage": null,
|
96
|
+
"status": "PASSED",
|
97
|
+
"stderr": "",
|
98
|
+
"stdout": ""
|
99
|
+
},
|
100
|
+
{
|
101
|
+
"age": 1,
|
102
|
+
"className": "Liking a track in player",
|
103
|
+
"duration": 86.88021,
|
104
|
+
"errorDetails": "failed When a user is offline and likes a track, display liked state and sync when online again",
|
105
|
+
"errorStackTrace": "\n Scenario: When a user is offline and likes a track, display liked state and sync when online again\n\nGiven explore and player and signin and waveform and stream datasets are loaded\nAnd that the app is started\nGiven I am signed in\nAnd I am on feed_picker_page\nAnd I tap on \"Trending Music\" stream_cell\nAnd track_list loaded items\nAnd I go to \"Trending Music Track 1\" player_page\nAnd I tap the player\nAnd that the network is unreachable\nThen offline_bar should be in unreachable state\nWhen I tap the player like button\nThen I should see the unlike button on player\nWhen that the network is reachable\n\nMessage:\n\n couldn't open player from feed (RuntimeError)\n./features/lib/page/explore.rb:38:in `block in touch_track_with_title_and_wait_for_player'\n./features/lib/page/explore.rb:57:in `call'\n./features/lib/page/explore.rb:57:in `track_with_title'\n./features/lib/page/explore.rb:24:in `touch_track_with_title_and_wait_for_player'\n./features/step_definitions/explore_page_steps.rb:54:in `/^I tap on track titled \"(.*)\"$/'\n./features/step_definitions/player_page_steps.rb:4:in `/^I go to \"(.*)\" player_page$/'\nfeatures/acceptance/player/player_like.feature:66:in `And I go to \"Trending Music Track 1\" player_page'\n ",
|
106
|
+
"failedSince": 223,
|
107
|
+
"name": "When a user is offline and likes a track, display liked state and sync when online again",
|
108
|
+
"skipped": false,
|
109
|
+
"skippedMessage": null,
|
110
|
+
"status": "REGRESSION",
|
111
|
+
"stderr": "",
|
112
|
+
"stdout": ""
|
113
|
+
},
|
114
|
+
{
|
115
|
+
"age": 7,
|
116
|
+
"className": "Search",
|
117
|
+
"duration": 26.78047,
|
118
|
+
"errorDetails": "failed ErrorView should not be shown when clearing search results",
|
119
|
+
"errorStackTrace": "\n Scenario: ErrorView should not be shown when clearing search results\n\nGiven explore and signin and search datasets are loaded\nAnd that the app is started\nAnd I am on search_page\nGiven that \"Search 0\" endpoint returns status code 404\nWhen I search for \"skrillex rulez\"\nThen I should not see any results\nAnd I should see the server_error_view\nAnd I should not see header_logo_view\nGiven search dataset is loaded\nWhen I clear the search box\nWhen I search for \"skrillex rulez\"\nAnd search results are loaded\nWhen I clear the search box\nThen I should not see the server_error_view\nAnd I should not see header_logo_view\n\nMessage:\n\n Error View is visible but it should not be (elapsed time: 15.001035, time 2014-09-24 21:21:04 +0200) (RuntimeError)\n./features/lib/helpers/wait_until.rb:28:in `rescue in wait_until'\n./features/lib/helpers/wait_until.rb:15:in `wait_until'\n./features/lib/helpers/waiter.rb:148:in `perform_until'\n./features/lib/helpers/waiter.rb:144:in `perform_until_after_delay'\n./features/step_definitions/search_page_steps.rb:78:in `/^I should not see the server_error_view$/'\nfeatures/acceptance/search/search.feature:121:in `Then I should not see the server_error_view'\n ",
|
120
|
+
"failedSince": 217,
|
121
|
+
"name": "ErrorView should not be shown when clearing search results",
|
122
|
+
"skipped": false,
|
123
|
+
"skippedMessage": null,
|
124
|
+
"status": "FAILED",
|
125
|
+
"stderr": "",
|
126
|
+
"stdout": ""
|
127
|
+
},
|
128
|
+
{
|
129
|
+
"age": 2,
|
130
|
+
"className": "Flaky Spec A",
|
131
|
+
"duration": 2.83868,
|
132
|
+
"errorDetails": "failed Mini waveform stops animating on track error",
|
133
|
+
"errorStackTrace": "\n Scenario: Mini waveform stops animating on track error\n\nGiven explore and player and waveform datasets are loaded\nAnd that the app is started\nAnd I am on explore_page\nAnd track_list loaded items\nWhen I go to \"Trending Music Track 1\" player_page\nThen I am in play state\nGiven that the network is unreachable\nThen offline_bar should be in unreachable state\nAnd I tap the next_player_page_button until I'm on \"Trending Music Track 3\" player_page\nThen I am in error state\nWhen I close the player\nThen mini waveform view should not be animating\n\nMessage:\n\n expected visible? to return true, got false (RSpec::Expectations::ExpectationNotMetError)\n./features/step_definitions/player_page_steps.rb:192:in `/^I should see the player error retry button$/'\n./features/step_definitions/player_page_steps.rb:177:in `/^I am in error state$/'\nfeatures/acceptance/player/player_shortcut.feature:43:in `Then I am in error state'\n ",
|
134
|
+
"failedSince": 221,
|
135
|
+
"name": "Mini waveform stops animating on track error",
|
136
|
+
"skipped": false,
|
137
|
+
"skippedMessage": null,
|
138
|
+
"status": "FAILED",
|
139
|
+
"stderr": "",
|
140
|
+
"stdout": ""
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"age": 6,
|
144
|
+
"className": "Search",
|
145
|
+
"duration": 26.590137,
|
146
|
+
"errorDetails": "failed ErrorView should not be shown when clearing search results",
|
147
|
+
"errorStackTrace": "\n Scenario: ErrorView should not be shown when clearing search results\n\nGiven explore and signin and search datasets are loaded\nAnd that the app is started\nAnd I am on search_page\nGiven that \"Search 0\" endpoint returns status code 404\nWhen I search for \"skrillex rulez\"\nThen I should not see any results\nAnd I should see the server_error_view\nAnd I should not see header_logo_view\nGiven search dataset is loaded\nWhen I clear the search box\nWhen I search for \"skrillex rulez\"\nAnd search results are loaded\nWhen I clear the search box\nThen I should not see the server_error_view\nAnd I should not see header_logo_view\n\nMessage:\n\n Error View is visible but it should not be (elapsed time: 15.001807, time 2014-09-24 21:12:29 +0200) (RuntimeError)\n./features/lib/helpers/wait_until.rb:28:in `rescue in wait_until'\n./features/lib/helpers/wait_until.rb:15:in `wait_until'\n./features/lib/helpers/waiter.rb:148:in `perform_until'\n./features/lib/helpers/waiter.rb:144:in `perform_until_after_delay'\n./features/step_definitions/search_page_steps.rb:78:in `/^I should not see the server_error_view$/'\nfeatures/acceptance/search/search.feature:121:in `Then I should not see the server_error_view'\n ",
|
148
|
+
"failedSince": 217,
|
149
|
+
"name": "ErrorView should not be shown when clearing search results",
|
150
|
+
"skipped": false,
|
151
|
+
"skippedMessage": null,
|
152
|
+
"status": "FAILED",
|
153
|
+
"stderr": "",
|
154
|
+
"stdout": ""
|
155
|
+
},
|
156
|
+
{
|
157
|
+
"age": 1,
|
158
|
+
"className": "Flaky Spec B",
|
159
|
+
"duration": 30.674717,
|
160
|
+
"errorDetails": "failed Going back after playing ad does not show ad again",
|
161
|
+
"errorStackTrace": "\n Scenario: Going back after playing ad does not show ad again\n\nGiven explore and player and waveform and audio_ad datasets are loaded\nAnd that the app is started\nAnd I am on explore_page\nGiven I go to \"Trending Music Track 1\" player_page\nAnd audio ad has loaded after \"Trending Music Track 1\"\nWhen I tap the next_player_page_button\nThen I should be on audio ad page\nAnd I should hear the audio ad \"MONEYZZZZ\"\nGiven I really want to wait for 4 seconds\nWhen I tap the next_player_page_button\nThen I should be on \"Trending Music Track 2\" player_page\nAnd I should hear music for track \"Trending Music Track 2\"\nAnd I should see the leave_behind\nWhen I tap the leave_behind close button\nThen I should not see the leave_behind\nWhen I tap the previous_player_page_button\nThen I should be on \"Trending Music Track 1\" player_page\n\nMessage:\n\n timed out waiting: timeout = 15, poll_sleep = 0.5 (elapsed time: 15.001166, time 2014-09-24 21:18:19 +0200) (RuntimeError)\n./features/lib/helpers/wait_until.rb:28:in `rescue in wait_until'\n./features/lib/helpers/wait_until.rb:15:in `wait_until'\n./features/step_definitions/player_page_steps.rb:63:in `/^I should be on \"(.*)\" player_page$/'\nfeatures/acceptance/player/player_audio_ad_playback.feature:52:in `Then I should be on \"Trending Music Track 1\" player_page'\n ",
|
162
|
+
"failedSince": 220,
|
163
|
+
"name": "Going back after playing ad does not show ad again",
|
164
|
+
"skipped": false,
|
165
|
+
"skippedMessage": null,
|
166
|
+
"status": "FAILED",
|
167
|
+
"stderr": "",
|
168
|
+
"stdout": ""
|
169
|
+
}
|
170
|
+
]
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
4
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
5
|
+
#
|
6
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
7
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
8
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
9
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
10
|
+
# a separate helper file that requires the additional dependencies and performs
|
11
|
+
# the additional setup, and require it from the spec files that actually need it.
|
12
|
+
#
|
13
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
14
|
+
# users commonly want.
|
15
|
+
#
|
16
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
17
|
+
RSpec.configure do |config|
|
18
|
+
# rspec-expectations config goes here. You can use an alternate
|
19
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
20
|
+
# assertions if you prefer.
|
21
|
+
config.expect_with :rspec do |expectations|
|
22
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
23
|
+
# and `failure_message` of custom matchers include text for helper methods
|
24
|
+
# defined using `chain`, e.g.:
|
25
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
26
|
+
# # => "be bigger than 2 and smaller than 4"
|
27
|
+
# ...rather than:
|
28
|
+
# # => "be bigger than 2"
|
29
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
30
|
+
end
|
31
|
+
|
32
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
33
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
34
|
+
config.mock_with :rspec do |mocks|
|
35
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
36
|
+
# a real object. This is generally recommended, and will default to
|
37
|
+
# `true` in RSpec 4.
|
38
|
+
mocks.verify_partial_doubles = true
|
39
|
+
end
|
40
|
+
|
41
|
+
# The settings below are suggested to provide a good initial experience
|
42
|
+
# with RSpec, but feel free to customize to your heart's content.
|
43
|
+
=begin
|
44
|
+
# These two settings work together to allow you to limit a spec run
|
45
|
+
# to individual examples or groups you care about by tagging them with
|
46
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
47
|
+
# get run.
|
48
|
+
config.filter_run :focus
|
49
|
+
config.run_all_when_everything_filtered = true
|
50
|
+
|
51
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
52
|
+
# For more details, see:
|
53
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
54
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
55
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
56
|
+
config.disable_monkey_patching!
|
57
|
+
|
58
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
59
|
+
# be too noisy due to issues in dependencies.
|
60
|
+
config.warnings = true
|
61
|
+
|
62
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
63
|
+
# file, and it's useful to allow more verbose output when running an
|
64
|
+
# individual spec file.
|
65
|
+
if config.files_to_run.one?
|
66
|
+
# Use the documentation formatter for detailed output,
|
67
|
+
# unless a formatter has already been configured
|
68
|
+
# (e.g. via a command-line flag).
|
69
|
+
config.default_formatter = 'doc'
|
70
|
+
end
|
71
|
+
|
72
|
+
# Print the 10 slowest examples and example groups at the
|
73
|
+
# end of the spec run, to help surface which specs are running
|
74
|
+
# particularly slow.
|
75
|
+
config.profile_examples = 10
|
76
|
+
|
77
|
+
# Run specs in random order to surface order dependencies. If you find an
|
78
|
+
# order dependency and want to debug it, you can fix the order by providing
|
79
|
+
# the seed, which is printed after each run.
|
80
|
+
# --seed 1234
|
81
|
+
config.order = :random
|
82
|
+
|
83
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
84
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
85
|
+
# test failures related to randomization by passing the same `--seed` value
|
86
|
+
# as the one that triggered the failure.
|
87
|
+
Kernel.srand config.seed
|
88
|
+
=end
|
89
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'korinthenkacker/test_case'
|
3
|
+
|
4
|
+
module Korinthenkacker
|
5
|
+
describe TestCase do
|
6
|
+
let(:test_case_a) { TestCase.new(json_a, 1) }
|
7
|
+
let(:test_case_b) { TestCase.new(json_b, 2) }
|
8
|
+
|
9
|
+
describe '#==' do
|
10
|
+
context 'with same name and same class name' do
|
11
|
+
let(:json_a) { {'name' => 'name', 'className' => 'class_name'} }
|
12
|
+
let(:json_b) { {'name' => 'name', 'className' => 'class_name'} }
|
13
|
+
|
14
|
+
it 'is considered equal' do
|
15
|
+
expect(test_case_a).to eql(test_case_b)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with same name but different class name' do
|
20
|
+
let(:json_a) { {'name' => 'name', 'className' => 'class_name_a'} }
|
21
|
+
let(:json_b) { {'name' => 'name', 'className' => 'class_name_b'} }
|
22
|
+
|
23
|
+
it 'is NOT considered equal' do
|
24
|
+
expect(test_case_a).to_not eql(test_case_b)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with different name but same class name' do
|
29
|
+
let(:json_a) { {'name' => 'name_a', 'className' => 'class_name'} }
|
30
|
+
let(:json_b) { {'name' => 'name_b', 'className' => 'class_name'} }
|
31
|
+
|
32
|
+
it 'is NOT considered equal' do
|
33
|
+
expect(test_case_a).to_not eql(test_case_b)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with different name and different class name' do
|
38
|
+
let(:json_a) { {'name' => 'name_a', 'className' => 'class_name_a'} }
|
39
|
+
let(:json_b) { {'name' => 'name_b', 'className' => 'class_name_b'} }
|
40
|
+
|
41
|
+
it 'is NOT considered equal' do
|
42
|
+
expect(test_case_a).to_not eql(test_case_b)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#sibling?' do
|
48
|
+
context 'when equal and same failed_since' do
|
49
|
+
let(:json_a) { {'name' => 'name', 'className' => 'class_name', 'failedSince' => 42} }
|
50
|
+
let(:json_b) { {'name' => 'name', 'className' => 'class_name', 'failedSince' => 42} }
|
51
|
+
|
52
|
+
it 'returns false' do
|
53
|
+
expect(test_case_a.sibling?(test_case_b)).to be_falsy
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when equal but different failed_since' do
|
58
|
+
let(:json_a) { {'name' => 'name', 'className' => 'class_name', 'failedSince' => 1} }
|
59
|
+
let(:json_b) { {'name' => 'name', 'className' => 'class_name', 'failedSince' => 42} }
|
60
|
+
|
61
|
+
it 'returns false' do
|
62
|
+
expect(test_case_a.sibling?(test_case_b)).to be_truthy
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when not equal and same failed_since' do
|
67
|
+
let(:json_a) { {'name' => 'nameA', 'className' => 'class_nameA', 'failedSince' => 42} }
|
68
|
+
let(:json_b) { {'name' => 'nameB', 'className' => 'class_nameB', 'failedSince' => 42} }
|
69
|
+
|
70
|
+
it 'returns false' do
|
71
|
+
expect(test_case_a.sibling?(test_case_b)).to be_falsy
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when not equal and different failed_since' do
|
76
|
+
let(:json_a) { {'name' => 'nameA', 'className' => 'class_nameA', 'failedSince' => 1} }
|
77
|
+
let(:json_b) { {'name' => 'nameB', 'className' => 'class_nameB', 'failedSince' => 42} }
|
78
|
+
|
79
|
+
it 'returns false' do
|
80
|
+
expect(test_case_a.sibling?(test_case_b)).to be_falsy
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: korinthenkacker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vincent Garrigues
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description: Find out what the fuck is going on with those tests
|
56
70
|
email:
|
57
71
|
- vincent@soundcloud.com
|
@@ -61,6 +75,7 @@ extensions: []
|
|
61
75
|
extra_rdoc_files: []
|
62
76
|
files:
|
63
77
|
- .gitignore
|
78
|
+
- .rspec
|
64
79
|
- .rvmrc
|
65
80
|
- Gemfile
|
66
81
|
- LICENSE.txt
|
@@ -72,10 +87,19 @@ files:
|
|
72
87
|
- lib/korinthenkacker/api.rb
|
73
88
|
- lib/korinthenkacker/cli.rb
|
74
89
|
- lib/korinthenkacker/configuration.rb
|
90
|
+
- lib/korinthenkacker/filters/failed.rb
|
91
|
+
- lib/korinthenkacker/filters/flaky.rb
|
75
92
|
- lib/korinthenkacker/job_info.rb
|
93
|
+
- lib/korinthenkacker/reporters/simple.rb
|
94
|
+
- lib/korinthenkacker/reporters/verbose.rb
|
76
95
|
- lib/korinthenkacker/test_case.rb
|
77
96
|
- lib/korinthenkacker/test_report.rb
|
78
97
|
- lib/korinthenkacker/version.rb
|
98
|
+
- spec/filters/failed_spec.rb
|
99
|
+
- spec/filters/flaky_spec.rb
|
100
|
+
- spec/fixtures/test_cases.json
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
- spec/test_case_spec.rb
|
79
103
|
homepage: ''
|
80
104
|
licenses:
|
81
105
|
- MIT
|
@@ -96,8 +120,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
120
|
version: '0'
|
97
121
|
requirements: []
|
98
122
|
rubyforge_project:
|
99
|
-
rubygems_version: 2.
|
123
|
+
rubygems_version: 2.2.1
|
100
124
|
signing_key:
|
101
125
|
specification_version: 4
|
102
126
|
summary: Seriously Jenkins?
|
103
|
-
test_files:
|
127
|
+
test_files:
|
128
|
+
- spec/filters/failed_spec.rb
|
129
|
+
- spec/filters/flaky_spec.rb
|
130
|
+
- spec/fixtures/test_cases.json
|
131
|
+
- spec/spec_helper.rb
|
132
|
+
- spec/test_case_spec.rb
|