Skip to content

Commit 473e416

Browse files
author
Daniel Jette
committed
Merge branch '206-generate-diffs' into testify-ext
2 parents 0c1592b + 7ca15e2 commit 473e416

25 files changed

Lines changed: 292 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#### Changes
88

9+
- FuzzyCompare (setExactness) is now multi-threaded and significantly faster.
910
- TestifyFeatures now support multiple named strings.
1011
- PixelCopyCapture can be enabled using either "testify-experimental-capture" or "testify-pixelcopy-capture" in the AndroidManifest
1112
- Optional constructor argument enableReporter added to ScreenshotRule. Allows you to specify whether to run the reporter for this test rule.
@@ -23,6 +24,7 @@
2324

2425
#### Added
2526

27+
- Added `TestifyFeatures.GenerateDiffs`. When enabled, will output a `.diff.png` alongside existing baseline images. These images are high-contrast images where each difference, regardless of how minor, are indicated in red against a black background. See the `generateDiffs` test in `ScreenshotRuleExampleTests` for an example. Diff images will be pulled from the device when running `screenshotPull`.
2628
- Added method `ScreenshotRule.beforeAssertSame()`. This method is invoked immediately before assertSame and before the activity is launched.
2729
- Added method `ScreenshotRule.beforeInitializeView(activity: Activity)`. This method is invoked prior to any view modifications and prior to layout inflation.
2830
- Added method `ScreenshotRule.afterInitializeView(activity: Activity)`. This method is invoked after layout inflation and all view modifications have been applied.

Library/build.gradle

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ android {
5656
implementation "androidx.test:runner:${versions.androidx.test.runner}"
5757
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
5858
implementation "com.github.ajalt:colormath:${versions.colormath}"
59+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3") {
60+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
61+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
62+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
63+
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
64+
}
5965

6066
testImplementation "org.mockito:mockito-core:${versions.mockito2}"
6167
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:${versions.mockitokotlin}"
@@ -71,4 +77,4 @@ android {
7177
}
7278

7379
apply from: "bintray.build.gradle"
74-
apply from: '../ktlint.gradle'
80+
apply from: '../ktlint.gradle'
49 KB
Loading
49.1 KB
Loading

Library/src/androidTest/java/com/shopify/testify/BitmapCompareTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import android.graphics.Bitmap
3030
import android.view.View
3131
import androidx.test.ext.junit.runners.AndroidJUnit4
3232
import androidx.test.rule.ActivityTestRule
33-
import com.shopify.testify.internal.compare.FuzzyCompare
34-
import com.shopify.testify.internal.compare.SameAsCompare
33+
import com.shopify.testify.internal.processor.compare.FuzzyCompare
34+
import com.shopify.testify.internal.processor.compare.SameAsCompare
3535
import org.junit.Assert.assertFalse
3636
import org.junit.Assert.assertTrue
3737
import org.junit.Before

Library/src/androidTest/java/com/shopify/testify/FuzzyCompareBitmapTest.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ package com.shopify.testify
2828
import android.graphics.Bitmap
2929
import androidx.test.ext.junit.runners.AndroidJUnit4
3030
import androidx.test.rule.ActivityTestRule
31-
import com.shopify.testify.internal.compare.FuzzyCompare
31+
import com.shopify.testify.internal.processor.compare.FuzzyCompare
3232
import org.junit.Assert.assertFalse
3333
import org.junit.Assert.assertTrue
3434
import org.junit.Rule
@@ -70,4 +70,15 @@ class FuzzyCompareBitmapTest {
7070
*/
7171
assertTrue(FuzzyCompare(0.975f).compareBitmaps(baselineBitmap, currentBitmap))
7272
}
73+
74+
/**
75+
* In this test, the baseline & current images are nearly identical where every pixel
76+
* is different, but within the exactness threshold. So, it is required to compare every pixel
77+
*/
78+
@Test
79+
fun compareWorstCase() {
80+
val baselineBitmap = loadBitmap("benchmark_baseline")
81+
val currentBitmap = loadBitmap("benchmark_current")
82+
assertTrue(FuzzyCompare(0.95f).compareBitmaps(baselineBitmap, currentBitmap))
83+
}
7384
}

