measured 2.0.0 → 2.8.2
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 +5 -5
- data/.github/workflows/ci.yml +31 -0
- data/CHANGELOG.md +60 -0
- data/README.md +68 -10
- data/Rakefile +22 -1
- data/cache/.keep +0 -0
- data/cache/length.json +2553 -0
- data/cache/volume.json +4695 -0
- data/cache/weight.json +3195 -0
- data/dev.yml +2 -6
- data/gemfiles/{activesupport-4.2.gemfile → activesupport-5.2.gemfile} +1 -1
- data/gemfiles/activesupport-6.0.gemfile +5 -0
- data/gemfiles/activesupport-6.1.gemfile +5 -0
- data/lib/measured/arithmetic.rb +10 -0
- data/lib/measured/base.rb +13 -6
- data/lib/measured/cache/json.rb +55 -0
- data/lib/measured/cache/json_writer.rb +9 -0
- data/lib/measured/cache/null.rb +16 -0
- data/lib/measured/conversion_table_builder.rb +110 -0
- data/lib/measured/cycle_detected.rb +11 -0
- data/lib/measured/measurable.rb +28 -21
- data/lib/measured/missing_conversion_path.rb +12 -0
- data/lib/measured/parser.rb +2 -1
- data/lib/measured/unit.rb +17 -27
- data/lib/measured/unit_already_added.rb +11 -0
- data/lib/measured/unit_error.rb +4 -0
- data/lib/measured/unit_system.rb +26 -21
- data/lib/measured/unit_system_builder.rb +46 -2
- data/lib/measured/units/length.rb +6 -3
- data/lib/measured/units/volume.rb +20 -0
- data/lib/measured/units/weight.rb +10 -2
- data/lib/measured/version.rb +2 -1
- data/lib/measured.rb +2 -0
- data/measured.gemspec +13 -5
- data/test/arithmetic_test.rb +36 -0
- data/test/cache/json_test.rb +43 -0
- data/test/cache/json_writer_test.rb +23 -0
- data/test/cache/null_test.rb +20 -0
- data/test/cache_consistency_test.rb +19 -0
- data/test/conversion_table_builder_test.rb +147 -0
- data/test/measurable_test.rb +28 -13
- data/test/parser_test.rb +1 -0
- data/test/support/always_true_cache.rb +14 -0
- data/test/support/fake_system.rb +1 -0
- data/test/support/subclasses.rb +7 -0
- data/test/test_helper.rb +5 -3
- data/test/unit_error_test.rb +1 -0
- data/test/unit_system_builder_test.rb +120 -2
- data/test/unit_system_test.rb +15 -0
- data/test/unit_test.rb +14 -5
- data/test/units/length_test.rb +123 -10
- data/test/units/volume_test.rb +497 -0
- data/test/units/weight_test.rb +290 -5
- metadata +49 -18
- data/.travis.yml +0 -17
- data/lib/measured/conversion_table.rb +0 -65
- data/test/conversion_table_test.rb +0 -98
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
Measured::Volume = Measured.build do
|
|
3
|
+
si_unit :l, aliases: [:liter, :litre, :liters, :litres]
|
|
4
|
+
|
|
5
|
+
unit :m3, value: "1000 l", aliases: [:cubic_meter, :cubic_metre, :cubic_meters, :cubic_metres]
|
|
6
|
+
unit :cm3, value: "0.001 l", aliases: [:cubic_centimeter, :cubic_centimetre, :cubic_centimeters, :cubic_centimetres]
|
|
7
|
+
unit :mm3, value: "0.000001 l", aliases: [:cubic_millimeter, :cubic_millimetre, :cubic_millimeters, :cubic_millimetres]
|
|
8
|
+
unit :in3, value: "0.016387064 l", aliases: [:cubic_inch, :cubic_inches]
|
|
9
|
+
unit :ft3, value: "1728 in3", aliases: [:cubic_foot, :cubic_feet]
|
|
10
|
+
unit :gal, value: "4.54609 l", aliases: [:imp_gal, :imperial_gallon, :imp_gals, :imperial_gallons]
|
|
11
|
+
unit :us_gal, value: "231 in3", aliases: [:us_gallon, :us_gals, :us_gallons]
|
|
12
|
+
unit :qt, value: "0.25 gal", aliases: [:imp_qt, :imperial_quart, :imp_qts, :imperial_quarts]
|
|
13
|
+
unit :us_qt, value: "0.25 us_gal", aliases: [:us_quart, :us_quarts]
|
|
14
|
+
unit :pt, value: "0.125 gal", aliases: [:imp_pt, :imperial_pint, :imp_pts, :imperial_pints]
|
|
15
|
+
unit :us_pt, value: "0.125 us_gal", aliases: [:us_pint, :us_pints]
|
|
16
|
+
unit :oz, value: "0.00625 gal", aliases: [:fl_oz, :imp_fl_oz, :imperial_fluid_ounce, :imperial_fluid_ounces]
|
|
17
|
+
unit :us_oz, value: "0.0078125 us_gal", aliases: [:us_fl_oz, :us_fluid_ounce, :us_fluid_ounces]
|
|
18
|
+
|
|
19
|
+
cache Measured::Cache::Json, "volume.json"
|
|
20
|
+
end
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
Measured::Weight = Measured.build do
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
si_unit :g, aliases: [:gram, :grams]
|
|
4
|
+
|
|
5
|
+
unit :t, value: "1000 kg", aliases: [:metric_ton, :metric_tons]
|
|
6
|
+
unit :slug, value: "14.593903 kg", aliases: [:slugs]
|
|
7
|
+
unit :N, value: "0.10197162129779283 kg", aliases: [:newtons, :newton]
|
|
8
|
+
unit :long_ton, value: "2240 lb", aliases: [:long_tons, :weight_ton, :weight_tons, 'W/T', :imperial_ton, :imperial_tons, :displacement_ton, :displacement_tons]
|
|
9
|
+
unit :short_ton, value: "2000 lb", aliases: [:short_tons]
|
|
4
10
|
unit :lb, value: "0.45359237 kg", aliases: [:lbs, :pound, :pounds]
|
|
5
11
|
unit :oz, value: "1/16 lb", aliases: [:ounce, :ounces]
|
|
12
|
+
|
|
13
|
+
cache Measured::Cache::Json, "weight.json"
|
|
6
14
|
end
|
data/lib/measured/version.rb
CHANGED
data/lib/measured.rb
CHANGED
data/measured.gemspec
CHANGED
|
@@ -6,23 +6,31 @@ require 'measured/version'
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "measured"
|
|
8
8
|
spec.version = Measured::VERSION
|
|
9
|
-
spec.authors = ["Kevin McPhillips"]
|
|
10
|
-
spec.email = ["
|
|
9
|
+
spec.authors = ["Kevin McPhillips", "Jason Gedge", "Javier Honduvilla Coto"]
|
|
10
|
+
spec.email = ["gems@shopify.com"]
|
|
11
11
|
spec.summary = %q{Encapsulate measurements with their units in Ruby}
|
|
12
|
-
spec.description = %q{Wrapper objects which encapsulate
|
|
12
|
+
spec.description = %q{Wrapper objects which encapsulate measurements and their associated units in Ruby.}
|
|
13
13
|
spec.homepage = "https://github.com/Shopify/measured"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
|
|
16
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
|
17
|
+
# delete this section to allow pushing this gem to any host.
|
|
18
|
+
if spec.respond_to?(:metadata)
|
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
|
20
|
+
else
|
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
22
|
+
end
|
|
23
|
+
|
|
16
24
|
spec.files = `git ls-files -z`.split("\x0")
|
|
17
25
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
26
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
27
|
spec.require_paths = ["lib"]
|
|
20
28
|
|
|
21
|
-
spec.add_runtime_dependency "activesupport", ">=
|
|
29
|
+
spec.add_runtime_dependency "activesupport", ">= 5.2"
|
|
22
30
|
|
|
23
31
|
spec.add_development_dependency "rake", "> 10.0"
|
|
24
32
|
spec.add_development_dependency "minitest", "> 5.5.1"
|
|
25
33
|
spec.add_development_dependency "minitest-reporters"
|
|
26
|
-
spec.add_development_dependency "mocha", "
|
|
34
|
+
spec.add_development_dependency "mocha", ">= 1.4.0"
|
|
27
35
|
spec.add_development_dependency "pry"
|
|
28
36
|
end
|
data/test/arithmetic_test.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "test_helper"
|
|
2
3
|
|
|
3
4
|
class Measured::ArithmeticTest < ActiveSupport::TestCase
|
|
@@ -7,6 +8,41 @@ class Measured::ArithmeticTest < ActiveSupport::TestCase
|
|
|
7
8
|
@four = Magic.new(4, :magic_missile)
|
|
8
9
|
end
|
|
9
10
|
|
|
11
|
+
test "should be able to sum same units" do
|
|
12
|
+
assert_equal Magic.new(9, :magic_missile), [@two, @three, @four].sum
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test 'can check for finite?' do
|
|
16
|
+
assert Magic.new(0, :magic_missile).finite?
|
|
17
|
+
refute Magic.new(Float::INFINITY, :magic_missile).finite?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test 'can check for infinite?' do
|
|
21
|
+
assert Magic.new(Float::INFINITY, :magic_missile).infinite?
|
|
22
|
+
refute Magic.new(0, :magic_missile).infinite?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test 'can check for zero?' do
|
|
26
|
+
assert Magic.new(0, :magic_missile).zero?
|
|
27
|
+
refute Magic.new(1, :magic_missile).zero?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test 'can check for nonzero?' do
|
|
31
|
+
assert_equal Magic.new(10, :magic_missile), Magic.new(10, :magic_missile).nonzero?
|
|
32
|
+
assert Magic.new(10, :magic_missile).nonzero?
|
|
33
|
+
refute Magic.new(0, :magic_missile).nonzero?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
test 'can check for positive?' do
|
|
37
|
+
assert Magic.new(1, :magic_missile).positive?
|
|
38
|
+
refute Magic.new(-1, :magic_missile).positive?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test 'can check for negative?' do
|
|
42
|
+
assert Magic.new(-1, :magic_missile).negative?
|
|
43
|
+
refute Magic.new(1, :magic_missile).negative?
|
|
44
|
+
end
|
|
45
|
+
|
|
10
46
|
test "#+ should add together same units" do
|
|
11
47
|
assert_equal Magic.new(5, :magic_missile), @two + @three
|
|
12
48
|
assert_equal Magic.new(5, :magic_missile), @three + @two
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
class Measured::Cache::JsonTest < ActiveSupport::TestCase
|
|
5
|
+
setup do
|
|
6
|
+
@cache = Measured::Cache::Json.new("test.json")
|
|
7
|
+
@table_json = { "a" => { "b" => { "numerator" => 2, "denominator" => 3 } } }.to_json
|
|
8
|
+
@table_hash = { "a" => { "b" => Rational(2, 3) } }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "#initialize sets the filename and path" do
|
|
12
|
+
assert_equal "test.json", @cache.filename
|
|
13
|
+
assert_match(/.+\/cache\/test\.json$/, @cache.path.to_s)
|
|
14
|
+
refute_match "../", @cache.path.to_s
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test "#exist? returns false if the file does not exist" do
|
|
18
|
+
File.expects(:exist?).with(@cache.path).returns(false)
|
|
19
|
+
refute_predicate @cache, :exist?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "#exist? returns true if the file exists" do
|
|
23
|
+
File.expects(:exist?).with(@cache.path).returns(true)
|
|
24
|
+
assert_predicate @cache, :exist?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test "#read returns nil if the file does not exist" do
|
|
28
|
+
File.expects(:exist?).with(@cache.path).returns(false)
|
|
29
|
+
assert_nil @cache.read
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
test "#read loads the file if it exists" do
|
|
33
|
+
File.expects(:exist?).with(@cache.path).returns(true)
|
|
34
|
+
File.expects(:read).with(@cache.path).returns(@table_json)
|
|
35
|
+
assert_equal @table_hash, @cache.read
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "#write raises not implemented" do
|
|
39
|
+
assert_raises(ArgumentError) do
|
|
40
|
+
@cache.write({})
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
class Measured::Cache::JsonWriterTest < ActiveSupport::TestCase
|
|
5
|
+
class JsonTestWithWriter < Measured::Cache::Json
|
|
6
|
+
prepend Measured::Cache::JsonWriter
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
setup do
|
|
10
|
+
@cache = JsonTestWithWriter.new("test.json")
|
|
11
|
+
@table_json = JSON.pretty_generate({ "a" => { "b" => { "numerator" => 2, "denominator" => 3 } } })
|
|
12
|
+
@table_hash = { "a" => { "b" => Rational(2, 3) } }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "#write writes the file" do
|
|
16
|
+
f = stub
|
|
17
|
+
f.expects(:write).with("// Do not modify this file directly. Regenerate it with 'rake cache:write'.\n")
|
|
18
|
+
f.expects(:write).with(@table_json)
|
|
19
|
+
|
|
20
|
+
File.expects(:open).with(@cache.path, "w").returns(123).yields(f)
|
|
21
|
+
assert_equal 123, @cache.write(@table_hash)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
class Measured::Cache::NullTest < ActiveSupport::TestCase
|
|
5
|
+
setup do
|
|
6
|
+
@cache = Measured::Cache::Null.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
test "#exist? false" do
|
|
10
|
+
assert_equal false, @cache.exist?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
test "#read returns nil" do
|
|
14
|
+
assert_nil @cache.read
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
test "#write returns nil" do
|
|
18
|
+
assert_nil @cache.write({})
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
# In general we do not want to expose the inner workings of the caching and unit systems as part of the API.
|
|
5
|
+
# But we do want to be able to test that there is no conflict between what's in the cache file and what is defined
|
|
6
|
+
# in the unit systems. So we compromise by reaching into implementation to force compare them.
|
|
7
|
+
class Measured::CacheConsistencyTest < ActiveSupport::TestCase
|
|
8
|
+
measurable_subclasses.select { |m| m.unit_system.cached? }.each do |measurable|
|
|
9
|
+
test "cached measurable #{ measurable } is not out of sync with the definition" do
|
|
10
|
+
builder = measurable.unit_system.instance_variable_get("@conversion_table_builder")
|
|
11
|
+
cache = builder.instance_variable_get("@cache")
|
|
12
|
+
|
|
13
|
+
expected = builder.send(:generate_table)
|
|
14
|
+
actual = cache.read
|
|
15
|
+
|
|
16
|
+
assert expected == actual, "The contents of the file cache for `#{ measurable }` does not match what the unit system generated.\nTry running `rake cache:write` to update the caches."
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "test_helper"
|
|
3
|
+
|
|
4
|
+
class Measured::ConversionTableBuilderTest < ActiveSupport::TestCase
|
|
5
|
+
test "#initialize creates a new object with the units" do
|
|
6
|
+
units = [Measured::Unit.new(:test)]
|
|
7
|
+
|
|
8
|
+
assert_equal units, Measured::ConversionTableBuilder.new(units).units
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "#to_h should return a hash for the simple case" do
|
|
12
|
+
conversion_table = Measured::ConversionTableBuilder.new([Measured::Unit.new(:test)]).to_h
|
|
13
|
+
|
|
14
|
+
expected = {
|
|
15
|
+
"test" => {"test" => Rational(1, 1)}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
assert_equal expected, conversion_table
|
|
19
|
+
assert_instance_of Rational, conversion_table.values.first.values.first
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "#to_h returns expected nested hashes with BigDecimal conversion factors in a tiny data set" do
|
|
23
|
+
conversion_table = Measured::ConversionTableBuilder.new([
|
|
24
|
+
Measured::Unit.new(:m),
|
|
25
|
+
Measured::Unit.new(:cm, value: "0.01 m"),
|
|
26
|
+
]).to_h
|
|
27
|
+
|
|
28
|
+
expected = {
|
|
29
|
+
"m" => {
|
|
30
|
+
"m" => Rational(1, 1),
|
|
31
|
+
"cm" => Rational(100, 1),
|
|
32
|
+
},
|
|
33
|
+
"cm" => {
|
|
34
|
+
"m" => Rational(1, 100),
|
|
35
|
+
"cm" => Rational(1, 1),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
assert_equal expected, conversion_table
|
|
40
|
+
|
|
41
|
+
conversion_table.values.map(&:values).flatten.each do |value|
|
|
42
|
+
assert_instance_of Rational, value
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
test "#to_h returns expected nested hashes factors" do
|
|
47
|
+
conversion_table = Measured::ConversionTableBuilder.new([
|
|
48
|
+
Measured::Unit.new(:m),
|
|
49
|
+
Measured::Unit.new(:cm, value: "0.01 m"),
|
|
50
|
+
Measured::Unit.new(:mm, value: "0.001 m"),
|
|
51
|
+
]).to_h
|
|
52
|
+
|
|
53
|
+
expected = {
|
|
54
|
+
"m" => {
|
|
55
|
+
"m" => Rational(1, 1),
|
|
56
|
+
"cm" => Rational(100, 1),
|
|
57
|
+
"mm" => Rational(1000, 1),
|
|
58
|
+
},
|
|
59
|
+
"cm" => {
|
|
60
|
+
"m" => Rational(1, 100),
|
|
61
|
+
"cm" => Rational(1, 1),
|
|
62
|
+
"mm" => Rational(10, 1),
|
|
63
|
+
},
|
|
64
|
+
"mm" => {
|
|
65
|
+
"m" => Rational(1, 1000),
|
|
66
|
+
"cm" => Rational(1, 10),
|
|
67
|
+
"mm" => Rational(1, 1),
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
assert_equal expected, conversion_table
|
|
72
|
+
|
|
73
|
+
conversion_table.values.map(&:values).flatten.each do |value|
|
|
74
|
+
assert_instance_of Rational, value
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
test "#to_h returns expected nested hashes in an indrect path" do
|
|
79
|
+
conversion_table = Measured::ConversionTableBuilder.new([
|
|
80
|
+
Measured::Unit.new(:mm),
|
|
81
|
+
Measured::Unit.new(:cm, value: "10 mm"),
|
|
82
|
+
Measured::Unit.new(:dm, value: "10 cm"),
|
|
83
|
+
Measured::Unit.new(:m, value: "10 dm"),
|
|
84
|
+
]).to_h
|
|
85
|
+
|
|
86
|
+
expected = {
|
|
87
|
+
"m" => {
|
|
88
|
+
"m" => Rational(1, 1),
|
|
89
|
+
"dm" => Rational(10, 1),
|
|
90
|
+
"cm" => Rational(100, 1),
|
|
91
|
+
"mm" => Rational(1000, 1),
|
|
92
|
+
},
|
|
93
|
+
"cm" => {
|
|
94
|
+
"m" => Rational(1, 100),
|
|
95
|
+
"dm" => Rational(1, 10),
|
|
96
|
+
"cm" => Rational(1, 1),
|
|
97
|
+
"mm" => Rational(10, 1),
|
|
98
|
+
},
|
|
99
|
+
"dm" => {
|
|
100
|
+
"m" => Rational(1, 10),
|
|
101
|
+
"cm" => Rational(10, 1),
|
|
102
|
+
"dm" => Rational(1, 1),
|
|
103
|
+
"mm" => Rational(100, 1),
|
|
104
|
+
},
|
|
105
|
+
"mm" => {
|
|
106
|
+
"m" => Rational(1, 1000),
|
|
107
|
+
"dm" => Rational(1, 100),
|
|
108
|
+
"cm" => Rational(1, 10),
|
|
109
|
+
"mm" => Rational(1, 1),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
assert_equal expected, conversion_table
|
|
114
|
+
|
|
115
|
+
conversion_table.values.map(&:values).flatten.each do |value|
|
|
116
|
+
assert_instance_of Rational, value
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
test "#to_h raises exception when there are cycles" do
|
|
121
|
+
unit1 = Measured::Unit.new(:pallets, value: "1 liters")
|
|
122
|
+
unit2 = Measured::Unit.new(:liters, value: "0.1 cases")
|
|
123
|
+
unit3 = Measured::Unit.new(:cases, value: "0.1 pallets")
|
|
124
|
+
|
|
125
|
+
assert_raises(Measured::CycleDetected) do
|
|
126
|
+
Measured::ConversionTableBuilder.new([unit1, unit2, unit3]).to_h
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
test "#cached? returns true if there's a cache" do
|
|
131
|
+
builder = Measured::ConversionTableBuilder.new([Measured::Unit.new(:test)], cache: { class: AlwaysTrueCache })
|
|
132
|
+
assert_predicate builder, :cached?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
test "#cached? returns false if there is not a cache" do
|
|
136
|
+
builder = Measured::ConversionTableBuilder.new([Measured::Unit.new(:test)])
|
|
137
|
+
refute_predicate builder, :cached?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
test "#write_cache pushes the generated table into the cache and writes it" do
|
|
141
|
+
builder = Measured::ConversionTableBuilder.new([Measured::Unit.new(:test)], cache: { class: AlwaysTrueCache })
|
|
142
|
+
AlwaysTrueCache.any_instance.expects(:exist?).returns(false)
|
|
143
|
+
table = builder.to_h
|
|
144
|
+
AlwaysTrueCache.any_instance.expects(:write).with(table).returns(123)
|
|
145
|
+
assert_equal 123, builder.update_cache
|
|
146
|
+
end
|
|
147
|
+
end
|
data/test/measurable_test.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require "test_helper"
|
|
2
3
|
|
|
3
4
|
class Measured::MeasurableTest < ActiveSupport::TestCase
|
|
4
|
-
|
|
5
5
|
setup do
|
|
6
6
|
@arcane = Magic.unit_system.unit_for!(:arcane)
|
|
7
7
|
@fireball = Magic.unit_system.unit_for!(:fireball)
|
|
@@ -216,6 +216,27 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
|
|
|
216
216
|
assert_equal "5 fireball", Magic.new(Rational(5, 1), :fire).to_s
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
+
test "#to_s outputs the correct number of decimals" do
|
|
220
|
+
assert_equal "9.3 fireball", Magic.new(9.3, :fire).to_s
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
test "#format outputs a formatted string" do
|
|
224
|
+
measured_object = Magic.new(9.342, :magic_missile)
|
|
225
|
+
assert_equal "9.3", measured_object.format("%.1<value>f")
|
|
226
|
+
assert_equal "magic_missile", measured_object.format("%<unit>s")
|
|
227
|
+
assert_equal "9.34 magic_missile", measured_object.format("%.2<value>f %<unit>s")
|
|
228
|
+
assert_equal "9.342000 magic_missile", measured_object.format("%<value>f %<unit>s")
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
test "#format with no formatting string uses the default one" do
|
|
232
|
+
assert_equal "9.34 magic_missile", Magic.new(9.342, :magic_missile).format
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
test "#format can drop the conversion amount" do
|
|
236
|
+
assert_equal "1.00 fireball (2/3 magic_missile)", Magic.new(1, :fireball).format
|
|
237
|
+
assert_equal "1.00 fireball", Magic.new(1, :fireball).format(with_conversion_string: false)
|
|
238
|
+
end
|
|
239
|
+
|
|
219
240
|
test "#humanize outputs the number and the unit properly pluralized" do
|
|
220
241
|
assert_equal "1 fireball", Magic.new("1", :fire).humanize
|
|
221
242
|
assert_equal "10 fireballs", Magic.new(10, :fire).humanize
|
|
@@ -230,22 +251,16 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
|
|
|
230
251
|
assert_equal "#<Magic: 1.234 #<Measured::Unit: magic_missile (magic_missiles, magic missile)>>", Magic.new(1.234, :magic_missile).inspect
|
|
231
252
|
end
|
|
232
253
|
|
|
233
|
-
test "#zero? always returns false" do
|
|
234
|
-
refute_predicate Magic.new(0, :fire), :zero?
|
|
235
|
-
refute_predicate Magic.new(0.0, :fire), :zero?
|
|
236
|
-
refute_predicate Magic.new("0.0", :fire), :zero?
|
|
237
|
-
end
|
|
238
|
-
|
|
239
254
|
test "#<=> compares regardless of the unit" do
|
|
240
|
-
assert_equal -1, @magic <=> Magic.new(20, :fire)
|
|
255
|
+
assert_equal (-1), @magic <=> Magic.new(20, :fire)
|
|
241
256
|
assert_equal 1, @magic <=> Magic.new(9, :magic_missile)
|
|
242
257
|
assert_equal 0, @magic <=> Magic.new(Rational(30, 2), :fire)
|
|
243
|
-
assert_equal -1, @magic <=> Magic.new(11, :magic_missile)
|
|
258
|
+
assert_equal (-1), @magic <=> Magic.new(11, :magic_missile)
|
|
244
259
|
end
|
|
245
260
|
|
|
246
261
|
test "#<=> doesn't compare against zero" do
|
|
247
262
|
assert_nil @magic <=> 0
|
|
248
|
-
assert_nil @magic <=> BigDecimal
|
|
263
|
+
assert_nil @magic <=> BigDecimal(0)
|
|
249
264
|
assert_nil @magic <=> 0.00
|
|
250
265
|
end
|
|
251
266
|
|
|
@@ -263,7 +278,7 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
|
|
|
263
278
|
test "#== doesn't compare against zero" do
|
|
264
279
|
arcane_zero = Magic.new(0, :arcane)
|
|
265
280
|
refute_equal arcane_zero, 0
|
|
266
|
-
refute_equal arcane_zero, BigDecimal
|
|
281
|
+
refute_equal arcane_zero, BigDecimal(0)
|
|
267
282
|
refute_equal arcane_zero, 0.0
|
|
268
283
|
end
|
|
269
284
|
|
|
@@ -279,10 +294,10 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
|
|
|
279
294
|
|
|
280
295
|
test "#> and #< should not compare against zero" do
|
|
281
296
|
assert_raises(ArgumentError) { @magic > 0 }
|
|
282
|
-
assert_raises(ArgumentError) { @magic > BigDecimal
|
|
297
|
+
assert_raises(ArgumentError) { @magic > BigDecimal(0) }
|
|
283
298
|
assert_raises(ArgumentError) { @magic > 0.00 }
|
|
284
299
|
assert_raises(ArgumentError) { @magic < 0 }
|
|
285
|
-
assert_raises(ArgumentError) { @magic < BigDecimal
|
|
300
|
+
assert_raises(ArgumentError) { @magic < BigDecimal(0) }
|
|
286
301
|
assert_raises(ArgumentError) { @magic < 0.00 }
|
|
287
302
|
end
|
|
288
303
|
end
|
data/test/parser_test.rb
CHANGED
data/test/support/fake_system.rb
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Extract the subclasses that exist early on because other classes will get added by tests
|
|
3
|
+
# later on in execution and in an unpredictable order.
|
|
4
|
+
class ActiveSupport::TestCase
|
|
5
|
+
cattr_accessor :measurable_subclasses
|
|
6
|
+
self.measurable_subclasses = Measured::Measurable.subclasses
|
|
7
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "pry" unless ENV["CI"]
|
|
1
3
|
require "measured"
|
|
2
4
|
require "minitest/reporters"
|
|
3
5
|
require "minitest/autorun"
|
|
4
|
-
require "mocha/
|
|
5
|
-
require "pry"
|
|
6
|
+
require "mocha/minitest"
|
|
6
7
|
|
|
7
8
|
ActiveSupport.test_order = :random
|
|
8
9
|
|
|
9
10
|
Minitest::Reporters.use! [Minitest::Reporters::ProgressReporter.new(color: true)]
|
|
10
11
|
|
|
12
|
+
require "support/subclasses"
|
|
11
13
|
require "support/fake_system"
|
|
14
|
+
require "support/always_true_cache"
|
|
12
15
|
|
|
13
16
|
class ActiveSupport::TestCase
|
|
14
|
-
|
|
15
17
|
protected
|
|
16
18
|
|
|
17
19
|
def assert_close_bigdecimal exp, act, delta = BigDecimal('0.000001')
|
data/test/unit_error_test.rb
CHANGED