ruby-measurement 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/CI.yml +30 -0
  3. data/CHANGELOG.md +25 -10
  4. data/README.md +13 -7
  5. data/lib/ruby-measurement/core_ext/string.rb +2 -2
  6. data/lib/ruby-measurement/core_ext/symbol.rb +1 -1
  7. data/lib/ruby-measurement/measurement.rb +101 -42
  8. data/lib/ruby-measurement/unit.rb +34 -28
  9. data/lib/ruby-measurement/version.rb +1 -1
  10. data/ruby-measurement.gemspec +5 -4
  11. data/spec/ruby-measurement/core_ext/numeric_spec.rb +2 -2
  12. data/spec/ruby-measurement/core_ext/string_spec.rb +12 -12
  13. data/spec/ruby-measurement/core_ext/symbol_spec.rb +3 -3
  14. data/spec/ruby-measurement/definitions/metric/area_spec.rb +32 -32
  15. data/spec/ruby-measurement/definitions/metric/capacity_spec.rb +18 -18
  16. data/spec/ruby-measurement/definitions/metric/length_spec.rb +128 -128
  17. data/spec/ruby-measurement/definitions/metric/volume_spec.rb +128 -128
  18. data/spec/ruby-measurement/definitions/metric/weight_spec.rb +160 -160
  19. data/spec/ruby-measurement/definitions/us_customary/area_spec.rb +72 -72
  20. data/spec/ruby-measurement/definitions/us_customary/capacity_spec.rb +32 -32
  21. data/spec/ruby-measurement/definitions/us_customary/length_spec.rb +128 -128
  22. data/spec/ruby-measurement/definitions/us_customary/volume_spec.rb +98 -98
  23. data/spec/ruby-measurement/definitions/us_customary/weight_spec.rb +72 -72
  24. data/spec/ruby-measurement/measurement_spec.rb +238 -164
  25. data/spec/ruby-measurement/unit_builder_spec.rb +35 -35
  26. data/spec/ruby-measurement/unit_spec.rb +84 -41
  27. data/tasks/rspec.rake +1 -1
  28. metadata +29 -25
  29. data/.travis.yml +0 -4
@@ -1,342 +1,416 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe Measurement do
4
- subject { Measurement }
5
-
5
+ RSpec.describe Measurement do
6
+ subject { described_class }
7
+
6
8
  describe '.new' do
7
9
  describe 'with valid quantity' do
8
10
  it 'sets the quantity' do
9
- subject.new(3).quantity.should eq 3
11
+ expect(subject.new(3).quantity).to eq 3
10
12
  end
11
-
13
+
12
14
  it 'sets the default unit' do
13
- subject.new(3).unit.should eq subject::Unit[:count]
15
+ expect(subject.new(3).unit).to eq subject::Unit[:count]
14
16
  end
15
17
  end
16
-
18
+
17
19
  describe 'with valid quantity and unit name' do
18
20
  it 'sets the quantity' do
19
- subject.new(2, :dozen).quantity.should eq 2
21
+ expect(subject.new(2, :dozen).quantity).to eq 2
20
22
  end
21
-
23
+
22
24
  it 'sets the unit' do
23
- subject.new(2, :dozen).unit.should eq subject::Unit[:dozen]
25
+ expect(subject.new(2, :dozen).unit).to eq subject::Unit[:dozen]
24
26
  end
25
27
  end
26
-
28
+
27
29
  describe 'with valid quantity and unit' do
28
30
  it 'sets the quantity' do
29
- subject.new(2, subject::Unit[:dozen]).quantity.should eq 2
31
+ expect(subject.new(2, subject::Unit[:dozen]).quantity).to eq 2
30
32
  end
31
-
33
+
32
34
  it 'sets the unit' do
33
- subject.new(2, subject::Unit[:dozen]).unit.should eq subject::Unit[:dozen]
35
+ expect(subject.new(2, subject::Unit[:dozen]).unit).to eq subject::Unit[:dozen]
34
36
  end
35
37
  end
36
-
38
+
37
39
  describe 'with invalid quantity' do
