Add private maxColourDistance for functional tests

Switch MSE-based tests to use it

Remove experimental MSE-based compare API
This commit is contained in:
Lovell Fuller
2015-05-19 17:57:03 +01:00
parent ef8db1eebf
commit 8832ae0bf9
16 changed files with 172 additions and 446 deletions

View File

@@ -83,8 +83,12 @@ describe('Alpha transparency', function() {
.resize(2048, 1536)
.interpolateWith('bicubic')
.toFile(actual, function(err) {
if (err) throw err;
fixtures.assertEqual(actual, expected, done);
if (err) {
done(err);
} else {
fixtures.assertMaxColourDistance(actual, expected, 102);
done();
}
});
});
@@ -96,8 +100,12 @@ describe('Alpha transparency', function() {
.resize(1024, 768)
.interpolateWith('bicubic')
.toFile(actual, function(err) {
if (err) throw err;
fixtures.assertEqual(actual, expected, done);
if (err) {
done(err);
} else {
fixtures.assertMaxColourDistance(actual, expected, 102);
done();
}
});
});

View File

@@ -1,77 +0,0 @@
'use strict';
var assert = require('assert');
var fixtures = require('../fixtures');
var fs = require('fs');
var sharp = require('../../index');
sharp.cache(0);
// Constants
var MAX_ALLOWED_MEAN_SQUARED_ERROR = 0.0005;
// Tests
describe('sharp.compare', function() {
it('should report equality when comparing an image to itself', function(done) {
var image = fixtures.inputPngOverlayLayer0;
sharp.compare(image, image, function (error, info) {
if (error) return done(error);
assert.strictEqual(info.isEqual, true, 'image is equal to itself');
assert.strictEqual(info.status, 'success', 'status is correct');
assert(0 <= info.meanSquaredError &&
info.meanSquaredError <= MAX_ALLOWED_MEAN_SQUARED_ERROR,
'MSE is within tolerance');
done();
});
});
it('should report that two images have a mismatched number of bands (channels)', function(done) {
var actual = fixtures.inputPngOverlayLayer1;
var expected = fixtures.inputJpg;
sharp.compare(actual, expected, function (error, info) {
if (error) return done(error);
assert.strictEqual(info.isEqual, false);
assert.strictEqual(info.status, 'mismatchedBands');
assert(typeof info.meanSquaredError === 'undefined', 'MSE is undefined');
done();
});
});
it('should report that two images have a mismatched dimensions', function(done) {
var actual = fixtures.inputJpg;
var expected = fixtures.inputJpgWithExif;
sharp.compare(actual, expected, function (error, info) {
if (error) return done(error);
assert.strictEqual(info.isEqual, false);
assert.strictEqual(info.status, 'mismatchedDimensions');
assert(typeof info.meanSquaredError === 'undefined', 'MSE is undefined');
done();
});
});
it('should report the correct mean squared error for two different images', function(done) {
var actual = fixtures.inputPngOverlayLayer0;
var expected = fixtures.inputPngOverlayLayer1;
sharp.compare(actual, expected, function (error, info) {
if (error) return done(error);
var meanSquaredError = info.meanSquaredError;
assert.strictEqual(info.isEqual, false);
assert.strictEqual(info.status, 'success');
// ImageMagick reports: 42242.5
// `compare -metric mse 'actual' 'expected' comparison.png`
assert(41900 <= meanSquaredError && meanSquaredError <= 41950,
'Expected: 41900 <= meanSquaredError <= 41950. Actual: ' + meanSquaredError);
done();
});
});
});

26
test/unit/fixtures.js Normal file
View File

@@ -0,0 +1,26 @@
'use strict';
var assert = require('assert');
var fixtures = require('../fixtures');
describe('Test fixtures', function() {
describe('assertMaxColourDistance', function() {
it('should throw an Error when images have a different number of channels', function() {
assert.throws(function() {
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer1, fixtures.inputJpg);
});
});
it('should throw an Error when images have different dimensions', function() {
assert.throws(function() {
fixtures.assertMaxColourDistance(fixtures.inputJpg, fixtures.inputJpgWithExif);
});
});
it('should accept a zero threshold when comparing an image to itself', function() {
var image = fixtures.inputPngOverlayLayer0;
fixtures.assertMaxColourDistance(image, image, 0);
});
it('should accept a numeric threshold for two different images', function() {
fixtures.assertMaxColourDistance(fixtures.inputPngOverlayLayer0, fixtures.inputPngOverlayLayer1, 100);
});
});
});

View File

@@ -1,54 +1,22 @@
'use strict';
var assert = require('assert');
var fixtures = require('../fixtures');
var fs = require('fs');
var sharp = require('../../index');
sharp.cache(0);
// Constants
var MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR = 0.3;
// Helpers
var getPaths = function(baseName, extension) {
if (typeof extension === 'undefined') {
extension = 'png';
}
var actual = fixtures.path('output.' + baseName + '.' + extension);
var expected = fixtures.expected(baseName + '.' + extension);
var expectedMagick = fixtures.expected(baseName + '-imagemagick.' + extension);
return {
actual: actual,
expected: expected,
expectedMagick: expectedMagick
actual: fixtures.path('output.' + baseName + '.' + extension),
expected: fixtures.expected(baseName + '.' + extension),
};
};
var assertEqual = function (paths, callback) {
if (typeof callback !== 'function') {
throw new TypeError('`callback` must be a function');
}
fixtures.assertEqual(paths.actual, paths.expected, function (error) {
if (error) return callback(error);
sharp.compare(paths.actual, paths.expectedMagick, function (error, info) {
if (error) return callback(error);
if (info.meanSquaredError > MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR) {
return callback(new Error('Expected MSE against ImageMagick to be <= ' +
MAX_ALLOWED_IMAGE_MAGICK_MEAN_SQUARED_ERROR + '. Actual: ' +
info.meanSquaredError));
}
callback();
});
});
};
// Test
describe('Overlays', function() {
it('Overlay transparent PNG on solid background', function(done) {
@@ -58,8 +26,8 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer1)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
done();
});
});
@@ -70,8 +38,8 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer1LowAlpha)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
done();
});
});
@@ -82,13 +50,12 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer1)
.toBuffer(function (error, data, info) {
if (error) return done(error);
sharp(data)
.overlayWith(fixtures.inputPngOverlayLayer2)
.toFile(paths.actual, function (error) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
done();
});
});
});
@@ -100,8 +67,8 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer2)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
done();
});
});
@@ -112,8 +79,8 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected, 2);
done();
});
});
@@ -129,8 +96,8 @@ describe('Overlays', function() {
.overlayWith(fixtures.inputPngOverlayLayer2LowAlpha)
.toFile(paths.actual, function (error, data, info) {
if (error) return done(error);
assertEqual(paths, done);
fixtures.assertMaxColourDistance(paths.actual, paths.expected);
done();
});
});
});
@@ -138,11 +105,11 @@ describe('Overlays', function() {
it('Composite transparent PNG onto JPEG', function(done) {
sharp(fixtures.inputJpg)
.overlayWith(fixtures.inputPngOverlayLayer1)
.toBuffer(function (error, data, info) {
.toBuffer(function (error) {
assert.strictEqual(true, error instanceof Error);
if (error.message !== 'Input image must have an alpha channel') {
return done(new Error('Unexpected error: ' + error.message));
}
done();
});
});

View File

@@ -1,6 +1,7 @@
'use strict';
var assert = require('assert');
var fixtures = require('../fixtures');
var sharp = require('../../index');
var defaultConcurrency = sharp.concurrency();