From 53e737c169bca0ea6614e69ff4e5b58c3bd292dc Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Sun, 27 Mar 2016 06:39:40 -0400 Subject: [PATCH] Allow API version-specific view tests; use relative image distance --- app/src/androidTest/assets/pull_failed | 4 +- .../CheckmarkView/checked.png | Bin .../CheckmarkView/implicitly_checked.png | Bin .../CheckmarkView/large_size.png | Bin .../CheckmarkView/unchecked.png | Bin .../assets/views/CheckmarkView/checked.png | Bin 0 -> 5170 bytes .../CheckmarkView/implicitly_checked.png | Bin 0 -> 5387 bytes .../assets/views/CheckmarkView/large_size.png | Bin 0 -> 17527 bytes .../assets/views/CheckmarkView/unchecked.png | Bin 0 -> 5589 bytes .../{Views => views}/RingView/render.png | Bin .../RingView/renderDifferentParams.png | Bin .../RingView/renderLongLabel.png | Bin .../uhabits/unit/views/CheckmarkViewTest.java | 8 +- .../uhabits/unit/views/RingViewTest.java | 6 +- .../isoron/uhabits/unit/views/ViewTest.java | 89 ++++++++++++------ 15 files changed, 70 insertions(+), 37 deletions(-) rename app/src/androidTest/assets/{Views => views-v21}/CheckmarkView/checked.png (100%) rename app/src/androidTest/assets/{Views => views-v21}/CheckmarkView/implicitly_checked.png (100%) rename app/src/androidTest/assets/{Views => views-v21}/CheckmarkView/large_size.png (100%) rename app/src/androidTest/assets/{Views => views-v21}/CheckmarkView/unchecked.png (100%) create mode 100644 app/src/androidTest/assets/views/CheckmarkView/checked.png create mode 100644 app/src/androidTest/assets/views/CheckmarkView/implicitly_checked.png create mode 100644 app/src/androidTest/assets/views/CheckmarkView/large_size.png create mode 100644 app/src/androidTest/assets/views/CheckmarkView/unchecked.png rename app/src/androidTest/assets/{Views => views}/RingView/render.png (100%) rename app/src/androidTest/assets/{Views => views}/RingView/renderDifferentParams.png (100%) rename app/src/androidTest/assets/{Views => views}/RingView/renderLongLabel.png (100%) 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 0000000000000000000000000000000000000000..7884c804f513594b4b3b9e2b4b966f2199c94116 GIT binary patch literal 5170 zcmcIobyQT*x4s|C&lfdSc|trIJOBU)72e2bfX_s*HQ?R{?;-qF z{|s0z(h6F*;PnC5A`}3~HWXxDX?dpa%=>t1!ZKSA7J3y1S#9Fjnik4y5QyQ?L=8N> zY$mmrSn3_JljIrdIBten6P*)YlScC+aJms{H+p(mr-{WSLSkYp5_q(2eNDV^PW+E! zzoC;SR(H4?O*J-0LMoS6*DFU)BqU-ThptxB8`%Ne$IF}ryLXp2lQitRIL?%BTd1%A zCitlz(^(+&G4peX3|4SZXln&A2^9r1X1lbEsa_~90Y1s6|3BlmLDZ*S)dBc;Uvgnd z?BbJryKhW!Kw}4)xlFi=Gbve~vJx>|B`^_`-sL!Lj$q%+(7D z;YXsqj$_r!9|!d}VBvUxe=bK)L?oK1?8+)46#KzFh{9eg+H95Dcmw?FpHo8f9BYU2isGZqb$@cqo z6ndy71s*S{fWGipPb`#eL0bjgS1m07 z5W_pHC0gKkOqF==#?tcpHMz9<4n(}z_n>?47hN+{`Z)yWV&ISR1tTT5CNEa*<@%ET ze3x&-ENJ^Y#|a5imK%5&5zXp(C3-v2^hMs%k~m^Bt9f=}bDxlGRn%%OxRT2%=&<=) ziu2oG1OVXCZUwP7OANc8I~T?*@A+C-247DE)l+FpIlwz+U9Rq*segeo=8c*Ziu9O$a_r7LrMzWItq7%tkWR{*?MqimR<4cxe*-OcgnXfAP>Wq?*__6e@|4f#q3&J5suf|+2-x% z5ZRqNjpYYHs#Vd|x~yclcb=&AK`yc=R?W2BoeC=^*_9bJwSp2$`nPfiM%n%X213!pHZ2 zZx|^=ormc(QUQ1`iNf8Mx&-yX?qUT{0_R$g;6WShsh|v zXp)?^6_m^|LjXI&`i37rh55O^7KI=KvH#B1Juhko{}W)XBS@Wa*&T}U)e+3d-#I>r ze`Z~z2`eQSqrgu>{8pN&uz8E6wgQL2(soQHGVrtb&xiP}m2jvQ3;)wLOebYSG5jH0 z-lCWk0dN+sGWwv4ce)J;(fle!6@VP&RAk$Sou(^yb1nB|S186bQN6h$z+eTm%#|@6wgpM$Oqd5GyDtI_D_G@qYOWH1_BK2DWA@rS?z01zSJ zy%#BLht7wShG7E!L5m~r@4C$eQLfo-aYCsB`);z8V=Y)@Cr+2kH`1?59{@~(Ox7>; zj$SkC0f73W#}Z7Qt>|zTGrh3f>>7lE_2@>&Z4}EI92~A}9|6A^r@j`*@|V178zy~& zk86n)jvbap8zjRhwXxJgwVKusoB!#ejE@@wrg+9gPOad*gOhNch5n|uZpezMY~iA_ zLHJDOP59~Pu%>{d0ML4-oup#Krs>hT$eCcFt&Ew!>Z#x+-{57UACsesgi-gp|8qV* z>BaoFt*Z1wde4@zui0uTsp!J0L^&6IrD|$`Nv<@g*&QyJ^#iJb$tf7P;8y2>mcCuJ(~st^_;ob9 z5efa!36WiDc@{w{jn$q#+r_2Qg0XWNC%^F590vjrK)qiPOF??3Za0V5c35U!u(oSl zP1%oj*nIfbU8X}tq!TZIWbiRRP+VEvD8y6c-174af!CkUrf6miWr*`_i}iy_lB11nof#bei4b1a23MU%|UmU(EKoCQr@6>U5AWkToLJQ7(jYiy{)J> zV$SKUG@sOqCnZBpRK=$;VY#?h{XA}Wh|9i}ab3H;iNNB<^}|HABi)rG*PZ(T$=j41 z1`PDw63OXh)`IID`H==DC23w(Gq&34UGncHP?o6aEiqTg9;4z}0sHTUJh)4zpG{nK zk+Xk#Z$DLm+_yVZf}N@2T?#`oISSChRNgbc)g(PHInFIBLG;q)9OmkFK5??acw7~w zJC9IZxYc1PT#(REeTWZaXXgw)S}M$~mTsdq(5nt8C800jnE0sw&f@%NNqb2k3((JQ z)6@V7RG*5XlS4o9*W`#Lw}Zp>E&h$0b1<{vimb_&HNVxiXK~Ki+}24tc^_9{N|+mb z?0m7!TbT8=pOqnLIVIM?r`K7vIvzg^06^!hg6W=$atuBN{`Tuq z0sBWMG-UoKA4vV(xJk+nVt&vbFJ;DJ`ZkO(txjpDQKbfp<+H&7;7FQ<8nBCR`g!6e z`^694Y{Zpzy5q1Tm9wC0T!I7O9;=~_@5DN#)GphuI~Bun{{}HexzQDI>@e8g!Muyo zb2)^a5r2loI065K4DneTVysXdpD~5z+m2i7@YKy9lsX2m{ghkaTFYku7pM>w`n|D+ zX6qo?nx4Qz^Se|%9_hX`o1@O^7$JRdZK!KLo>Fo&OQxL=ToR3I3DtYlz_k}I)G77y z{xBIr1$APZb2e~yvx4`frR_Cyo{btG1RHpHmg#x2)ae{sn(~ullKs!$CgIG>s+u=< z3;B^ACw_whj9ZOm6WP`86$awZ7UYslt12`KpP-Psvv-YjHu7chw0r^W$xmq*^IOVP z7chXWfh#0|H*bfgf_%~V@pbeY3gE9EO!h3s%uyldc7fmVAf2454FHszNER!L$?rK_ zW-V{=+|17fF&s%V>q*sjheq{56?ra$E|lT{z%m^Bc5A#6qa6{3ehT=XXj<)WFK&4cu|(4m;o>f^}rUBU&9h_dm4`l2dlnqAh$l-AsI-x-8_ICE=W zyv)vj`DT-kMg{;10~z*ABw7O>Y$aX38{7W-+!8ADXltOKl`;)XZ=5sWKUS;V^@fMA zg_k!aX++?Wkt5aql7yg7W=Of=C?h=U&h=Dg8bGJZF$WO*^1goMC9vT61J zmE`U9U&^Yh{_Qz2`xVxV@B}`jx&-jH=w&e%BIt(engFOkjVoKC1@& zOIAZ+;abs0V_{c2!u8myD6*XE%shM)S~aT9Nr) z!)QsrpLwnQ6z5DFco4M;0H;YJcfU3Qsqw%yUVU09OC<0d4enH)QYf?qp41)f? z7c&Va^@3S-vsz^TXAfR_>Tb?3!^fX*A;)TTg3$@vju`u@Ha;gwK zbkIe(#1BhLpVg^}WJ|yOB)NZO8Gb~3FM@B=(6>|#wRvq9xPKh}3LvxQaIN8vQxNw% z;XC+woo`p947RRgAH~$PKdb{P?(!orzAre>6xo)OJX8yEi0dDM>UQzR>m0FPbF*fW zZl$B1h4mvFYlXo9(E4bPp|y?l8+dX|TMqGmDt9Li*NSm}rVX+UeTEFVIM}zWQV)60 z4(AHogj7^?^q&P1Df^xwTb29&tLXok(THqN^!ir(-M%=cSZo$TNwXPv+-hp0DnsB? znm5px_jlWWC>jI!hI3!3$t%dBKzj%!{uY4~jMDpHAXtPyLl$8W3>)Hv`RJ-3byz;C zd#js_k28sj*ky)jF@Ivw?IU;{_0(2$mg~1;v)0tzLAOTrqajPK{q5&8 z9s56x8TRX*IX6^n>m$Sywa5Nxgt>Lkvc_6{>rr=oRc#acL(ThlKBw$EAn}GVy+v3U zT?;r&AwElDaDVv<#VE<*q~GSZEbA$4tMW)V)YDPH@$wvf%OEy=x|tH!UgkLnLeOEE zE-n9O>6BY&P_b6*qmNq|?vhVM*GQA>T<+ub&Vz)5 z#6NTc040{v;#g1@iuz&%veawq<$=-7YLA`TzM$!FSZKRRhj+bCr?sqe9x-dXwaEC)lbS<$OeM+Mnf?OJ>IiFzYUf))FhnB-NR+j*ALF56fz<&f- literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3096be18064061aecdad6afd8bf7123e301cf9b5 GIT binary patch literal 5387 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 WnX4_z?gD*U=&^#jeC|WD7yki@aQF%U literal 0 HcmV?d00001 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)