Complete
over 3 years ago

Not a CIQ issue. For more context, here's a link to the Bug Reports FAQ, https://forums.garmin.com/developer/connect-iq/w/wiki/5/bug-reports-faq.

Next time, consider starting a discussion. A discussion can be escalated to a bug report.

Unable to test km to mile conversion of half marathon

```

  (:distance)
  module Distance {

    function toMiles(dist) {
      var mi = dist.toDouble() * 0.6213711922d;
      return mi.toDouble();
    }

  }

I have the following Test:

// t.is() == test.assertEqualmessage
// t.ok() == test.assertMessage()
// t.pass() == test.assertMessage(true, msg)
// t.fail() == test.assertMessage(false, msg)

    (:test)
    function testDistance(logger) {

      t.is(dist.toMiles(1), 0.6213711922d, "1km is 0.6213711922 miles");

      var mi = dist.toMiles(21.0975);
      Sys.println(mi); // prints 13.109379

      var mile = 13.109379d;
      Sys.println(mile); // print 13.109379

      if (mile == mi) {
        t.pass("A mile is a mile");
      }
      else {
        t.fail("A mile isn't a mile");
      }

      t.is(dist.toMiles(21.0975), 13.109378728d, "Half marathon distance");
      t.ok(dist.toMiles(21.0975) == 13.109379d, "Half marathon distance");

      return true;
    }

This fails on Exception: ASSERTION FAILED: A mile isn't a mile    File: UnitTests

I'm kinda expecting it all to work.


The problem is because I cannot see what the test sees (as described here https://forums.garmin.com/developer/connect-iq/i/bug-reports/test-assertequalmessage-and-friends-to-show-incorrectness), so from there I'm sitting the values should be correct. Working around it by adding a toString() doesn't work, it still thinks it isn't the same value.

Parents
  • 1. always have the most possible but at least the necessary data in your error messages. i.e: t.fail("A mile (" + mile + ") isn't a mile (" + mi + ")")
    2. it can happen that even here you will see the "same" value and still == won't be true. This is life and how floating point arithmetic works.
    3. you can maybe convert to string and compare them as string to fix that.
    4. IMHO you don't need return mi.toDouble();, enough return mi, 'cause it's anyway already a double.

Comment
  • 1. always have the most possible but at least the necessary data in your error messages. i.e: t.fail("A mile (" + mile + ") isn't a mile (" + mi + ")")
    2. it can happen that even here you will see the "same" value and still == won't be true. This is life and how floating point arithmetic works.
    3. you can maybe convert to string and compare them as string to fix that.
    4. IMHO you don't need return mi.toDouble();, enough return mi, 'cause it's anyway already a double.

Children
  • 3 doesn't work, yet when you print the values it does seem to be the same. Which makes the behaviour odd.
    Oh, when you have a precision of 6 it starts to work with toString(). But that is something for the testsuite to fix I think. or allow toDouble(precision) so you can tweak the precision within the compare, eg test.assertEqualMessage(3.toDouble(4) * 2, 6.toDouble(4), "we can math");

  • As to 1, to humor you

    t.is(mi, mile, Lang.format("A mile $1$ is a mile $2$", [ mi, mile ]));
    
    # outputs:
    Exception: ASSERTION FAILED: A mile 13.109379 is a mile 13.109379  - pc: 0x10000874
    

  • I don't want to have to repeat all kinds of values just so I can see what is wrong. As seen in the link, I've asked to include it by the test functions. They won't because of blub reasons.

    I solved it differently tho or worked around it. In order to get assertEquals and friends to play nice, I format both the needle and the haystack with a precision of 7 digits and than compare the lot:

        function cmp_double(dbl, expect, msg) {
          dbl = dbl.format("%.7f");
          expect = expect.format("%.7f");
          // https://forums.garmin.com/developer/connect-iq/i/bug-reports/unable-to-test-km-to-mile-conversion-of-half-marathon
          //Sys.println(dbl  + " " + expect);
          t.is(dbl, expect, msg);
        }
    
        (:test)
        function testDistance(logger) {
    
          cmp_double(dist.toMiles(1), 0.6213712d, "1km us 0.62137 miles");
          cmp_double(dist.toMiles(21.0975), 13.1093786d, "Half marathon distance");
    
          return true;
        }
    
        (:test)
        function testWeight(logger) {
    
          cmp_double(mass.toLbs(1), 2.2046226d, "1kg is 2.20462 lbs");
          cmp_double(mass.toLbs(86.2), 190.0384633d, "Karting weight");
          cmp_double(mass.toLbs(20), 44.0924524d, "Barbell weight");
          return true;
    
        }

    The test.assert-family should deal with the objects and how things are compared, assertEqualMessage("foo", "bar", "compare the two"); could compare with "foo".equals("bar"), but I'm not sure as Garmin has closed source their SDK.

  • 5. strings you sompare with equals: str1.equals(str2)