38
40
  it 'raises exception' do
39
- expect { subject.new('hi') }.to raise_exception
41
+ expect { subject.new('hi') }.to raise_error(ArgumentError, "Invalid quantity: 'hi'")
40
42
  end
41
43
  end
42
-
44
+
43
45
  describe 'with invalid unit' do
44
46
  it 'raises exception' do
45
- expect { subject.new(3, :finklebaum) }.to raise_exception
47
+ expect { subject.new(3, :finklebaum) }.to raise_error(ArgumentError, "Invalid unit: 'finklebaum'")
46
48
  end
47
49
  end
48
50
  end
49
-
51
+
50
52
  describe '.parse' do
51
53
  describe 'quantity' do
52
54
  it 'parses scientific notation' do
53
55
  m = subject.parse('4.3e12')
54
- m.quantity.should eq 4.3e12
55
- m.unit.should eq subject::Unit[:count]
56
-
56
+ expect(m.quantity).to eq 4.3e12
57
+ expect(m.unit).to eq Measurement::Unit[:count]
58
+
57
59
  m = subject.parse('4.3e12 dozen')
58
- m.quantity.should eq 4.3e12
59
- m.unit.should eq subject::Unit[:dozen]
60
-
60
+ expect(m.quantity).to eq 4.3e12
61
+ expect(m.unit).to eq Measurement::Unit[:dozen]
62
+
61
63
  m = subject.parse('4.3e12doz')
62
- m.quantity.should eq 4.3e12
63
- m.unit.should eq subject::Unit[:dozen]
64
+ expect(m.quantity).to eq 4.3e12
65
+ expect(m.unit).to eq Measurement::Unit[:dozen]
64
66
  end
65
-
67
+
66
68
  it 'parses fractions' do
67
69
  m = subject.parse('1/4')
68
- m.quantity.should eq 0.25
69
- m.unit.should eq subject::Unit[:count]
70
-
70
+ expect(m.quantity).to eq 0.25
71
+ expect(m.unit).to eq Measurement::Unit[:count]
72
+
71
73
  m = subject.parse('1/4 dozen')
72
- m.quantity.should eq 0.25
73
- m.unit.should eq subject::Unit[:dozen]
74
-
74
+ expect(m.quantity).to eq 0.25
75
+ expect(m.unit).to eq Measurement::Unit[:dozen]
76
+
75
77
  m = subject.parse('1/4doz')
76
- m.quantity.should eq 0.25
77
- m.unit.should eq subject::Unit[:dozen]
78
+ expect(m.quantity).to eq 0.25
79
+ expect(m.unit).to eq Measurement::Unit[:dozen]
78
80
  end
79
-
81
+
80
82
  it 'parses mixed fractions' do
81
83
  m = subject.parse('3 2/5')
82
- m.quantity.should eq 3.4
83
- m.unit.should eq subject::Unit[:count]
84
-
84
+ expect(m.quantity).to eq 3.4
85
+ expect(m.unit).to eq Measurement::Unit[:count]
86
+
85
87
  m = subject.parse('3 2/5 dozen')
86
- m.quantity.should eq 3.4
87
- m.unit.should eq subject::Unit[:dozen]
88
-
89
- m = subject.parse('3 2/5')
90
- m.quantity.should eq 3.4
91
- m.unit.should eq subject::Unit[:count]
88
+ expect(m.quantity).to eq 3.4
89
+ expect(m.unit).to eq Measurement::Unit[:dozen]
92
90
  end
