mutant 0.5.9 → 0.5.10

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
  SHA1:
3
- metadata.gz: cf574dc48496c63daaefac87f3603ba5b2c4703a
4
- data.tar.gz: 2666871190b2b4788d9e216f3e3fe155833b6e00
3
+ metadata.gz: 84a8405d55414b2cd802d72e2a8fab5a3a2e9383
4
+ data.tar.gz: e4acca9abe75f892f73c1b830473d17630ec1001
5
5
  SHA512:
6
- metadata.gz: b837342c26c28e970e5ff9784531fce12fd26fb30dde6ee7ef0f856910a44026891534468a488459b81e7e653167948c913ef13e0f5e6b01f16c7c45ab23413a
7
- data.tar.gz: ff9190edab3e81f861e06767196b268327e690b22b1229b94296af49c596b3e057fc45ffc11471a9fe18730e42ee6dec176b03fab465bee3917c189bdb8fc84d
6
+ metadata.gz: 1ca5f7c4ff72450792d49df2c40d10a45335442d095b54564c8f650bf9218fed4b9821994fa17162d27e4b1e2c1087cfc2f4bf8661e3adf63e73c187e57475d1
7
+ data.tar.gz: 8a0154fce8d6a39824108c609c2a76f170f5fb855fa8b5cfb4224b91a5528106b41d83500e5af0b67b2d7775ca4a00b24e5ffbe090369efa94c4e9525e0fccc4
@@ -8,7 +8,6 @@ rvm:
8
8
  matrix:
9
9
  allow_failures:
10
10
  - rvm: rbx
11
- - rvm: 2.1.1
12
11
  notifications:
13
12
  irc:
14
13
  channels:
@@ -1,3 +1,12 @@
1
+ # v0.5.10 2014-04-06
2
+
3
+ Changes:
4
+
5
+ * Fix crash without conditionals
6
+ * Remove dependency to descendants tracker
7
+ * Add mutation #== => #eql?, #equal?
8
+ * Add mutation #eql? => #equal?
9
+
1
10
  # v0.5.9 2014-03-28
2
11
 
3
12
  Changes:
