quarantine 2.1.3 → 2.2.0

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
  SHA256:
3
- metadata.gz: 6ab8e4aa2ba3c2ab497cb3adfb08b6c14459eab525f26a00f4bc1fb9b27e1084
4
- data.tar.gz: ffafe0bdf3508389ae614ab5b8946c4cb9b5303f7697ca4b378b6284f335375f
3
+ metadata.gz: c846ed3cf614eecefab5610bfb5d693444099fe90b6b429e4c697c16a014e21b
4
+ data.tar.gz: 5d17a24b4735f4c34af2d0902c0e3a7199750ce592694b5f9fe375928ada9d03
5
5
  SHA512:
6
- metadata.gz: c4d12718e41b13558f30add75b2a5d5e25f5d29d4e19b55704e7500c1980f7192ed1a8fa3e4fc83e45329486c94bae42bd56f99a718144f42c6884878b926faf
7
- data.tar.gz: 283aa10d1dafe98d3e5ed08f1add97facdcfbe6f4a1761759e42677b7dd26fafbc323d958ab81965076a1d19e951e18c67e35e01679ad43e44d622876649641f
6
+ metadata.gz: cb20ce19d6581b4836486176a080a6204a66f93d609e2b76a5d7bb91886b97e07466026fe45d0d7d4c16b8d2f072212a4ff982f42c40a55d68f42413276a92c4
7
+ data.tar.gz: bc093985a12b77f636d577b3fed3ab783f5fe206350a759a796097eee93976f42cb2fa199101a853f81d729aa109cce612f6deb4ba75748779281086e2591bca
data/lib/quarantine.rb CHANGED
@@ -9,23 +9,6 @@ require 'quarantine/databases/base'
9
9
  require 'quarantine/databases/dynamo_db'
10
10
  require 'quarantine/databases/google_sheets'
11
11
 
12
- module RSpec
13
- module Core
14
- class Example
15
- extend T::Sig
16
-
17
- # The implementation of clear_exception in rspec-retry doesn't work
18
- # for examples that use `it_behaves_like`, so we implement our own version that
19
- # clear the exception field recursively.
20
- sig { void }
21
- def clear_exception!
22
- @exception = T.let(nil, T.untyped)
23
- T.unsafe(self).example.clear_exception! if defined?(example)
24
- end
25
- end
26
- end
27
- end
28
-
29
12
  class Quarantine
30
13
  extend T::Sig
31
14
 
@@ -41,7 +41,13 @@ class Quarantine
41
41
  indexes = Hash[parsed_rows.each_with_index.map { |item, idx| [item['id'], idx] }]
42
42
 
43
43
  items.each do |item|
44
- cells = headers.map { |header| item[header].to_s }
44
+ cells = headers.map do |header|
45
+ match = header.match(/^(extra_)?(.+)/)
46
+ extra, name = match[1..]
47
+ puts "header: #{header}, extra: #{extra}, name: #{name}"
48
+ value = extra ? item['extra_attributes'][name.to_sym] : item[name]
49
+ value.to_s
50
+ end
45
51
  row_idx = indexes[item['id']]
46
52
  if row_idx
47
53
  # Overwrite existing row
@@ -104,8 +110,10 @@ class Quarantine
104
110
  hash_row = Hash[headers.zip(row)]
105
111
  # TODO: use Google Sheets developer metadata to store type information
106
112
  unless hash_row['id'].empty?
107
- hash_row['extra_attributes'] = JSON.parse(hash_row['extra_attributes']) if hash_row['extra_attributes']
108
- hash_row
113
+ extra_values, base_values = hash_row.partition{|k, v| k.start_with?('extra_')}
114
+ base_hash = Hash[base_values]
115
+ base_hash['extra_attributes'] = Hash[extra_values]
116
+ base_hash
109
117
  end
110
118
  end.compact
111
119
  end
@@ -1,5 +1,22 @@
1
1
  # typed: strict
2
2
 
