Allow API version-specific view tests; use relative image distance

pull/77/merge
Alinson S. Xavier 10 years ago
parent 285f79ed95
commit 53e737c169

@ -1,5 +1,5 @@
#!/bin/bash
P=/sdcard/Android/data/org.isoron.uhabits/cache/Failed/
adb pull $P
adb shell rm -rf $P
adb pull $P Failed/
adb shell rm -r $P

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

@ -53,7 +53,7 @@ public class CheckmarkViewTest extends ViewTest
@Test
public void render_checked() throws IOException
{
assertRenders(view, "Views/CheckmarkView/checked.png");
assertRenders(view, "CheckmarkView/checked.png");
}
@Test
@ -62,7 +62,7 @@ public class CheckmarkViewTest extends ViewTest
habit.repetitions.toggle(DateHelper.getStartOfToday());
view.refreshData();
assertRenders(view, "Views/CheckmarkView/unchecked.png");
assertRenders(view, "CheckmarkView/unchecked.png");
}
@Test
@ -75,13 +75,13 @@ public class CheckmarkViewTest extends ViewTest
habit.repetitions.toggle(today - 2 * day);
view.refreshData();
assertRenders(view, "Views/CheckmarkView/implicitly_checked.png");
assertRenders(view, "CheckmarkView/implicitly_checked.png");
}
@Test
public void render_largeSize() throws IOException
{
measureView(dpToPixels(300), dpToPixels(300), view);
assertRenders(view, "Views/CheckmarkView/large_size.png");
assertRenders(view, "CheckmarkView/large_size.png");
}
}

@ -52,7 +52,7 @@ public class RingViewTest extends ViewTest
public void render_base() throws IOException
{
measureView(dpToPixels(100), dpToPixels(100), view);
assertRenders(view, "Views/RingView/render.png");
assertRenders(view, "RingView/render.png");
}
@Test
@ -61,7 +61,7 @@ public class RingViewTest extends ViewTest
view.setLabel("The quick brown fox jumps over the lazy fox");
measureView(dpToPixels(100), dpToPixels(100), view);
assertRenders(view, "Views/RingView/renderLongLabel.png");
assertRenders(view, "RingView/renderLongLabel.png");
}
@Test
@ -73,6 +73,6 @@ public class RingViewTest extends ViewTest
view.setColor(ColorHelper.palette[5]);
measureView(dpToPixels(200), dpToPixels(200), view);
assertRenders(view, "Views/RingView/renderDifferentParams.png");
assertRenders(view, "RingView/renderDifferentParams.png");
}
}