data/README.md CHANGED
@@ -4,6 +4,7 @@ mutant
4
4
  [![Build Status](https://secure.travis-ci.org/mbj/mutant.png?branch=master)](http://travis-ci.org/mbj/mutant)
5
5
  [![Dependency Status](https://gemnasium.com/mbj/mutant.png)](https://gemnasium.com/mbj/mutant)
6
6
  [![Code Climate](https://codeclimate.com/github/mbj/mutant.png)](https://codeclimate.com/github/mbj/mutant)
7
+ [![Inline docs](http://inch-pages.github.io/github/mbj/mutant.png)](http://inch-pages.github.io/github/mbj/mutant)
7
8
 
8
9
  Mutant is a mutation testing tool for ruby.
9
10
 
@@ -68,6 +69,8 @@ emits around 3-6 mutations.
68
69
 
69
70
  Currently mutant covers the majority of ruby's complex nodes that often occur in method bodies.
70
71
 
72
+ NOTE: The textbook examples you find on mutation testing are intentionally not implemented. This is subjected to change.
73
+
71
74
  Some stats from the [axiom](https://github.com/dkubb/axiom) library:
72
75
 
73
76
  ```
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 18
3
- total_score: 802
3
+ total_score: 804
@@ -5,7 +5,6 @@ require 'set'
5
5
  require 'adamantium'
6
6
  require 'ice_nine'
7
7
  require 'abstract_type'
8
- require 'descendants_tracker'
9
8
  require 'securerandom'
10
9
  require 'equalizer'
11
10
  require 'digest/sha1'
@@ -22,8 +21,10 @@ require 'morpher'
22
21
 
23
22
  # Library namespace
24
23
  module Mutant
25
- # The empty string used within this namespace
24
+ # The frozen empty string used within mutant
26
25
  EMPTY_STRING = ''.freeze
26
+ # The frozen empty array used within mutant
27
+ EMPTY_ARRAY = [].freeze
27
28
  end # Mutant
28
29
 
29
30
  require 'mutant/version'
@@ -66,6 +66,9 @@ module Mutant
66
66
  # @param [#call] selector
67
67
  #
68
68
  # @return [self]
69
+ #
70
+ # @api private
71
+ #
69
72
  def add_subject_selector(selector)
70
73
  @subject_selectors << selector
71
74
  self
@@ -84,6 +87,12 @@ module Mutant
84
87
  self
85
88
  end
86
89
 
90
+ # Return generated matcher
91
+ #
92
+ # @return [Mutant::Matcher]
93
+ #
94
+ # @api private
95
+ #
87
96
  def matcher
88
97
  if @matchers.empty?
89
98
  raise(Error, 'No patterns given')
@@ -80,6 +80,12 @@ module Mutant
80
80
  #
81
81
  # @param [String] input
82
82
  #
83
+ # @return [Classifier]
84
+ # if classifier can be found
85
+ #
86
+ # @return [nil]
87
+ # otherwise
88
+ #
83
89
  # @api private
84
90
  #
85
91
  def self.find(input)
@@ -4,7 +4,6 @@ module Mutant
4
4
  # Abstract matcher to find subjects to mutate
5
5
  class Matcher
6
6
  include Adamantium::Flat, Enumerable, AbstractType
7
- extend DescendantsTracker
8
7
 
9
8
  # Enumerate subjects
10
9
  #
@@ -181,7 +181,7 @@ module Mutant
181
181
  # @api private
182
182
  #
183
183
  def emit_nil
184
- emit(N_NIL) unless agsn_left?
184
+ emit(N_NIL) unless asgn_left?
185
185
  end
186
186
 
187
187
  # Return new self typed child
@@ -228,7 +228,7 @@ module Mutant
228
228
  #
229
229
  # @api private
230
230
  #
231
- def agsn_left?
231
+ def asgn_left?
232
232
  OP_ASSIGN.include?(parent_type) && parent.left.equal?(node)
233
233
  end
234
234
 
@@ -20,7 +20,7 @@ module Mutant
20
20
  # @api private
21
21
  #
22
22
  def dispatch
23
- emit_condition_mutations
23
+ emit_condition_mutations if condition
24
24
  emit_when_mutations
25
25
  emit_else_mutations
26
26
  emit_nil
@@ -11,10 +11,12 @@ module Mutant
11
11
 
12
12
  children :receiver, :selector
13
13
 
14
- SELECTOR_REPLACEMENTS = {
15
- send: :public_send,
16
- gsub: :sub
17
- }.freeze
14
+ SELECTOR_REPLACEMENTS = IceNine.deep_freeze(
15
+ send: [:public_send],
16
+ gsub: [:sub],
17
+ eql?: [:equal?],
18
+ :== => [:eql?, :equal?]
19
+ )
18
20
 
19
21
  INDEX_REFERENCE = :[]
20
22
  INDEX_ASSIGN = :[]=
@@ -118,8 +120,9 @@ module Mutant
118
120
  # @api private
119
121
  #
120
122
  def emit_selector_replacement
121
- replacement = SELECTOR_REPLACEMENTS.fetch(selector) { return }
122
- emit_selector(replacement)
123
+ SELECTOR_REPLACEMENTS.fetch(selector, EMPTY_ARRAY).each do |replacement|
124
+ emit_selector(replacement)
125
+ end
123
126
  end
124
127
 
125
128
  # Emit naked receiver mutation
@@ -21,6 +21,7 @@ module Mutant
21
21
  def dispatch
22
22
  emit(left)
23
23
  emit_left_mutations
24
+ emit_selector_replacement
24
25
  emit(right) unless right.type == :splat
25
26
  emit_right_mutations
26
27
  end
@@ -18,7 +18,11 @@ module Mutant
18
18
  # @api private
19
19
  #
20
20
  def dispatch
21
- mutate_body
21
+ if body
22
+ mutate_body
23
+ else
24
+ emit_child_update(body_index, RAISE)
25
+ end
22
26
  mutate_conditions
23
27
  end
24
28
 
@@ -43,7 +47,31 @@ module Mutant
43
47
  # @api private
44
48
  #
45
49
  def mutate_body
46
- mutate_child(children.length - 1)
50
+ mutate_child(body_index)
51
+ end
52
+
53
+ # Return body node
54
+ #
55
+ # @return [Parser::AST::Node]
56
+ # if body is present
57
+ #
58
+ # @return [nil]
59
+ # otherwise
60
+ #
61
+ # @api private
62
+ #
63
+ def body
64
+ children[body_index]
65
+ end
66
+
67
+ # Return body index
68
+ #
69
+ # @return [Fixnum]
70
+ #
71
+ # @api private
72
+ #
73
+ def body_index
74
+ children.length - 1
47
75
  end
48
76
 
49
77
  end # When
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # The current mutant version
5
- VERSION = '0.5.9'.freeze
5
+ VERSION = '0.5.10'.freeze
6
6
  end # Mutant
@@ -23,20 +23,19 @@ Gem::Specification.new do |gem|
23
23
 
24
24
  gem.required_ruby_version = '>= 1.9.3'
25
25
 
26
- gem.add_runtime_dependency('parser', '~> 2.1')
27
- gem.add_runtime_dependency('morpher', '~> 0.2.0')
28
- gem.add_runtime_dependency('procto', '~> 0.0.2')
29
- gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
30
- gem.add_runtime_dependency('unparser', '~> 0.1.8')
31
- gem.add_runtime_dependency('ice_nine', '~> 0.11.0')
32
- gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
33
- gem.add_runtime_dependency('adamantium', '~> 0.2.0')
34
- gem.add_runtime_dependency('memoizable', '~> 0.4.2')
35
- gem.add_runtime_dependency('equalizer', '~> 0.0.7')
36
- gem.add_runtime_dependency('inflecto', '~> 0.0.2')
37
- gem.add_runtime_dependency('anima', '~> 0.2.0')
38
- gem.add_runtime_dependency('concord', '~> 0.1.4')
39
- gem.add_runtime_dependency('diff-lcs', '~> 1.2')
26
+ gem.add_runtime_dependency('parser', '~> 2.1')
27
+ gem.add_runtime_dependency('diff-lcs', '~> 1.2')
28
+ gem.add_runtime_dependency('morpher', '~> 0.2.1')
29
+ gem.add_runtime_dependency('procto', '~> 0.0.2')
30
+ gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
31
+ gem.add_runtime_dependency('unparser', '~> 0.1.10')
32
+ gem.add_runtime_dependency('ice_nine', '~> 0.11.0')
33
+ gem.add_runtime_dependency('adamantium', '~> 0.2.0')
34
+ gem.add_runtime_dependency('memoizable', '~> 0.4.2')
35
+ gem.add_runtime_dependency('equalizer', '~> 0.0.9')
36
+ gem.add_runtime_dependency('inflecto', '~> 0.0.2')
37
+ gem.add_runtime_dependency('anima', '~> 0.2.0')
38
+ gem.add_runtime_dependency('concord', '~> 0.1.4')
40
39
 
41
40
  gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
42
41
  end
@@ -9,12 +9,48 @@ describe Mutant::Mutator::Node::Case do
9
9
  Mutant::Random.stub(hex_string: random_string)
10
10
  end
11
11
 
12
+ context 'without condition' do
13
+ let(:source) do
14
+ <<-RUBY
15
+ case
16
+ when true
17
+ else
18
+ end
19
+ RUBY
20
+ end
21
+
22
+ let(:mutations) do
23
+ mutations = []
24
+ mutations << 'nil'
25
+ mutations << <<-RUBY
26
+ case
27
+ when true
28
+ raise
29
+ else
30
+ end
31
+ RUBY
32
+ mutations << <<-RUBY
33
+ case
34
+ when false
35
+ else
36
+ end
37
+ RUBY
38
+ mutations << <<-RUBY
39
+ case
40
+ when nil
41
+ else
42
+ end
43
+ RUBY
44
+ end
45
+
46
+ it_should_behave_like 'a mutator'
47
+ end
48
+
12
49
  context 'with multiple when branches' do
13
50
  let(:source) do
14
51
  <<-RUBY
15
52
  case :condition
16
53
  when :foo
17
- :foo
18
54
  when :bar, :baz
19
55
  :barbaz
20
56
  else
@@ -38,7 +74,6 @@ describe Mutant::Mutator::Node::Case do
38
74
  mutations << <<-RUBY
39
75
  case :condition
40
76
  when :foo
41
- :foo
42
77
  else
43
78
  :else
44
79
  end
@@ -46,7 +81,6 @@ describe Mutant::Mutator::Node::Case do
46
81
  mutations << <<-RUBY
47
82
  case :condition
48
83
  when :foo
49
- :foo
50
84
  when :bar, :baz
51
85
  :barbaz
52
86
  end
@@ -56,7 +90,6 @@ describe Mutant::Mutator::Node::Case do
56
90
  mutations << <<-RUBY
57
91
  case nil
58
92
  when :foo
59
- :foo
60
93
  when :bar, :baz
61
94
  :barbaz
62
95
  else
@@ -66,7 +99,6 @@ describe Mutant::Mutator::Node::Case do
66
99
  mutations << <<-RUBY
67
100
  case :srandom
68
101
  when :foo
69
- :foo
70
102
  when :bar, :baz
71
103
  :barbaz
72
104
  else
@@ -78,17 +110,7 @@ describe Mutant::Mutator::Node::Case do
78
110
  mutations << <<-RUBY
79
111
  case :condition
80
112
  when :foo
81
- nil
82
- when :bar, :baz
83
- :barbaz
84
- else
85
- :else
86
- end
87
- RUBY
88
- mutations << <<-RUBY
89
- case :condition
90
- when :foo
91
- :srandom
113
+ raise
92
114
  when :bar, :baz
93
115
  :barbaz
94
116
  else
@@ -98,7 +120,6 @@ describe Mutant::Mutator::Node::Case do
98
120
  mutations << <<-RUBY
99
121
  case :condition
100
122
  when :foo
101
- :foo
102
123
  when :bar, :baz
103
124
  :srandom
104
125
  else
@@ -108,7 +129,6 @@ describe Mutant::Mutator::Node::Case do
108
129
  mutations << <<-RUBY
109
130
  case :condition
110
131
  when :foo
111
- :foo
112
132
  when :bar, :baz
113
133
  nil
114
134
  else
@@ -118,7 +138,6 @@ describe Mutant::Mutator::Node::Case do
118
138
  mutations << <<-RUBY
119
139
  case :condition
120
140
  when :foo
121
- :foo
122
141
  when :bar, :baz
123
142
  :barbaz
124
143
  else
@@ -128,7 +147,6 @@ describe Mutant::Mutator::Node::Case do
128
147
  mutations << <<-RUBY
129
148
  case :condition
130
149
  when :foo
131
- :foo
132
150
  when :bar, :baz
133
151
  :barbaz
134
152
  else
@@ -140,7 +158,6 @@ describe Mutant::Mutator::Node::Case do
140
158
  mutations << <<-RUBY
141
159
  case :condition
142
160
  when :srandom
143
- :foo
144
161
  when :bar, :baz
145
162
  :barbaz
146
163
  else
@@ -150,7 +167,6 @@ describe Mutant::Mutator::Node::Case do
150
167
  mutations << <<-RUBY
151
168
  case :condition
152
169
  when nil
153
- :foo
154
170
  when :bar, :baz
155
171
  :barbaz
156
172
  else
@@ -160,7 +176,6 @@ describe Mutant::Mutator::Node::Case do
160
176
  mutations << <<-RUBY
161
177
  case :condition
162
178
  when :foo
163
- :foo
164
179
  when :srandom, :baz
165
180
  :barbaz
166
181
  else
@@ -170,7 +185,6 @@ describe Mutant::Mutator::Node::Case do
170
185
  mutations << <<-RUBY
171
186
  case :condition
172
187
  when :foo
173
- :foo
174
188
  when nil, :baz
175
189
  :barbaz
176
190
  else
@@ -180,7 +194,6 @@ describe Mutant::Mutator::Node::Case do
180
194
  mutations << <<-RUBY
181
195
  case :condition
182
196
  when :foo
183
- :foo
184
197
  when :bar, nil
185
198
  :barbaz
186
199
  else
@@ -190,7 +203,6 @@ describe Mutant::Mutator::Node::Case do
190
203
  mutations << <<-RUBY
191
204
  case :condition
192
205
  when :foo
193
- :foo
194
206
  when :bar, :srandom
195
207
  :barbaz
196
208
  else
@@ -200,7 +212,6 @@ describe Mutant::Mutator::Node::Case do
200
212
  mutations << <<-RUBY
201
213
  case :condition
202
214
  when :foo
203
- :foo
204
215
  when :baz
205
216
  :barbaz
206
217
  else
@@ -210,7 +221,6 @@ describe Mutant::Mutator::Node::Case do
210
221
  mutations << <<-RUBY
211
222
  case :condition
212
223
  when :foo
213
- :foo
214
224
  when :bar
215
225
  :barbaz
216
226
  else
@@ -5,7 +5,24 @@ require 'spec_helper'
5
5
  # FIXME: This spec needs to be structured better!
6
6
  describe Mutant::Mutator, 'send' do
7
7
 
8
- context 'when using String#gsub' do
8
+ context 'when using #==' do
9
+ let(:source) { 'foo == bar' }
10
+
11
+ let(:mutations) do
12
+ mutations = []
13
+ mutations << 'foo'
14
+ mutations << 'bar'
15
+ mutations << 'nil == bar'
16
+ mutations << 'foo == nil'
17
+ mutations << 'nil'
18
+ mutations << 'foo.eql?(bar)'
19
+ mutations << 'foo.equal?(bar)'
20
+ end
21
+
22
+ it_should_behave_like 'a mutator'
23
+ end
24
+
25
+ context 'when using #gsub' do
9
26
  let(:source) { 'foo.gsub(a, b)' }
10
27
 
11
28
  let(:mutations) do
@@ -297,7 +314,7 @@ describe Mutant::Mutator, 'send' do
297
314
  it_should_behave_like 'a mutator'
298
315
  end
299
316
 
300
- Mutant::BINARY_METHOD_OPERATORS.each do |operator|
317
+ (Mutant::BINARY_METHOD_OPERATORS - [:==, :eql?]).each do |operator|
301
318
  context 'on literal scalar arguments' do
302
319
  let(:source) { "true #{operator} false" }
303
320
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.5.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-28 00:00:00.000000000 Z
11
+ date: 2014-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -25,89 +25,89 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: morpher
28
+ name: diff-lcs
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.0
33
+ version: '1.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.0
40
+ version: '1.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: procto
42
+ name: morpher
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 0.0.2
47
+ version: 0.2.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: 0.0.2
54
+ version: 0.2.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: abstract_type
56
+ name: procto
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.0.7
61
+ version: 0.0.2
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 0.0.7
68
+ version: 0.0.2
69
69
  - !ruby/object:Gem::Dependency
70
- name: unparser
70
+ name: abstract_type
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: 0.1.8
75
+ version: 0.0.7
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: 0.1.8
82
+ version: 0.0.7
83
83
  - !ruby/object:Gem::Dependency
84
- name: ice_nine
84
+ name: unparser
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ~>
88
88
  - !ruby/object:Gem::Version
89
- version: 0.11.0
89
+ version: 0.1.10
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
- version: 0.11.0
96
+ version: 0.1.10
97
97
  - !ruby/object:Gem::Dependency
98
- name: descendants_tracker
98
+ name: ice_nine
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: 0.0.1
103
+ version: 0.11.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: 0.0.1
110
+ version: 0.11.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: adamantium
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - ~>
144
144
  - !ruby/object:Gem::Version
145
- version: 0.0.7
145
+ version: 0.0.9
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - ~>
151
151
  - !ruby/object:Gem::Version
152
- version: 0.0.7
152
+ version: 0.0.9
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: inflecto
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -192,20 +192,6 @@ dependencies:
192
192
  - - ~>
193
193
  - !ruby/object:Gem::Version
194
194
  version: 0.1.4
195
- - !ruby/object:Gem::Dependency
196
- name: diff-lcs
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ~>
200
- - !ruby/object:Gem::Version
201
- version: '1.2'
202
- type: :runtime
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ~>
207
- - !ruby/object:Gem::Version
208
- version: '1.2'
209
195
  - !ruby/object:Gem::Dependency
210
196
  name: bundler
211
197
  requirement: !ruby/object:Gem::Requirement