93
-
91
+
92
+ it 'parses fractions with special characters' do
93
+ m = subject.parse('⅜')
94
+ expect(m.quantity).to eq 0.375
95
+ expect(m.unit).to eq Measurement::Unit[:count]
96
+
97
+ m = subject.parse('⅜ dozen')
98
+ expect(m.quantity).to eq 0.375
99
+ expect(m.unit).to eq Measurement::Unit[:dozen]
100
+
101
+ m = subject.parse('⅜doz')
102
+ expect(m.quantity).to eq 0.375
103
+ expect(m.unit).to eq Measurement::Unit[:dozen]
104
+ end
105
+
106
+ it 'parses mixed fractions with special characters' do
107
+ m = subject.parse('3⅜')
108
+ expect(m.quantity).to eq 3.375
109
+ expect(m.unit).to eq Measurement::Unit[:count]
110
+
111
+ m = subject.parse('3 ⅜')
112
+ expect(m.quantity).to eq 3.375
113
+ expect(m.unit).to eq Measurement::Unit[:count]
114
+
115
+ m = subject.parse('3⅜ dozen')
116
+ expect(m.quantity).to eq 3.375
117
+ expect(m.unit).to eq Measurement::Unit[:dozen]
118
+
119
+ m = subject.parse('3 ⅜ dozen')
120
+ expect(m.quantity).to eq 3.375
121
+ expect(m.unit).to eq Measurement::Unit[:dozen]
122
+
123
+ m = subject.parse('3⅜doz')
124
+ expect(m.quantity).to eq 3.375
125
+ expect(m.unit).to eq Measurement::Unit[:dozen]
126
+ end
127
+
94
128
  it 'parses decimals' do
95
129
  m = subject.parse('2.1')
96
- m.quantity.should eq 2.1
97
- m.unit.should eq subject::Unit[:count]
98
-
130
+ expect(m.quantity).to eq 2.1
131
+ expect(m.unit).to eq Measurement::Unit[:count]
132
+
99
133
  m = subject.parse('2.1 dozen')
100
- m.quantity.should eq 2.1
101
- m.unit.should eq subject::Unit[:dozen]
102
-
134
+ expect(m.quantity).to eq 2.1
135
+ expect(m.unit).to eq Measurement::Unit[:dozen]
136
+
103
137
  m = subject.parse('2.1doz')
104
- m.quantity.should eq 2.1
105
- m.unit.should eq subject::Unit[:dozen]
138
+ expect(m.quantity).to eq 2.1
139
+ expect(m.unit).to eq Measurement::Unit[:dozen]
106
140
  end
107
141
  end
108
-
142
+
109
143
  describe 'unit' do
110
144
  it 'converts when defined' do
111
- subject.parse('3 dozen').unit.should eq subject::Unit[:dozen]
145
+ expect(subject.parse('3 dozen').unit).to eq Measurement::Unit[:dozen]
112
146
  end
113
-
147
+
114
148
  it 'raises exception when undefined' do
115
- expect { subject.parse('3 finklebaums') }.to raise_error
149
+ expect { subject.parse('3 finklebaums') }.to raise_error(ArgumentError, "Invalid unit: 'finklebaums'")
116
150
  end
117
151
  end
118
152
  end
119
-
153
+
120
154
  describe '.define' do
121
155
  it 'delegates to Unit.define' do
122
- subject::Unit.should_receive(:define)
156
+ expect(Measurement::Unit).to receive(:define)
123
157
  subject.define(:something)
124
158
  end
125
159
  end
126
-
160
+
127
161
  describe '#convert_to' do
128
162
  let(:measurement) { subject.new(3) }
129
-
163
+
130
164
  it 'returns copy of self when target unit matches current unit' do
131
165
  result = measurement.convert_to(:count)
132
- result.should_not be measurement
133
- result.should eq measurement
166
+ expect(result).to_not be measurement
167
+ expect(result).to eq measurement
134
168
  end
135
-
169
+
136
170
  it 'returns target unit if it exists and is convertable' do
137
171
  result = measurement.convert_to(:dozen)
138
- result.quantity.should eq 0.25
139
- result.unit.should eq subject::Unit[:dozen]
172
+ expect(result.quantity).to eq 0.25
173
+ expect(result.unit).to eq Measurement::Unit[:dozen]
140
174
  end
141
-
175
+
142
176
  it 'raises exception if unit exists and is not convertable' do
143
- expect { measurement.convert_to(:inches) }.to raise_error
177
+ expect { measurement.convert_to(:inches) }.to raise_error(ArgumentError, "Invalid conversion: 'count' to 'in.'")
144
178
  end