@ -37,7 +37,8 @@ import static junit.framework.Assert.fail;
public class ViewTest
{
protected static final int SIMILARITY_CUTOFF = 6000;
protected static final double SIMILARITY_CUTOFF = 0.02;
public static final int HISTOGRAM_BIN_SIZE = 8;
protected Context testContext;
protected Context targetContext;
@ -61,37 +62,39 @@ public class ViewTest
protected void assertRenders(View view, String expectedImagePath) throws IOException
{
StringBuilder errorMessage = new StringBuilder();
expectedImagePath = getVersionedViewAssetPath(expectedImagePath);
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap actual = view.getDrawingCache();
Bitmap expected = getBitmapFromAssets(expectedImagePath);
Bitmap actualBitmap = view.getDrawingCache();
Bitmap expectedBitmap = getBitmapFromAssets(expectedImagePath);
Bitmap scaledExpectedBitmap = Bitmap.createScaledBitmap(expectedBitmap,
actualBitmap.getWidth(), actualBitmap.getHeight(), false);
int width = actual.getWidth();
int height = actual.getHeight();
Bitmap scaledExpected = Bitmap.createScaledBitmap(expected, width, height, true);
double distance;
boolean similarEnough = true;
long distance;
if ((distance = compareHistograms(getHistogram(actualBitmap), getHistogram(
scaledExpectedBitmap))) > SIMILARITY_CUTOFF)
if ((distance = compareHistograms(getHistogram(actual), getHistogram(scaledExpected))) > SIMILARITY_CUTOFF)
{
similarEnough = false;
errorMessage.append(String.format(
"Rendered image has wrong histogram (distance=%d). ",
"Rendered image has wrong histogram (distance=%f). ",
distance));
}
if(!similarEnough)
{
String path = saveBitmap(expectedImagePath, actualBitmap);
saveBitmap(expectedImagePath, ".scaledExpected", scaledExpected);
String path = saveBitmap(expectedImagePath, ".actual", actual);
errorMessage.append(String.format("Actual rendered image " + "saved to %s", path));
fail(errorMessage.toString());
}
actualBitmap.recycle();
expectedBitmap.recycle();
scaledExpectedBitmap.recycle();
actual.recycle();
expected.recycle();
scaledExpected.recycle();
}
private Bitmap getBitmapFromAssets(String path) throws IOException
@ -100,11 +103,35 @@ public class ViewTest
return BitmapFactory.decodeStream(stream);
}
private String saveBitmap(String filename, Bitmap bitmap)
private String getVersionedViewAssetPath(String path)
{
String result = null;
if (android.os.Build.VERSION.SDK_INT >= 21)
{
try
{
String vpath = "views-v21/" + path;
testContext.getAssets().open(vpath);
result = vpath;
}
catch (IOException e)
{
// ignored
}
}
if(result == null)
result = "views/" + path;
return result;
}
private String saveBitmap(String filename, String suffix, Bitmap bitmap)
throws IOException
{
String absolutePath = String.format("%s/Failed/%s", targetContext.getExternalCacheDir(),
filename.replaceAll("\\.png$", ".actual.png"));
filename.replaceAll("\\.png$", suffix + ".png"));
new File(absolutePath).getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(absolutePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
@ -114,7 +141,7 @@ public class ViewTest
private int[][] getHistogram(Bitmap bitmap)
{
int histogram[][] = new int[4][256];
int histogram[][] = new int[4][256 / HISTOGRAM_BIN_SIZE];
for(int x = 0; x < bitmap.getWidth(); x++)
{
@ -128,29 +155,35 @@ public class ViewTest
(color ) & 0xff //blue
};
histogram[0][argb[0]]++;
histogram[1][argb[1]]++;
histogram[2][argb[2]]++;
histogram[3][argb[3]]++;
histogram[0][argb[0] / HISTOGRAM_BIN_SIZE]++;
histogram[1][argb[1] / HISTOGRAM_BIN_SIZE]++;
histogram[2][argb[2] / HISTOGRAM_BIN_SIZE]++;
histogram[3][argb[3] / HISTOGRAM_BIN_SIZE]++;
}
}
return histogram;
}
private long compareHistograms(int[][] actualHistogram, int[][] expectedHistogram)
private double compareHistograms(int[][] actualHistogram, int[][] expectedHistogram)
{
long distance = 0;
long diff = 0;
long total = 0;
for(int i = 0; i < 255; i ++)
for(int i = 0; i < 256 / HISTOGRAM_BIN_SIZE; i ++)
{
distance += Math.abs(actualHistogram[0][i] - expectedHistogram[0][i]);
distance += Math.abs(actualHistogram[1][i] - expectedHistogram[1][i]);
distance += Math.abs(actualHistogram[2][i] - expectedHistogram[2][i]);
distance += Math.abs(actualHistogram[3][i] - expectedHistogram[3][i]);
diff += Math.abs(actualHistogram[0][i] - expectedHistogram[0][i]);
diff += Math.abs(actualHistogram[1][i] - expectedHistogram[1][i]);
diff += Math.abs(actualHistogram[2][i] - expectedHistogram[2][i]);
diff += Math.abs(actualHistogram[3][i] - expectedHistogram[3][i]);
total += actualHistogram[0][i];
total += actualHistogram[1][i];
total += actualHistogram[2][i];
total += actualHistogram[3][i];
}
return distance;
return (double) diff / total / 2;
}
protected int dpToPixels(int dp)

Loading…
Cancel
Save