quarantine 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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