Add a persisted test suite
`bundle exec rake test` (minitest, a default gem but pinned in Gemfile for reproducibility) now covers what ad-hoc scripts kept re-verifying by hand during development: Gpx/Fit/TrackStats parsing, GpxStore/LiveTrackStore file/TTL logic, LiveTrackClient's payload parsing, and app.rb's routes end to end via Rack::MockRequest. MAPTOOL_DATA_DIR (new, app.rb) lets the suite point GPX_STORE/ LIVETRACK_STORE at a throwaway directory instead of real data/ — without it every run would leave uploaded test files behind. Each lib file's old `if __FILE__ == $0` self-check is now redundant with real tests covering the same ground, so removed rather than kept as a second copy of the same assertions. Wired into ci.yml so it isn't just a local convenience.
This commit is contained in:
1 parent
a3c31ace06
commit
cd4eef342b
19 files changed
+706
-174
No files matched your search
@@ -0,0 +1,60 @@
|
||||
require_relative "test_helper"
|
||||
require "maptool/fit"
|
||||
|
||||
class FitTest < Minitest::Test
|
||||
def le32(n)
|
||||
[n].pack("l<")
|
||||
end
|
||||
|
||||
# A minimal hand-built FIT file: header + one definition message (local
|
||||
# type 0, global mesg 20 "record", fields position_lat/position_long,
|
||||
# both sint32) + data messages. Exercises the header/definition/data
|
||||
# framing without needing an external fixture file.
|
||||
def build_fit(records)
|
||||
definition = [0, 0].pack("CC") + [20].pack("S<") + [2].pack("C") +
|
||||
[0, 4, 0x85].pack("C3") + [1, 4, 0x85].pack("C3")
|
||||
definition_header = [0b01000000].pack("C")
|
||||
|
||||
data = records.map { |lat, lon| [0b00000000].pack("C") + le32(lat) + le32(lon) }.join
|
||||
|
||||
body = definition_header + definition + data
|
||||
header = [12, 16, 0, 0].pack("C2S<") + le32(body.bytesize) + ".FIT"
|
||||
header + body + "\x00\x00"
|
||||
end
|
||||
|
||||
def write_fit(records)
|
||||
path = File.join(Dir.mktmpdir, "test.fit")
|
||||
File.binwrite(path, build_fit(records))
|
||||
path
|
||||
end
|
||||
|
||||
def test_parses_coordinates_from_record_messages
|
||||
path = write_fit([[100_000_000, 200_000_000], [100_000_100, 200_000_100]])
|
||||
|
||||
geojson = Maptool::Fit.to_geojson(path)
|
||||
coords = geojson["features"][0]["geometry"]["coordinates"][0]
|
||||
|
||||
assert_equal 2, coords.size
|
||||
expected_lat = 100_000_000 * Maptool::Fit::SEMICIRCLE_TO_DEGREES
|
||||
expected_lon = 200_000_000 * Maptool::Fit::SEMICIRCLE_TO_DEGREES
|
||||
assert_in_delta expected_lat, coords[0][1], 1e-9
|
||||
assert_in_delta expected_lon, coords[0][0], 1e-9
|
||||
end
|
||||
|
||||
def test_kinds_is_track_when_positioned
|
||||
assert_equal ["track"], Maptool::Fit.kinds(write_fit([[100_000_000, 200_000_000]]))
|
||||
end
|
||||
|
||||
def test_a_file_with_no_positioned_records_has_no_features_or_kinds
|
||||
path = write_fit([])
|
||||
assert_empty Maptool::Fit.to_geojson(path)["features"]
|
||||
assert_empty Maptool::Fit.kinds(path)
|
||||
end
|
||||
|
||||
def test_garbage_input_raises_parse_error
|
||||
path = File.join(Dir.mktmpdir, "garbage.fit")
|
||||
File.binwrite(path, "not a fit file at all")
|
||||
|
||||
assert_raises(Maptool::Fit::ParseError) { Maptool::Fit.to_geojson(path) }
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user