diff --git a/frameworks/javascript/cw-2.js b/frameworks/javascript/cw-2.js index 6de862e9..611f2352 100644 --- a/frameworks/javascript/cw-2.js +++ b/frameworks/javascript/cw-2.js @@ -360,8 +360,8 @@ try { // Compares two floating point values and checks whether they are approximately equal to each other options = options || {}; msg = Test.display.message('Expected actual value ' + actual + ' to approximately equal expected value ' + expected + ' (accepted relative error: 1e-9)', msg); - if (expected === 0) { - Test.expect(Math.abs(actual) <= 1e-9, msg, options); + if (Math.abs(expected) <= 1) { + Test.expect(Math.abs(expected - actual) <= 1e-9, msg, options); } else { Test.expect(Math.abs((expected - actual) / expected) <= 1e-9, msg, options); @@ -371,8 +371,8 @@ try { // Compares two floating point values and checks whether they are sufficiently different from each other options = options || {}; msg = Test.display.message('Actual value ' + actual + ' should not approximately equal unexpected value ' + unexpected + ' (rejected relative error: 1e-9)', msg); - if (unexpected === 0) { - Test.expect(Math.abs(actual) > 1e-9, msg, options); + if (Math.abs(unexpected) <= 1) { + Test.expect(Math.abs(unexpected - actual) > 1e-9, msg, options); } else { Test.expect(Math.abs((unexpected - actual) / unexpected) > 1e-9, msg, options); diff --git a/test/runners/javascript_spec.js b/test/runners/javascript_spec.js index 20d41e27..c4e0454b 100644 --- a/test/runners/javascript_spec.js +++ b/test/runners/javascript_spec.js @@ -849,6 +849,168 @@ describe("test", function(){ }); }); + describe('Fix Codewars/codewars.com#962', function() { + describe('Test.assertApproxEquals', function() { + it('should allow for an absolute error range of 1e-9 when the actual value returned is 0', function(done) { + runner.run({language: 'javascript', code: 'var a = 0', fixture: `Test.assertApproxEquals(a, 1e-15); +Test.assertApproxEquals(a, 1e-14); +Test.assertApproxEquals(a, 1e-13); +Test.assertApproxEquals(a, 1e-12); +Test.assertApproxEquals(a, 1e-11); +Test.assertApproxEquals(a, 1e-10); +Test.assertApproxEquals(a, 1e-9); +Test.assertApproxEquals(a, -1e-9); +Test.assertApproxEquals(a, -1e-10); +Test.assertApproxEquals(a, -1e-11); +Test.assertApproxEquals(a, -1e-12); +Test.assertApproxEquals(a, -1e-13); +Test.assertApproxEquals(a, -1e-14); +Test.assertApproxEquals(a, -1e-15);`, testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should allow for an absolute error range of *no more than* 1e-9 when the actual value returned is 0', function(done) { + runner.run({language: 'javascript', code: 'var a = 0', fixture: `Test.assertApproxEquals(a, 1e-8); +Test.assertApproxEquals(a, 1e-7); +Test.assertApproxEquals(a, 1e-6); +Test.assertApproxEquals(a, 1e-5); +Test.assertApproxEquals(a, 1e-4); +Test.assertApproxEquals(a, 1e-3); +Test.assertApproxEquals(a, 1e-2); +Test.assertApproxEquals(a, 1e-1); +Test.assertApproxEquals(a, 1); +Test.assertApproxEquals(a, -1); +Test.assertApproxEquals(a, -1e-1); +Test.assertApproxEquals(a, -1e-2); +Test.assertApproxEquals(a, -1e-3); +Test.assertApproxEquals(a, -1e-4); +Test.assertApproxEquals(a, -1e-5); +Test.assertApproxEquals(a, -1e-6); +Test.assertApproxEquals(a, -1e-7); +Test.assertApproxEquals(a, -1e-8);`, testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as an absolute error margin and not a relative one when Math.abs(expected) <= 1 (passing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1e-8 - 1e-10, 1e-8 - 1e-11, 1e-8 - 1e-12, 1e-8 - 1e-13, 1e-8 - 1e-14, 1e-8 - 1e-15, 1e-8 + 1e-15, 1e-8 + 1e-14, 1e-8 + 1e-13, 1e-8 + 1e-12, 1e-8 + 1e-11, 1e-8 + 1e-10], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertApproxEquals(a[i], 1e-8); Test.assertApproxEquals(b[i], -1e-8); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as an absolute error margin and not a relative one when Math.abs(expected) <= 1 (failing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1e-8 - 1e-8, 1e-8 - 1e-7, 1e-8 - 1e-6, 1e-8 - 1e-5, 1e-8 - 1e-4, 1e-8 - 1e-3, 1e-8 - 1e-2, 1e-8 - 1e-1, 1e-8 + 1e-1, 1e-8 + 1e-2, 1e-8 + 1e-3, 1e-8 + 1e-4, 1e-8 + 1e-5, 1e-8 + 1e-6, 1e-8 + 1e-7, 1e-8 + 1e-8], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertApproxEquals(a[i], 1e-8); Test.assertApproxEquals(b[i], -1e-8); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as a relative error margin and not an absolute one when Math.abs(expected) > 1 (passing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1000000 - 1e-8, 1000000 - 1e-7, 1000000 - 1e-6, 1000000 - 1e-5, 1000000 - 1e-4, 1000000 + 1e-4, 1000000 + 1e-5, 1000000 + 1e-6, 1000000 + 1e-7, 1000000 + 1e-8], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertApproxEquals(a[i], 1000000); Test.assertApproxEquals(b[i], -1000000); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as a relative error margin and not an absolute one when Math.abs(expected) > 1 (failing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1000000 - 1e-2, 1000000 - 1e-1, 1000000 - 1, 1000000 - 10, 1000000 - 100, 1000000 + 100, 1000000 + 10, 1000000 + 1, 1000000 + 1e-1, 1000000 + 1e-2], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertApproxEquals(a[i], 1000000); Test.assertApproxEquals(b[i], -1000000); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + }); + describe('Test.assertNotApproxEquals', function() { + it('should reject an absolute difference of 1e-9 or less if the actual value is 0', function(done) { + runner.run({language: 'javascript', code: 'var a = 0', fixture: `Test.assertNotApproxEquals(a, 1e-15); +Test.assertNotApproxEquals(a, 1e-14); +Test.assertNotApproxEquals(a, 1e-13); +Test.assertNotApproxEquals(a, 1e-12); +Test.assertNotApproxEquals(a, 1e-11); +Test.assertNotApproxEquals(a, 1e-10); +Test.assertNotApproxEquals(a, 1e-9); +Test.assertNotApproxEquals(a, -1e-9); +Test.assertNotApproxEquals(a, -1e-10); +Test.assertNotApproxEquals(a, -1e-11); +Test.assertNotApproxEquals(a, -1e-12); +Test.assertNotApproxEquals(a, -1e-13); +Test.assertNotApproxEquals(a, -1e-14); +Test.assertNotApproxEquals(a, -1e-15);`, testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should accept an absolute difference greater than 1e-9 if the actual value is 0', function(done) { + runner.run({language: 'javascript', code: 'var a = 0', fixture: `Test.assertNotApproxEquals(a, 1e-8); +Test.assertNotApproxEquals(a, 1e-7); +Test.assertNotApproxEquals(a, 1e-6); +Test.assertNotApproxEquals(a, 1e-5); +Test.assertNotApproxEquals(a, 1e-4); +Test.assertNotApproxEquals(a, 1e-3); +Test.assertNotApproxEquals(a, 1e-2); +Test.assertNotApproxEquals(a, 1e-1); +Test.assertNotApproxEquals(a, 1); +Test.assertNotApproxEquals(a, -1); +Test.assertNotApproxEquals(a, -1e-1); +Test.assertNotApproxEquals(a, -1e-2); +Test.assertNotApproxEquals(a, -1e-3); +Test.assertNotApproxEquals(a, -1e-4); +Test.assertNotApproxEquals(a, -1e-5); +Test.assertNotApproxEquals(a, -1e-6); +Test.assertNotApproxEquals(a, -1e-7); +Test.assertNotApproxEquals(a, -1e-8);`, testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as an absolute error margin and not a relative one when Math.abs(unexpected) <= 1 (failing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1e-8 - 1e-10, 1e-8 - 1e-11, 1e-8 - 1e-12, 1e-8 - 1e-13, 1e-8 - 1e-14, 1e-8 - 1e-15, 1e-8 + 1e-15, 1e-8 + 1e-14, 1e-8 + 1e-13, 1e-8 + 1e-12, 1e-8 + 1e-11, 1e-8 + 1e-10], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertNotApproxEquals(a[i], 1e-8); Test.assertNotApproxEquals(b[i], -1e-8); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as an absolute error margin and not a relative one when Math.abs(unexpected) <= 1 (passing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1e-8 - 1e-8, 1e-8 - 1e-7, 1e-8 - 1e-6, 1e-8 - 1e-5, 1e-8 - 1e-4, 1e-8 - 1e-3, 1e-8 - 1e-2, 1e-8 - 1e-1, 1e-8 + 1e-1, 1e-8 + 1e-2, 1e-8 + 1e-3, 1e-8 + 1e-4, 1e-8 + 1e-5, 1e-8 + 1e-6, 1e-8 + 1e-7, 1e-8 + 1e-8], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertNotApproxEquals(a[i], 1e-8); Test.assertNotApproxEquals(b[i], -1e-8); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as a relative error margin and not an absolute one when Math.abs(unexpected) > 1 (failing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1000000 - 1e-8, 1000000 - 1e-7, 1000000 - 1e-6, 1000000 - 1e-5, 1000000 - 1e-4, 1000000 + 1e-4, 1000000 + 1e-5, 1000000 + 1e-6, 1000000 + 1e-7, 1000000 + 1e-8], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertNotApproxEquals(a[i], 1000000); Test.assertNotApproxEquals(b[i], -1000000); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + it('should treat 1e-9 as a relative error margin and not an absolute one when Math.abs(unexpected) > 1 (passing tests only)', function(done) { + runner.run({language: 'javascript', code: 'var a = [1000000 - 1e-2, 1000000 - 1e-1, 1000000 - 1, 1000000 - 10, 1000000 - 100, 1000000 + 100, 1000000 + 10, 1000000 + 1, 1000000 + 1e-1, 1000000 + 1e-2], b = a.map(n => -n)', fixture: 'for (let i = 0; i < a.length; i++) { Test.assertNotApproxEquals(a[i], 1000000); Test.assertNotApproxEquals(b[i], -1000000); }', testFramework: 'cw-2'}, function(buffer) { + expect(buffer.stdout).to.contain(''); + expect(buffer.stdout).to.not.contain(''); + expect(buffer.stdout).to.not.contain(''); + done(); + }); + }); + }); + }); //---------------------------------------------------------------------------------------- // Karma BDD