Library/src/main/java/com/shopify/testify/ScreenshotRule.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ import com.shopify.testify.annotation.TestifyLayout
5252
import com.shopify.testify.internal.DeviceIdentifier
5353
import com.shopify.testify.internal.DeviceIdentifier.DEFAULT_NAME_FORMAT
5454
import com.shopify.testify.internal.TestName
55-
import com.shopify.testify.internal.compare.FuzzyCompare
56-
import com.shopify.testify.internal.compare.RegionCompare
57-
import com.shopify.testify.internal.compare.SameAsCompare
55+
import com.shopify.testify.internal.processor.compare.FuzzyCompare
56+
import com.shopify.testify.internal.processor.compare.RegionCompare
57+
import com.shopify.testify.internal.processor.compare.SameAsCompare
5858
import com.shopify.testify.internal.exception.ActivityNotRegisteredException
5959
import com.shopify.testify.internal.exception.AssertSameMustBeLastException
6060
import com.shopify.testify.internal.exception.MissingAssertSameException
@@ -75,6 +75,7 @@ import com.shopify.testify.internal.modification.HidePasswordViewModification
7575
import com.shopify.testify.internal.modification.HideScrollbarsViewModification
7676
import com.shopify.testify.internal.modification.HideTextSuggestionsViewModification
7777
import com.shopify.testify.internal.modification.SoftwareRenderViewModification
78+
import com.shopify.testify.internal.processor.diff.HighContrastDiff
7879
import com.shopify.testify.internal.output.OutputFileUtility
7980
import com.shopify.testify.report.ReportSession
8081
import com.shopify.testify.report.Reporter
@@ -543,6 +544,13 @@ open class ScreenshotRule<T : Activity> @JvmOverloads constructor(
543544
screenshotUtility.deleteBitmap(activity, outputFileName)
544545
)
545546
} else {
547+
if (TestifyFeatures.GenerateDiffs.isEnabled(activity)) {
548+
HighContrastDiff()
549+
.name(outputFileName)
550+
.baseline(baselineBitmap)
551+
.current(currentBitmap)
552+
.generate(context = activity)
553+
}
546554
if (isRecordMode()) {
547555
instrumentationPrintln(
548556
"\n\t" + 27.toChar() + "[36mRecording baseline for " + testName +

Library/src/main/java/com/shopify/testify/ScreenshotUtility.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ import androidx.test.platform.app.InstrumentationRegistry
3535
import com.shopify.testify.TestifyFeatures.CanvasCapture
3636
import com.shopify.testify.TestifyFeatures.PixelCopyCapture
3737
import com.shopify.testify.internal.DeviceIdentifier
38-
import com.shopify.testify.internal.capture.createBitmapFromCanvas
39-
import com.shopify.testify.internal.capture.createBitmapFromDrawingCache
40-
import com.shopify.testify.internal.capture.createBitmapUsingPixelCopy
38+
import com.shopify.testify.internal.processor.capture.createBitmapFromCanvas
39+
import com.shopify.testify.internal.processor.capture.createBitmapFromDrawingCache
40+
import com.shopify.testify.internal.processor.capture.createBitmapUsingPixelCopy
4141
import com.shopify.testify.internal.exception.ScreenshotDirectoryNotFoundException
4242
import com.shopify.testify.internal.output.OutputFileUtility
4343
import com.shopify.testify.internal.output.OutputFileUtility.Companion.PNG_EXTENSION
@@ -59,7 +59,7 @@ class ScreenshotUtility {
5959
return options
6060
}
6161

62-
private fun saveBitmapToFile(context: Context, bitmap: Bitmap?, outputFilePath: String): Boolean {
62+
fun saveBitmapToFile(context: Context, bitmap: Bitmap?, outputFilePath: String): Boolean {
6363
if (bitmap == null) {
6464
return false
6565
}

Library/src/main/java/com/shopify/testify/TestifyFeatures.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum class TestifyFeatures(internal val tags: List<String>, private val defaultV
3131
ExampleFeature(listOf("testify-example", "testify-alias"), defaultValue = true),
3232
ExampleDisabledFeature(listOf("testify-disabled")),
3333

34+
GenerateDiffs(listOf("testify-generate-diffs"), defaultValue = false),
3435
Locale(listOf("testify-experimental-locale"), defaultValue = true),
3536
CanvasCapture(listOf("testify-canvas-capture")),
3637
PixelCopyCapture(listOf("testify-experimental-capture", "testify-pixelcopy-capture"));
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.shopify.testify.internal.processor
2+
3+
import android.graphics.Bitmap
4+
import kotlinx.coroutines.asCoroutineDispatcher
5+
import java.util.concurrent.Executors
6+
7+
fun ParallelPixelProcessor.TransformResult.createBitmap(): Bitmap {
8+
return Bitmap.createBitmap(
9+
this.pixels,
10+
this.width,
11+
this.height,
12+
Bitmap.Config.ARGB_8888
13+
)
14+
}
15+
16+
val numberOfCores by lazy { Runtime.getRuntime().availableProcessors() }
17+
val executorDispatcher by lazy {
18+
Executors.newFixedThreadPool(numberOfCores).asCoroutineDispatcher()
19+
}

0 commit comments

Comments
 (0)