3
+ module RSpec
4
+ module Core
5
+ class Example
6
+ extend T::Sig
7
+
8
+ # The implementation of clear_exception in rspec-retry doesn't work
9
+ # for examples that use `it_behaves_like`, so we implement our own version that
10
+ # clear the exception field recursively.
11
+ sig { void }
12
+ def clear_exception!
13
+ @exception = T.let(nil, T.untyped)
14
+ T.unsafe(self).example.clear_exception! if defined?(example)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
3
20
  class Quarantine
4
21
  module RSpecAdapter
5
22
  extend T::Sig
@@ -52,33 +69,47 @@ class Quarantine
52
69
  end
53
70
  end
54
71
 
72
+ sig { params(example: RSpec::Core::Example).returns(T.nilable([Symbol, T::Boolean])) }
73
+ def self.final_status(example)
74
+ metadata = example.metadata
75
+
76
+ # The user may define their own after hook that marks an example as flaky in its metadata.
77
+ previously_quarantined = Quarantine::RSpecAdapter.quarantine.test_quarantined?(example) || metadata[:flaky]
78
+
79
+ if example.exception
80
+ # The example failed _this try_.
81
+ if metadata[:retry_attempts] + 1 == metadata[:retry]
82
+ # The example failed all its retries - if it's already quarantined, keep it that way;
83
+ # otherwise, mark it as failing.
84
+ if RSpec.configuration.skip_quarantined_tests && previously_quarantined
85
+ return [:quarantined, false]
86
+ else
87
+ return [:failing, false]
88
+ end
89
+ end
90
+ # The example failed, but it's not the final retry yet, so return nil.
91
+ return nil
92
+ elsif metadata[:retry_attempts] > 0
93
+ # The example passed this time, but failed one or more times before - the definition of a flaky test.
94
+ return [:quarantined, false]
95
+ elsif previously_quarantined
96
+ # The example passed the first time, but it's already marked quarantined, so keep it that way.
97
+ return [:quarantined, true]
98
+ else
99
+ return [:passing, true]
100
+ end
101
+ end
102
+
55
103
  # Purpose: binds quarantine to record test statuses
56
104
  sig { void }
57
105
  def self.bind_on_test
58
106
  ::RSpec.configure do |config|
59
107
  config.after(:each) do |example|
60
- metadata = example.metadata
61
-
62
- # optionally, the upstream RSpec configuration could define an after hook that marks an example as flaky in
63
- # the example's metadata
64
- quarantined = Quarantine::RSpecAdapter.quarantine.test_quarantined?(example) || metadata[:flaky]
65
- if example.exception
66
- if metadata[:retry_attempts] + 1 == metadata[:retry]
67
- # will record the failed test if it's final retry from the rspec-retry gem
68
- if RSpec.configuration.skip_quarantined_tests && quarantined
69
- example.clear_exception!
70
- Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: false)
71
- else
72
- Quarantine::RSpecAdapter.quarantine.on_test(example, :failing, passed: false)
73
- end
74
- end
75
- elsif metadata[:retry_attempts] > 0
76
- # will record the flaky test if it failed the first run but passed a subsequent run
77
- Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: false)
78
- elsif quarantined
79
- Quarantine::RSpecAdapter.quarantine.on_test(example, :quarantined, passed: true)
80
- else
81
- Quarantine::RSpecAdapter.quarantine.on_test(example, :passing, passed: true)
108
+ result = Quarantine::RSpecAdapter.final_status(example)
109
+ if result
110
+ status, passed = result
111
+ example.clear_exception! if status == :quarantined && !passed
112
+ Quarantine::RSpecAdapter.quarantine.on_test(example, status, passed: passed)
82
113
  end
83
114
  end
84
115
  end
@@ -1,3 +1,3 @@
1
1
  class Quarantine
2
- VERSION = '2.1.3'.freeze
2
+ VERSION = '2.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quarantine
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flexport Engineering, Eric Zhu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-15 00:00:00.000000000 Z
11
+ date: 2021-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec