unitwise-193 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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