145
-
179
+
146
180
  it 'raises exception if unit does not exist' do
147
- expect { measurement.convert_to(:finklebaum) }.to raise_error
181
+ expect { measurement.convert_to(:finklebaum) }.to raise_error(ArgumentError, "Invalid unit: 'finklebaum'")
148
182
  end
149
183
  end
150
-
184
+
151
185
  describe '#convert_to!' do
152
186
  let(:measurement) { subject.new(3) }
153
-
187
+
154
188
  it 'modifies the object' do
155
189
  measurement.convert_to!(:dozen)
156
- measurement.quantity.should eq 0.25
157
- measurement.unit.should eq subject::Unit[:dozen]
190
+ expect(measurement.quantity).to eq 0.25
191
+ expect(measurement.unit).to eq Measurement::Unit[:dozen]
158
192
  end
159
193
  end
160
-
194
+
161
195
  describe '#+' do
162
196
  let(:measurement) { subject.new(3) }
163
-
197
+
164
198
  it 'adds numeric values' do
165
199
  result = measurement + 4
166
- result.quantity.should eq 7
167
- result.unit.should eq measurement.unit
200
+ expect(result.quantity).to eq 7
201
+ expect(result.unit).to eq measurement.unit
168
202
  end
169
-
203
+
170
204
  it 'adds units of the same type' do
171
205
  other = subject.new(4)
172
- other.unit.should eq measurement.unit
173
-
206
+ expect(other.unit).to eq measurement.unit
207
+
174
208
  result = measurement + other
175
- result.quantity.should eq 7
176
- result.unit.should eq measurement.unit
209
+ expect(result.quantity).to eq 7
210
+ expect(result.unit).to eq measurement.unit
177
211
  end
178
-
212
+
179
213
  it 'adds units of a convertable type' do
180
214
  other = subject.new(2, :dozen)
181
- other.unit.should_not eq measurement.unit
182
-
215
+ expect(other.unit).to_not eq measurement.unit
216
+
183
217
  result = measurement + other
184
- result.quantity.should eq 27
185
- result.unit.should eq measurement.unit
218
+ expect(result.quantity).to eq 27
219
+ expect(result.unit).to eq measurement.unit
186
220
  end
187
-
221
+
188
222
  it 'raises exception for incompatible units' do
189
223
  other = subject.new(4, :inches)
190
- other.unit.should_not eq measurement.unit
191
- expect { measurement + other }.to raise_error
224
+ expect(other.unit).to_not eq measurement.unit
225
+ expect { measurement + other }.to raise_error(ArgumentError, "Invalid conversion: 'in.' to 'count'")
192
226
  end
193
227
  end
194
-
228
+
195
229
  describe '#-' do
196
230
  let(:measurement) { subject.new(3) }
197
-
231
+
198
232
  it 'subtracts numeric values' do
199
233
  result = measurement - 4
200
- result.quantity.should eq -1
201
- result.unit.should eq measurement.unit
234
+ expect(result.quantity).to eq(-1)
235
+ expect(result.unit).to eq measurement.unit
202
236
  end
203
-
237
+
204
238
  it 'subtracts units of the same type' do
205
239
  other = subject.new(4)
206
- other.unit.should eq measurement.unit
207
-
240
+ expect(other.unit).to eq measurement.unit
241
+
208
242
  result = measurement - other
209
- result.quantity.should eq -1
210
- result.unit.should eq measurement.unit
243
+ expect(result.quantity).to eq(-1)
244
+ expect(result.unit).to eq measurement.unit
211
245
  end
212
-
246
+
213
247
  it 'subtracts units of a convertable type' do
214
248
  other = subject.new(2, :dozen)
215
- other.unit.should_not eq measurement.unit
216
-
249
+ expect(other.unit).to_not eq measurement.unit
250
+
217
251
  result = measurement - other
218
- result.quantity.should eq -21
219
- result.unit.should eq measurement.unit
252
+ expect(result.quantity).to eq(-21)
253
+ expect(result.unit).to eq measurement.unit
220
254
  end
