Skip to content
This repository has been archived by the owner on Oct 14, 2020. It is now read-only.

Commit

Permalink
Fix Test.assert(Not)ApproxEquals (#435)
Browse files Browse the repository at this point in the history
* Add relevant tests for fixing codewars/codewars.com#962
* Treat 1e-9 as absolute error margin when (un)expected value small enough
  • Loading branch information
DonaldKellett authored and jhoffner committed Jul 12, 2017
1 parent 241a65b commit 48e9f2a
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 4 deletions.
8 changes: 4 additions & 4 deletions frameworks/javascript/cw-2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
162 changes: 162 additions & 0 deletions test/runners/javascript_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
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('<PASSED::>');
expect(buffer.stdout).to.not.contain('<FAILED::>');
expect(buffer.stdout).to.not.contain('<ERROR::>');
done();
});
});
});
});

//----------------------------------------------------------------------------------------
// Karma BDD
Expand Down

0 comments on commit 48e9f2a

Please sign in to comment.