unitwise-193 1.0.4

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +21 -0
  5. data/CHANGELOG.md +44 -0
  6. data/Gemfile +10 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +297 -0
  9. data/Rakefile +21 -0
  10. data/data/base_unit.yaml +43 -0
  11. data/data/derived_unit.yaml +3542 -0
  12. data/data/prefix.yaml +121 -0
  13. data/lib/unitwise.rb +70 -0
  14. data/lib/unitwise/atom.rb +121 -0
  15. data/lib/unitwise/base.rb +58 -0
  16. data/lib/unitwise/compatible.rb +60 -0
  17. data/lib/unitwise/errors.rb +7 -0
  18. data/lib/unitwise/expression.rb +35 -0
  19. data/lib/unitwise/expression/composer.rb +41 -0
  20. data/lib/unitwise/expression/decomposer.rb +68 -0
  21. data/lib/unitwise/expression/matcher.rb +47 -0
  22. data/lib/unitwise/expression/parser.rb +58 -0
  23. data/lib/unitwise/expression/transformer.rb +37 -0
  24. data/lib/unitwise/ext.rb +2 -0
  25. data/lib/unitwise/ext/numeric.rb +45 -0
  26. data/lib/unitwise/functional.rb +117 -0
  27. data/lib/unitwise/measurement.rb +198 -0
  28. data/lib/unitwise/prefix.rb +24 -0
  29. data/lib/unitwise/scale.rb +139 -0
  30. data/lib/unitwise/search.rb +46 -0
  31. data/lib/unitwise/standard.rb +29 -0
  32. data/lib/unitwise/standard/base.rb +73 -0
  33. data/lib/unitwise/standard/base_unit.rb +21 -0
  34. data/lib/unitwise/standard/derived_unit.rb +49 -0
  35. data/lib/unitwise/standard/extras.rb +17 -0
  36. data/lib/unitwise/standard/function.rb +35 -0
  37. data/lib/unitwise/standard/prefix.rb +17 -0
  38. data/lib/unitwise/standard/scale.rb +25 -0
  39. data/lib/unitwise/term.rb +142 -0
  40. data/lib/unitwise/unit.rb +181 -0
  41. data/lib/unitwise/version.rb +3 -0
  42. data/test/support/scale_tests.rb +117 -0
  43. data/test/test_helper.rb +19 -0
  44. data/test/unitwise/atom_test.rb +129 -0
  45. data/test/unitwise/base_test.rb +6 -0
  46. data/test/unitwise/expression/decomposer_test.rb +45 -0
  47. data/test/unitwise/expression/matcher_test.rb +42 -0
  48. data/test/unitwise/expression/parser_test.rb +109 -0
  49. data/test/unitwise/ext/numeric_test.rb +54 -0
  50. data/test/unitwise/functional_test.rb +17 -0
  51. data/test/unitwise/measurement_test.rb +233 -0
  52. data/test/unitwise/prefix_test.rb +25 -0
  53. data/test/unitwise/scale_test.rb +7 -0
  54. data/test/unitwise/search_test.rb +18 -0
  55. data/test/unitwise/term_test.rb +55 -0
  56. data/test/unitwise/unit_test.rb +87 -0
  57. data/test/unitwise_test.rb +35 -0
  58. data/unitwise.gemspec +33 -0
  59. metadata +246 -0
