diff --git a/app/src/androidTest/assets/pull_failed b/app/src/androidTest/assets/pull_failed index 845b255de..8a3238df7 100755 --- a/app/src/androidTest/assets/pull_failed +++ b/app/src/androidTest/assets/pull_failed @@ -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 diff --git a/app/src/androidTest/assets/Views/CheckmarkView/checked.png b/app/src/androidTest/assets/views-v21/CheckmarkView/checked.png similarity index 100% rename from app/src/androidTest/assets/Views/CheckmarkView/checked.png rename to app/src/androidTest/assets/views-v21/CheckmarkView/checked.png diff --git a/app/src/androidTest/assets/Views/CheckmarkView/implicitly_checked.png b/app/src/androidTest/assets/views-v21/CheckmarkView/implicitly_checked.png similarity index 100% rename from app/src/androidTest/assets/Views/CheckmarkView/implicitly_checked.png rename to app/src/androidTest/assets/views-v21/CheckmarkView/implicitly_checked.png diff --git a/app/src/androidTest/assets/Views/CheckmarkView/large_size.png b/app/src/androidTest/assets/views-v21/CheckmarkView/large_size.png similarity index 100% rename from app/src/androidTest/assets/Views/CheckmarkView/large_size.png rename to app/src/androidTest/assets/views-v21/CheckmarkView/large_size.png diff --git a/app/src/androidTest/assets/Views/CheckmarkView/unchecked.png b/app/src/androidTest/assets/views-v21/CheckmarkView/unchecked.png similarity index 100% rename from app/src/androidTest/assets/Views/CheckmarkView/unchecked.png rename to app/src/androidTest/assets/views-v21/CheckmarkView/unchecked.png diff --git a/app/src/androidTest/assets/views/CheckmarkView/checked.png b/app/src/androidTest/assets/views/CheckmarkView/checked.png new file mode 100644 index 000000000..7884c804f Binary files /dev/null and b/app/src/androidTest/assets/views/CheckmarkView/checked.png differ diff --git a/app/src/androidTest/assets/views/CheckmarkView/implicitly_checked.png b/app/src/androidTest/assets/views/CheckmarkView/implicitly_checked.png new file mode 100644 index 000000000..3096be180 Binary files /dev/null and b/app/src/androidTest/assets/views/CheckmarkView/implicitly_checked.png differ diff --git a/app/src/androidTest/assets/views/CheckmarkView/large_size.png b/app/src/androidTest/assets/views/CheckmarkView/large_size.png new file mode 100644 index 000000000..79152fb18 Binary files /dev/null and b/app/src/androidTest/assets/views/CheckmarkView/large_size.png differ diff --git a/app/src/androidTest/assets/views/CheckmarkView/unchecked.png b/app/src/androidTest/assets/views/CheckmarkView/unchecked.png new file mode 100644 index 000000000..b0d90c5c0 Binary files /dev/null and b/app/src/androidTest/assets/views/CheckmarkView/unchecked.png differ diff --git a/app/src/androidTest/assets/Views/RingView/render.png b/app/src/androidTest/assets/views/RingView/render.png similarity index 100% rename from app/src/androidTest/assets/Views/RingView/render.png rename to app/src/androidTest/assets/views/RingView/render.png diff --git a/app/src/androidTest/assets/Views/RingView/renderDifferentParams.png b/app/src/androidTest/assets/views/RingView/renderDifferentParams.png similarity index 100% rename from app/src/androidTest/assets/Views/RingView/renderDifferentParams.png rename to app/src/androidTest/assets/views/RingView/renderDifferentParams.png diff --git a/app/src/androidTest/assets/Views/RingView/renderLongLabel.png b/app/src/androidTest/assets/views/RingView/renderLongLabel.png similarity index 100% rename from app/src/androidTest/assets/Views/RingView/renderLongLabel.png rename to app/src/androidTest/assets/views/RingView/renderLongLabel.png diff --git a/app/src/androidTest/java/org/isoron/uhabits/unit/views/CheckmarkViewTest.java b/app/src/androidTest/java/org/isoron/uhabits/unit/views/CheckmarkViewTest.java index e86049d13..1ac8894c8 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/unit/views/CheckmarkViewTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/unit/views/CheckmarkViewTest.java @@ -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"); } } diff --git a/app/src/androidTest/java/org/isoron/uhabits/unit/views/RingViewTest.java b/app/src/androidTest/java/org/isoron/uhabits/unit/views/RingViewTest.java index 06f2ac901..9ac6c1b5b 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/unit/views/RingViewTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/unit/views/RingViewTest.java @@ -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"); } } diff --git a/app/src/androidTest/java/org/isoron/uhabits/unit/views/ViewTest.java b/app/src/androidTest/java/org/isoron/uhabits/unit/views/ViewTest.java index 45344a560..8047435c6 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/unit/views/ViewTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/unit/views/ViewTest.java @@ -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)