221
-
255
+
222
256
  it 'raises exception for incompatible units' do
223
257
  other = subject.new(4, :inches)
224
- other.unit.should_not eq measurement.unit
225
- expect { measurement - other }.to raise_error
258
+ expect(other.unit).to_not eq measurement.unit
259
+ expect { measurement - other }.to raise_error(ArgumentError, "Invalid conversion: 'in.' to 'count'")
226
260
  end
227
261
  end
228
-
262
+
229
263
  describe '#*' do
230
264
  let(:measurement) { subject.new(3) }
231
-
265
+
232
266
  it 'multiplies numeric values' do
233
267
  result = measurement * 4
234
- result.quantity.should eq 12
235
- result.unit.should eq measurement.unit
268
+ expect(result.quantity).to eq 12
269
+ expect(result.unit).to eq measurement.unit
236
270
  end
237
-
271
+
238
272
  it 'multiplies units of the same type' do
239
273
  other = subject.new(4)
240
- other.unit.should eq measurement.unit
241
-
274
+ expect(other.unit).to eq measurement.unit
275
+
242
276
  result = measurement * other
243
- result.quantity.should eq 12
244
- result.unit.should eq measurement.unit
277
+ expect(result.quantity).to eq 12
278
+ expect(result.unit).to eq measurement.unit
245
279
  end
246
-
280
+
247
281
  it 'multiplies units of a convertable type' do
248
282
  other = subject.new(2, :dozen)
249
- other.unit.should_not eq measurement.unit
250
-
283
+ expect(other.unit).to_not eq measurement.unit
284
+
251
285
  result = measurement * other
252
- result.quantity.should eq 72
253
- result.unit.should eq measurement.unit
286
+ expect(result.quantity).to eq 72
287
+ expect(result.unit).to eq measurement.unit
254
288
  end
255
-
289
+
256
290
  it 'raises exception for incompatible units' do
257
291
  other = subject.new(4, :inches)
258
- other.unit.should_not eq measurement.unit
259
- expect { measurement * other }.to raise_error
292
+ expect(other.unit).to_not eq measurement.unit
293
+ expect { measurement * other }.to raise_error(ArgumentError, "Invalid conversion: 'in.' to 'count'")
260
294
  end
261
295
  end
262
-
296
+
263
297
  describe '#/' do
264
298
  let(:measurement) { subject.new(12) }
265
-
299
+
266
300
  it 'divides numeric values' do
267
301
  result = measurement / 4
268
- result.quantity.should eq 3
269
- result.unit.should eq measurement.unit
302
+ expect(result.quantity).to eq 3
303
+ expect(result.unit).to eq measurement.unit
270
304
  end
271
-
305
+
272
306
  it 'divides units of the same type' do
273
307
  other = subject.new(4)
274
- other.unit.should eq measurement.unit
275
-
308
+ expect(other.unit).to eq measurement.unit
309
+
276
310
  result = measurement / other
277
- result.quantity.should eq 3
278
- result.unit.should eq measurement.unit
311
+ expect(result.quantity).to eq 3
312
+ expect(result.unit).to eq measurement.unit
279
313
  end
280
-
314
+
281
315
  it 'divides units of a convertable type' do
282
316
  other = subject.new(1, :dozen)
283
- other.unit.should_not eq measurement.unit
284
-
317
+ expect(other.unit).to_not eq measurement.unit
318
+
285
319
  result = measurement / other
286
- result.quantity.should eq 1
287
- result.unit.should eq measurement.unit
320
+ expect(result.quantity).to eq 1
321
+ expect(result.unit).to eq measurement.unit
288
322
  end
289
-
323
+
290
324
  it 'raises exception for incompatible units' do
291
325
  other = subject.new(4, :inches)
292
- other.unit.should_not eq measurement.unit
293
- expect { measurement / other }.to raise_error
326
+ expect(other.unit).to_not eq measurement.unit
327
+ expect { measurement / other }.to raise_error(ArgumentError, "Invalid conversion: 'in.' to 'count'")
294
328
  end