@@ -0,0 +1,19 @@
1
+ if RUBY_VERSION > '1.8.7'
2
+ require 'coveralls'
3
+ Coveralls.wear!
4
+ end
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest/pride'
8
+
9
+ require 'unitwise'
10
+
11
+ module Minitest::Assertions
12
+ def assert_almost_equal(expected, actual)
13
+ message = "Expected #{actual} to be almost equal to #{expected}"
14
+ range = 0.00001
15
+ assert expected + range > actual && expected - range < actual, message
16
+ end
17
+ end
18
+
19
+ Numeric.infect_an_assertion :assert_almost_equal, :must_almost_equal
@@ -0,0 +1,129 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Atom do
4
+ subject { Unitwise::Atom }
5
+ describe "::data" do
6
+ it "must have data" do
7
+ subject.data.must_be_instance_of Array
8
+ subject.data.count.must_be :>, 0
9
+ end
10
+ end
11
+
12
+ describe "::all" do
13
+ it "must be an Array of instances" do
14
+ subject.all.must_be_instance_of Array
15
+ subject.all.first.must_be_instance_of Unitwise::Atom
16
+ end
17
+ end
18
+
19
+ describe "::find" do
20
+ it "must find atoms" do
21
+ subject.find("m").must_be_instance_of Unitwise::Atom
22
+ subject.find("V").must_be_instance_of Unitwise::Atom
23
+ end
24
+ end
25
+
26
+ let(:second) { Unitwise::Atom.find("s") }
27
+ let(:yard) { Unitwise::Atom.find("[yd_i]")}
28
+ let(:pi) { Unitwise::Atom.find("[pi]")}
29
+ let(:celsius) { Unitwise::Atom.find("Cel")}
30
+ let(:pfu) { Unitwise::Atom.find("[PFU]")}
31
+ let(:joule) { Unitwise::Atom.find("J")}
32
+ describe "#scale" do
33
+ it "must be nil for base atoms" do
34
+ second.scale.must_equal nil
35
+ end
36
+ it "sould be a Scale object for derived atoms" do
37
+ yard.scale.must_be_instance_of Unitwise::Scale
38
+ end
39
+ it "must be a FunctionalScale object for special atoms" do
40
+ celsius.scale.must_be_instance_of Unitwise::Functional
41
+ end
42
+ end
43
+
44
+ describe "#base?" do
45
+ it "must be true for base atoms" do
46
+ second.base?.must_equal true
47
+ end
48
+ it "must be false for derived atoms" do
49
+ yard.base?.must_equal false
50
+ pi.base?.must_equal false
51
+ end
52
+ end
53
+
54
+ describe "#derived?" do
55
+ it "must be false for base atoms" do
56
+ second.derived?.must_equal false
57
+ end
58
+ it "must be true for derived atoms" do
59
+ yard.derived?.must_equal true
60
+ celsius.derived?.must_equal true
61
+ end
62
+ end
63
+
64
+ describe "#metric?" do
65
+ it "must be true for base atoms" do
66
+ second.metric?.must_equal true
67
+ end
68
+ it "must be false for english atoms" do
69
+ yard.metric?.must_equal false
70
+ end
71
+ end
72
+
73
+ describe "#special?" do
74
+ it "must be true for special atoms" do
75
+ celsius.special?.must_equal true
76
+ end
77
+ it "must be false for non-special atoms" do
78
+ second.special?.must_equal false
79
+ end
80
+ end
81
+
82
+ describe "#arbitrary?" do
83
+ it "must be true for arbitrary atoms" do
84
+ pfu.arbitrary?.must_equal true
85
+ end
86
+ it "must be false for non-arbitrary atoms" do
87
+ yard.arbitrary?.must_equal false
88
+ celsius.arbitrary?.must_equal false
89
+ end
90
+ end
91
+
92
+ describe "#terminal?" do
93
+ it "must be true for atoms without a valid measurement atom" do
94
+ second.terminal?.must_equal true
95
+ pi.terminal?.must_equal true
96
+ end
97
+ it "must be false for child atoms" do
98
+ yard.terminal?.must_equal false
99
+ end
100
+ end
101
+
102
+ describe "#scalar" do
103
+ it "must return scalar relative to terminal atom" do
104
+ second.scalar.must_equal 1
105
+ yard.scalar.must_almost_equal 0.9144
106
+ pi.scalar.must_almost_equal 3.141592653589793
107
+ end
108
+ end
109
+
110
+ describe "#dim" do
111
+ it "must return the dim" do
112
+ second.dim.must_equal 'T'
113
+ yard.dim.must_equal 'L'
114
+ joule.dim.must_equal 'L2.M.T-2'
115
+ end
116
+ end
117
+
118
+ describe "#measurement=" do
119
+ it "must create a new measurement object and set attributes" do
120
+ skip("need to figure out mocking and stubbing with minitest")
121
+ end
122
+ end
123
+
124
+ describe "#frozen?" do
125
+ it "should be frozen" do
126
+ second.frozen?.must_equal true
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,6 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Base do
4
+
5
+
6
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Expression::Decomposer do
4
+ subject { Unitwise::Expression::Decomposer }
5
+
6
+ describe "#terms" do
7
+ it "should accept codes" do
8
+ fts = subject.new("[ft_i]/s").terms
9
+ fts.count.must_equal 2
10
+ end
11
+ it "should accept names" do
12
+ kms = subject.new("kilometer/second").terms
13
+ kms.count.must_equal 2
14
+ end
15
+ it "should accept spaced names" do
16
+ ncg = subject.new("Newtonian constant of gravitation").terms
17
+ ncg.count.must_equal 1
18
+ end
19
+ it "should accept parameterized names" do
20
+ pc = subject.new("planck_constant").terms
21
+ pc.count.must_equal 1
22
+ end
23
+ it "should accept symbols" do
24
+ saff = subject.new("<i>g<sub>n</sub></i>").terms
25
+ saff.count.must_equal 1
26
+ end
27
+ it "should accept complex units" do
28
+ complex = subject.new("(mg.(km/s)3/J)2.Pa").terms
29
+ complex.count.must_equal 5
30
+ end
31
+ it "should accept more complex units" do
32
+ complex = subject.new("4.1(mm/2s3)4.7.3J-2").terms
33
+ complex.count.must_equal 3
34
+ end
35
+ it "should accept weird units" do
36
+ frequency = subject.new("/s").terms
37
+ frequency.count.must_equal 1
38
+ end
39
+ it "should accept units with a factor and unit" do
40
+ oddity = subject.new("2ms2").terms
41
+ oddity.count.must_equal 1
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Expression::Matcher do
4
+ describe "::atom(:codes)" do
5
+ subject { Unitwise::Expression::Matcher.atom(:primary_code)}
6
+ it "must be an Alternative list" do
7
+ subject.must_be_instance_of Parslet::Atoms::Alternative
8
+ end
9
+ it "must parse [in_i]" do
10
+ subject.parse("[in_i]").must_equal("[in_i]")
11
+ end
12
+ end
13
+ describe "::metric_atom(:names)" do
14
+ subject { Unitwise::Expression::Matcher.metric_atom(:names)}
15
+ it "must be an Alternative list of names" do
16
+ subject.must_be_instance_of Parslet::Atoms::Alternative
17
+ end
18
+ it "must parse 'Joule'" do
19
+ subject.parse('Joule').must_equal('Joule')
20
+ end
21
+ end
22
+
23
+ describe "::atom(:slugs)" do
24
+ subject { Unitwise::Expression::Matcher.atom(:slugs)}
25
+ it "must be an Alternative list of slugs" do
26
+ subject.must_be_instance_of Parslet::Atoms::Alternative
27
+ end
28
+ it "must match 'georgian_year'" do
29
+ subject.parse("mean_gregorian_year").must_equal("mean_gregorian_year")
30
+ end
31
+ end
32
+
33
+ describe "::prefix(:symbol)" do
34
+ subject { Unitwise::Expression::Matcher.prefix(:symbol)}
35
+ it "must be an Alternative list of symbols" do
36
+ subject.must_be_instance_of Parslet::Atoms::Alternative
37
+ end
38
+ it "must parse 'h'" do
39
+ subject.parse('h').must_equal('h')
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,109 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Expression::Parser do
4
+ subject { Unitwise::Expression::Parser.new}
5
+ describe '#metric_atom' do
6
+ it "must match 'N'" do
7
+ subject.metric_atom.parse('N')[:atom_code].must_equal('N')
8
+ end
9
+ end
10
+
11
+ describe '#atom' do
12
+ it "must match '[in_i]'" do
13
+ subject.atom.parse('[in_i]')[:atom_code].must_equal('[in_i]')
14
+ end
15
+ end
16
+
17
+ describe '#prefix' do
18
+ it "must match 'k'" do
19
+ subject.prefix.parse('k')[:prefix_code].must_equal('k')
20
+ end
21
+ end
22
+
23
+ describe '#annotation' do
24
+ it "must match '{foobar}'" do
25
+ subject.annotation.parse('{foobar}')[:annotation].must_equal('foobar')
26
+ end
27
+ end
28
+
29
+ describe "#factor" do
30
+ it "must match positives and fixnums" do
31
+ subject.factor.parse('3.2')[:factor].must_equal(:fixnum => '3.2')
32
+ end
33
+ it "must match negatives and integers" do
34
+ subject.factor.parse('-5')[:factor].must_equal(:integer => '-5')
35
+ end
36
+ end
37
+
38
+ describe "#exponent" do
39
+ it "must match positives integers" do
40
+ subject.exponent.parse('4')[:exponent].must_equal(:integer => '4')
41
+ end
42
+ it "must match negative integers" do
43
+ subject.exponent.parse('-5')[:exponent].must_equal(:integer => '-5')
44
+ end
45
+ end
46
+
47
+ describe "term" do
48
+ it "must match basic atoms" do
49
+ subject.term.parse('[in_i]')[:term][:atom][:atom_code].must_equal('[in_i]')
50
+ end
51
+ it "must match prefixed atoms" do
52
+ match = subject.term.parse('ks')[:term]
53
+ match[:atom][:atom_code].must_equal('s')
54
+ match[:prefix][:prefix_code].must_equal('k')
55
+ end
56
+ it "must match exponential atoms" do
57
+ match = subject.term.parse('cm3')[:term]
58
+ match[:atom][:atom_code].must_equal 'm'
59
+ match[:prefix][:prefix_code].must_equal 'c'
60
+ match[:exponent][:integer].must_equal '3'
61
+ end
62
+ it "must match factors" do
63
+ subject.term.parse('3.2')[:term][:factor][:fixnum].must_equal '3.2'
64
+ end
65
+ it "must match annotations" do
66
+ match = subject.term.parse('N{Normal}')[:term]
67
+ match[:atom][:atom_code].must_equal 'N'
68
+ match[:annotation].must_equal 'Normal'
69
+ end
70
+ end
71
+
72
+ describe '#group' do
73
+ it "must match parentheses with a term" do
74
+ match = subject.group.parse('(s2)')[:group][:nested][:left][:term]
75
+ match[:atom][:atom_code].must_equal 's'
76
+ match[:exponent][:integer].must_equal '2'
77
+ end
78
+ it "must match nested groups" do
79
+ match = subject.group.parse('((kg))')[:group][:nested][:left][:group][:nested][:left][:term]
80
+ match[:atom][:atom_code].must_equal 'g'
81
+ match[:prefix][:prefix_code].must_equal 'k'
82
+ end
83
+ it "must pass exponents down" do
84
+ match = subject.group.parse('([in_i])3')[:group]
85
+ match[:exponent][:integer].must_equal '3'
86
+ match[:nested][:left][:term][:atom][:atom_code].must_equal '[in_i]'
87
+ end
88
+ end
89
+
90
+ describe "#expression" do
91
+ it "must match left only" do
92
+ match = subject.expression.parse('m')
93
+ match[:left][:term][:atom][:atom_code].must_equal("m")
94
+ end
95
+ it "must match left + right + operator" do
96
+ match = subject.expression.parse('m.s')
97
+ match[:left][:term][:atom][:atom_code].must_equal("m")
98
+ match[:operator].must_equal('.')
99
+ match[:right][:left][:term][:atom][:atom_code].must_equal('s')
100
+ end
101
+ it "must match operator + right" do
102
+ match = subject.expression.parse("/s")
103
+ match[:operator].must_equal('/')
104
+ match[:right][:left][:term][:atom][:atom_code].must_equal('s')
105
+ end
106
+ end
107
+
108
+
109
+ end
@@ -0,0 +1,54 @@
1
+ require 'test_helper'
2
+ require 'unitwise/ext'
3
+ describe Numeric do
4
+ describe "#convert" do
5
+ it "must work for Integer" do
6
+ measurement = 22.convert_to("kg")
7
+ measurement.must_be_instance_of(Unitwise::Measurement)
8
+ measurement.value.must_equal 22
9
+ end
10
+ it "must work for Fixnum" do
11
+ measurement = 24.25.convert_to("[ft_i]")
12
+ measurement.must_be_instance_of(Unitwise::Measurement)
13
+ measurement.value.must_equal 24.25
14
+ end
15
+ it "must work for Float" do
16
+ measurement = (22.0/7).convert_to("[mi_i]")
17
+ measurement.must_be_instance_of(Unitwise::Measurement)
18
+ measurement.value.must_equal 3.142857142857143
19
+ end
20
+ it "must work for Rational" do
21
+ measurement = Rational(22/7).convert_to("N/m2")
22
+ measurement.must_be_instance_of(Unitwise::Measurement)
23
+ measurement.value.must_equal Rational(22/7)
24
+ end
25
+ end
26
+
27
+ describe "#method_missing" do
28
+ it "must match 'mm'" do
29
+ mm = 2.5.mm
30
+ mm.must_be_instance_of(Unitwise::Measurement)
31
+ mm.value.must_equal 2.5
32
+ 1.0.respond_to?(:mm).must_equal true
33
+ 3.respond_to?(:to_mm).must_equal true
34
+ end
35
+ it "must match 'to_mm'" do
36
+ mm = 2.5.to_mm
37
+ mm.must_be_instance_of(Unitwise::Measurement)
38
+ mm.value.must_equal 2.5
39
+ 4.0.methods.grep(/mm/).count.must_equal 2
40
+ 1.methods.grep(/mm/).count.must_equal 2
41
+ end
42
+
43
+ it "must not match 'foo'" do
44
+ lambda { 1.foo }.must_raise NoMethodError
45
+ end
46
+
47
+ it "must not match 'to_foo'" do
48
+ lambda { 1.to_foo }.must_raise NoMethodError
49
+ end
50
+
51
+ end
52
+
53
+
54
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ describe Unitwise::Functional do
4
+ subject { Unitwise::Functional }
5
+ %w{cel degf hpX hpC tan100 ph ld ln lg 2lg}.each do |function|
6
+ describe function do
7
+ it 'should convert back and forth' do
8
+ number = rand(1000) / 1000.0
9
+ there = subject.send "to_#{function}", number
10
+ back_again = subject.send "from_#{function}", there
11
+ rounded_result = (back_again * 1000).round / 1000.0
12
+ rounded_result.must_equal number
13
+ end
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,233 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+ require 'support/scale_tests'
4
+
5
+ describe Unitwise::Measurement do
6
+ let(:described_class) { Unitwise::Measurement }
7
+ include ScaleTests
8
+
9
+ describe "#new" do
10
+ it "should raise an error for unknown units" do
11
+ lambda { Unitwise::Measurement.new(1,"funkitron") }.must_raise(Unitwise::ExpressionError)
12
+ end
13
+ end
14
+
15
+ describe "#convert_to" do
16
+ it "must convert to a similar unit code" do
17
+ mph.convert_to('km/h').value.must_almost_equal(96.56063)
18
+ end
19
+ it "must raise an error if the units aren't similar" do
20
+ lambda { mph.convert_to('N') }.must_raise Unitwise::ConversionError
21
+ end
22
+ it "must convert special units to their base units" do
23
+ cel.convert_to('K').value.must_equal 295.15
24
+ end
25
+ it "must convert base units to special units" do
26
+ k.convert_to('Cel').value.must_equal 100
27
+ end
28
+ it "must convert special units to special units" do
29
+ f.convert_to('Cel').value.must_almost_equal 37
30
+ end
31
+ it "must convert special units to non-special units" do
32
+ cel.convert_to("[degR]").value.must_almost_equal(531.27)
33
+ end
34
+ it "must convert derived units to special units" do
35
+ r.convert_to("Cel").value.must_almost_equal(0)
36
+ end
37
+ it "must convert to a unit of another measurement" do
38
+ mph.convert_to(kmh).value.must_almost_equal(96.56064)
39
+ end
40
+ end
41
+
42
+ describe "#*" do
43
+ it "must multiply by scalars" do
44
+ mult = mph * 4
45
+ mult.value.must_equal 240
46
+ mult.unit.must_equal Unitwise::Unit.new("[mi_i]/h")
47
+ end
48
+ it "must multiply similar units" do
49
+ mult = mph * kmh
50
+ mult.value.must_almost_equal 3728.22715342
51
+ mult.unit.must_equal Unitwise::Unit.new("([mi_i]/h).([mi_i]/h)")
52
+ end
53
+ it "must multiply unsimilar units" do
54
+ mult = mph * mile
55
+ mult.value.must_equal 180
56
+ mult.unit.must_equal Unitwise::Unit.new("[mi_i]2/h")
57
+ end
58
+ it "must multiply canceling units" do
59
+ mult = mph * hpm
60
+ mult.value.must_equal 360
61
+ mult.unit.to_s.must_equal "1"
62
+ end
63
+ end
64
+
65
+ describe "#/" do
66
+ it "must divide by scalars" do
67
+ div = kmh / 4
68
+ div.value.must_equal 25
69
+ div.unit.must_equal kmh.unit
70
+ end
71
+ it "must divide by the value of similar units" do
72
+ div = kmh / mph
73
+ div.value.must_almost_equal 1.03561865
74
+ div.unit.to_s.must_equal '1'
75
+ end
76
+ it "must divide dissimilar units" do
77
+ div = mph / hpm
78
+ div.value.must_equal 10
79
+ div.unit.to_s.must_equal "[mi_i]2/h2"
80
+ end
81
+ end
82
+
83
+ describe "#+" do
84
+ it "must add values when units are similar" do
85
+ added = mph + kmh
86
+ added.value.must_almost_equal 122.13711922
87
+ added.unit.must_equal mph.unit
88
+ end
89
+ it "must raise an error when units are not similar" do
90
+ assert_raises(TypeError) { mph + hpm}
91
+ end
92
+ end
93
+
94
+ describe "#-" do
95
+ it "must add values when units are similar" do
96
+ added = mph - kmh
97
+ added.value.must_almost_equal(-2.1371192)
98
+ added.unit.must_equal mph.unit
99
+ end
100
+ it "must raise an error when units are not similar" do
101
+ assert_raises(TypeError) { mph - hpm}
102
+ end
103
+ end
104
+
105
+ describe "#**" do
106
+ it "must raise to a power" do
107
+ exp = mile ** 3
108
+ exp.value.must_equal 27
109
+ exp.unit.to_s.must_equal "[mi_i]3"
110
+ end
111
+ it "must raise to a negative power" do
112
+ exp = mile ** -3
113
+ exp.value.must_equal 0.037037037037037035
114
+ exp.unit.to_s.must_equal "1/[mi_i]3"
115
+ end
116
+ it "must not raise to a weird power" do
117
+ lambda { mile ** 'weird' }.must_raise TypeError
118
+ end
119
+ end
120
+
121
+ describe "#coerce" do
122
+ let(:meter) { Unitwise::Measurement.new(1, 'm') }
123
+ it "must coerce numerics" do
124
+ (5 * meter).must_equal Unitwise::Measurement.new(5, 'm')
125
+ end
126
+ it "should raise an error for other crap" do
127
+ lambda { meter.coerce("foo") }.must_raise TypeError
128
+ end
129
+ end
130
+
131
+ describe "equality" do
132
+ let(:m) { Unitwise::Measurement.new(1,'m') }
133
+ let(:feet) { Unitwise::Measurement.new(20, 'foot') }
134
+ let(:mm) { Unitwise::Measurement.new(1000,'mm') }
135
+ let(:foot) { Unitwise::Measurement.new(1,'foot') }
136
+ let(:g) { Unitwise::Measurement.new(1,'gram') }
137
+ it "should be ==" do
138
+ assert m == m
139
+ assert m == mm
140
+ refute m == foot
141
+ refute m == g
142
+ end
143
+ it "should be ===" do
144
+ assert m == m
145
+ assert m === mm
146
+ refute m === foot
147
+ refute m == g
148
+ end
149
+ it "should be equal?" do
150
+ assert m.equal?(m)
151
+ refute m.equal?(mm)
152
+ refute m.equal?(foot)
153
+ refute m.equal?(g)
154
+ end
155
+ it "should be eql?" do
156
+ assert m.eql?(m)
157
+ refute m.equal?(mm)
158
+ refute m.equal?(foot)
159
+ refute m.equal?(g)
160
+ end
161
+ end
162
+
163
+ describe "#method_missing" do
164
+ let(:meter) { Unitwise::Measurement.new(1, 'm')}
165
+ it "must convert 'to_mm'" do
166
+ convert = meter.to_mm
167
+ convert.must_be_instance_of Unitwise::Measurement
168
+ convert.value.must_equal 1000
169
+ end
170
+
171
+ it "must convert 'to_foot'" do
172
+ convert = meter.to_foot
173
+ convert.must_be_instance_of Unitwise::Measurement
174
+ convert.value.must_almost_equal 3.280839895
175
+ end
176
+
177
+ it "must not convert 'foo'" do
178
+ lambda { meter.foo }.must_raise NoMethodError
179
+ end
180
+
181
+ it "must not convert 'to_foo'" do
182
+ lambda { meter.to_foo }.must_raise NoMethodError
183
+ end
184
+
185
+ end
186
+
187
+ describe "#round" do
188
+ it "must round Floats to Integers" do
189
+ result = Unitwise::Measurement.new(98.6, "[degF]").round
190
+ result.value.must_equal(99)
191
+ result.value.must_be_kind_of(Integer)
192
+ end
193
+ it "must round Floats to Floats" do
194
+ if RUBY_VERSION > '1.8.7'
195
+ result = Unitwise::Measurement.new(17.625, "J").round(2)
196
+ result.value.must_equal(17.63)
197
+ result.value.must_be_kind_of(Float)
198
+ end
199
+ end
200
+ end
201
+ describe "#to_f" do
202
+ it "must convert to a float" do
203
+ f.to_f.must_be_kind_of(Float)
204
+ end
205
+ end
206
+
207
+ describe "#to_i" do
208
+ it "must convert to an integer" do
209
+ k.to_i.must_be_kind_of(Integer)
210
+ end
211
+ end
212
+
213
+ describe "#to_r" do
214
+ it "must convert to a rational" do
215
+ cel.to_r.must_be_kind_of(Rational)
216
+ end
217
+ end
218
+
219
+ describe "#to_s" do
220
+ it "should include the simplified value and use the mode it was created with" do
221
+ foot = described_class.new(7.00, "foot")
222
+ foot.to_s.must_equal "7 foot"
223
+ meter = described_class.new(BigDecimal("3.142"), "m")
224
+ meter.to_s.must_equal("3.142 m")
225
+ end
226
+ it "should accept a mode and print that mode string" do
227
+ temp = described_class.new(25, "degree Celsius")
228
+ temp.to_s(:primary_code).must_equal("25 Cel")
229
+ temp.to_s(:symbol).must_equal("25 °C")
230
+ end
231
+ end
232
+
233
+ end