295
329
  end
296
-
330
+
297
331
  describe '#**' do
298
332
  let(:measurement) { subject.new(3) }
299
-
333
+
300
334
  it 'raises to the power of numeric values' do
301
- (measurement ** 3).quantity.should eq 27
335
+ expect((measurement ** 3).quantity).to eq 27
302
336
  end
303
-
337
+
304
338
  it 'raises exception for non-numeric values' do
305
- expect { measurement ** subject.new(3) }.to raise_error
339
+ expect { measurement ** subject.new(3) }.to raise_error(ArgumentError, 'Invalid arithmetic: 3 count ** 3 count')
306
340
  end
307
341
  end
308
-
342
+
309
343
  describe '#==' do
310
344
  let(:measurement) { subject.new(3) }
311
-
345
+
312
346
  it 'returns true for measurements with same quantity and unit' do
313
- (measurement == subject.new(3)).should be_true
347
+ expect(measurement == subject.new(3)).to be true
314
348
  end
315
-
349
+
316
350
  it 'returns false for measurements with same quantity and different unit' do
317
- (measurement == subject.new(3, :dozen)).should be_false
351
+ expect(measurement == subject.new(3, :dozen)).to be false
318
352
  end
319
-
353
+
320
354
  it 'returns false for measurements with same unit and different quantity' do
321
- (measurement == subject.new(4)).should be_false
355
+ expect(measurement == subject.new(4)).to be false
322
356
  end
323
-
357
+
324
358
  it 'returns false for non-measurement objects' do
325
- (measurement == 3).should be_false
359
+ expect(measurement == 3).to be false
326
360
  end
327
361
  end
328
-
362
+
363
+ describe '#>' do
364
+ let(:measurement) { subject.new(3) }
365
+
366
+ it 'raises ArgumentError for non-measurement objects' do
367
+ expect { measurement > 2 }.to raise_error(ArgumentError)
368
+ end
369
+
370
+ it 'returns false for measurements for different unit' do
371
+ expect { measurement > subject.new(2, :dozen) }.to raise_error(ArgumentError)
372
+ end
373
+
374
+ it 'returns true for measurements with same unit and larger quantity' do
375
+ expect(measurement > subject.new(2)).to be true
376
+ end
377
+
378
+ it 'returns false for measurements with same unit and smaller quantity' do
379
+ expect(measurement > subject.new(4)).to be false
380
+ end
381
+ end
382
+
383
+ describe '#<' do
384
+ let(:measurement) { subject.new(3) }
385
+
386
+ it 'raises ArgumentError for non-measurement objects' do
387
+ expect { measurement < 4 }.to raise_error(ArgumentError)
388
+ end
389
+
390
+ it 'returns false for measurements for different unit' do
391
+ expect { measurement < subject.new(4, :dozen) }.to raise_error(ArgumentError)
392
+ end
393
+
394
+ it 'returns true for measurements with same unit and smaller quantity' do
395
+ expect(measurement < subject.new(4)).to be true
396
+ end
397
+
398
+ it 'returns false for measurements with same unit and larger quantity' do
399
+ expect(measurement < subject.new(2)).to be false
400
+ end
401
+ end
402
+
329
403
  describe '#to_s' do
330
404
  it 'returns the quantity and unit' do
331
- subject.new(3.5).to_s.should eq '3.5 count'
332
- subject.new(2, :dozen).to_s.should eq '2 doz'
405
+ expect(subject.new(3.5).to_s).to eq '3.5 count'
406
+ expect(subject.new(2, :dozen).to_s).to eq '2 doz'
333
407
  end
334
408
  end
335
-
409
+
336
410
  describe '#inspect' do
337
411
  it 'returns the quantity and unit' do
338
- subject.new(3.5).inspect.should eq '3.5 count'
339
- subject.new(2, :dozen).inspect.should eq '2 doz'
412
+ expect(subject.new(3.5).inspect).to eq '3.5 count'
413
+ expect(subject.new(2, :dozen).inspect).to eq '2 doz'
340
414
  end
341
415
  end
342
416
  end