Skip to content

Commit

Permalink
Add roborazzi.compare.output.dir gradle.properties
Browse files Browse the repository at this point in the history
  • Loading branch information
takahirom committed Dec 7, 2024
1 parent 10c66ac commit 19f993e
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ data class RoborazziOptions(
}

data class CompareOptions(
val outputDirectoryPath: String = roborazziSystemPropertyOutputDirectory(),
val outputDirectoryPath: String = roborazziSystemPropertyCompareOutputDirectory(),
val imageComparator: ImageComparator = DefaultImageComparator,
val comparisonStyle: ComparisonStyle = ComparisonStyle.Grid(),
val aiAssertionOptions: AiAssertionOptions? = null,
Expand All @@ -127,7 +127,7 @@ data class RoborazziOptions(
imageComparator: ImageComparator = DefaultImageComparator,
resultValidator: (result: ImageComparator.ComparisonResult) -> Boolean = DefaultResultValidator,
): this(
outputDirectoryPath = roborazziSystemPropertyOutputDirectory(),
outputDirectoryPath = roborazziSystemPropertyCompareOutputDirectory(),
imageComparator = imageComparator,
resultValidator = resultValidator,
)
Expand All @@ -145,7 +145,7 @@ data class RoborazziOptions(
}

constructor(
outputDirectoryPath: String = roborazziSystemPropertyOutputDirectory(),
outputDirectoryPath: String = roborazziSystemPropertyCompareOutputDirectory(),
/**
* This value determines the threshold of pixel change at which the diff image is output or not.
* The value should be between 0 and 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ fun roborazziSystemPropertyOutputDirectory(): String {
return getSystemProperty("roborazzi.output.dir", DEFAULT_ROBORAZZI_OUTPUT_DIR_PATH)
}

@ExperimentalRoborazziApi
fun roborazziSystemPropertyCompareOutputDirectory(): String {
return getSystemProperty("roborazzi.compare.output.dir", DEFAULT_ROBORAZZI_OUTPUT_DIR_PATH)
}

@ExperimentalRoborazziApi
fun roborazziSystemPropertyImageExtension(): String {
return getSystemProperty("roborazzi.record.image.extension", "png")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class AppModule(val rootProject: RoborazziGradleRootProject, val testProjectDir:
private val PATH = "app/build.gradle.kts"
var removeOutputDirBeforeTestTypeTask = false
var customOutputDirPath: String? = null
var customCompareOutputDirPath: String? = null

init {
addIncludeBuild()
Expand Down Expand Up @@ -312,6 +313,19 @@ dependencies {
roborazzi {
outputDir.set(file("$customOutputDirPath"))
}
""".trimIndent()
)
}
if (customCompareOutputDirPath != null) {
buildFile.appendText(
"""
roborazzi {
compare {
outputDir.set(file("$customCompareOutputDirPath"))
}
}
""".trimIndent()
)
}
Expand Down Expand Up @@ -468,6 +482,13 @@ class MainActivity : ComponentActivity() {
file.appendText("\nroborazzi.record.filePathStrategy=relativePathFromRoborazziContextOutputDirectory")
}

fun removeCompareOutputDir() {
if(!testProjectDir.root.resolve("app/build/custom_compare_outputDirectoryPath")
.deleteRecursively()){
throw IllegalStateException("Failed to delete custom_compare_outputDirectoryPath")
}
}

fun addRuleTest() {
val file =
testProjectDir.root.resolve("app/src/test/java/com/github/takahirom/integration_test_project/RoborazziTest.kt")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.junit.rules.TestWatcher
import org.junit.runner.Description

/**
* Run this test with `cd include-build` and `./gradlew roborazzi-gradle-plugin:check`
Expand All @@ -20,6 +21,11 @@ class RoborazziGradleProjectTest {
override fun starting(description: org.junit.runner.Description?) {
println("RoborazziGradleProjectTest.${description?.methodName} started")
}

override fun finished(description: Description?) {
super.finished(description)
println("RoborazziGradleProjectTest.${description?.methodName} finished")
}
}

private val className = "com.github.takahirom.integration_test_project.RoborazziTest"
Expand Down Expand Up @@ -146,15 +152,87 @@ class RoborazziGradleProjectTest {
RoborazziGradleRootProject(testProjectDir).appModule.apply {
val customDirFromGradle = "src/screenshots/roborazzi_customdir_from_gradle"
buildGradle.customOutputDirPath = customDirFromGradle
removeRoborazziOutputDir()
val output1 = record().output
assertNotSkipped(output1)
val output2 = record().output
assertSkipped(output2)

checkResultsSummaryFileExists()
checkRecordedFileExists("app/$customDirFromGradle/$className.testCapture.png")
checkRecordedFileNotExists("$$screenshotAndName.testCapture_compare.png")
checkRecordedFileNotExists("$$screenshotAndName.testCapture_actual.png")
checkRecordedFileNotExists("$screenshotAndName.testCapture.png")
checkRecordedFileNotExists("$screenshotAndName.testCapture_compare.png")
checkRecordedFileNotExists("$screenshotAndName.testCapture_actual.png")
checkRecordedFileNotExists("app/$customDirFromGradle/$className.testCapture_compare.png")

// We should be able to use the cache
changeScreen()
removeRoborazziOutputDir()
compare()
checkRecordedFileExists("$screenshotAndName.testCapture_compare.png")
removeRoborazziOutputDir()
compare()

checkResultsSummaryFileExists()
checkRecordedFileExists("app/$customDirFromGradle/$className.testCapture.png")
checkRecordedFileExists("$screenshotAndName.testCapture_compare.png")
checkRecordedFileExists("$screenshotAndName.testCapture_actual.png")
checkRecordedFileNotExists("app/$customDirFromGradle/$className.testCapture_compare.png")
}
}

@Test
fun compareWithCompareOutputDirPathItShouldSavedInTheDirectory() {
RoborazziGradleRootProject(testProjectDir).appModule.apply {
buildGradle.customCompareOutputDirPath = "build/custom_compare_outputDirectoryPath"

record()
changeScreen()
compare()

checkResultsSummaryFileExists()
checkRecordedFileExists("$screenshotAndName.testCapture.png")
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture_compare.png")
checkRecordedFileNotExists("$screenshotAndName.testCapture_compare.png")

// We should be able to use the cache
removeRoborazziOutputDir()
compare()
removeRoborazziOutputDir()
val buildResult = compare()
assertSkipped(buildResult.output)

checkResultsSummaryFileExists()
checkRecordedFileExists("$screenshotAndName.testCapture.png")
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture_compare.png")
checkRecordedFileNotExists("$screenshotAndName.testCapture_compare.png")
}
}

@Test
fun compareWithBothOutputDirPathItShouldSavedInTheDirectory() {
RoborazziGradleRootProject(testProjectDir).appModule.apply {
buildGradle.customCompareOutputDirPath = "build/custom_compare_outputDirectoryPath"
val customDirFromGradle = "build/custom_compare_outputDirectoryPath"
buildGradle.customOutputDirPath = customDirFromGradle

record()
changeScreen()
compare()

checkResultsSummaryFileExists()
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture.png")
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture_compare.png")
checkRecordedFileNotExists("app/build/outputs/roborazzi/$className.testCapture_compare.png")

// We should be able to use the cache
removeCompareOutputDir()
compare()

checkResultsSummaryFileExists()
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture.png")
checkRecordedFileExists("app/build/custom_compare_outputDirectoryPath/$className.testCapture_compare.png")
checkRecordedFileNotExists("app/build/outputs/roborazzi/$className.testCapture_compare.png")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFile
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
Expand Down Expand Up @@ -49,6 +51,15 @@ private const val DEFAULT_TEMP_DIR = "intermediates/roborazzi"
open class RoborazziExtension @Inject constructor(objects: ObjectFactory) {
val outputDir: DirectoryProperty = objects.directoryProperty()

@ExperimentalRoborazziApi
val compare: RoborazziCompareExtension =
objects.newInstance(RoborazziCompareExtension::class.java)

@ExperimentalRoborazziApi
fun compare(action: Action<RoborazziCompareExtension>) {
action.execute(compare)
}

@ExperimentalRoborazziApi
val generateComposePreviewRobolectricTests: GenerateComposePreviewRobolectricTestsExtension =
objects.newInstance(GenerateComposePreviewRobolectricTestsExtension::class.java)
Expand All @@ -59,6 +70,10 @@ open class RoborazziExtension @Inject constructor(objects: ObjectFactory) {
}
}

open class RoborazziCompareExtension @Inject constructor(objects: ObjectFactory) {
val outputDir: DirectoryProperty = objects.directoryProperty()
}

val KnownImageFileExtensions: Set<String> = setOf("png", "gif", "jpg", "jpeg", "webp")

@Suppress("unused")
Expand Down Expand Up @@ -93,6 +108,8 @@ abstract class RoborazziPlugin : Plugin<Project> {
// For fixing unexpected skip test
val outputDir =
extension.outputDir.convention(project.layout.buildDirectory.dir(DEFAULT_OUTPUT_DIR))
val compareOutputDirProvider =
extension.compare.outputDir.convention(project.layout.buildDirectory.dir(DEFAULT_OUTPUT_DIR))
val testTaskOutputDir: DirectoryProperty = project.objects.directoryProperty()
val intermediateDir =
testTaskOutputDir.convention(project.layout.buildDirectory.dir(DEFAULT_TEMP_DIR))
Expand Down Expand Up @@ -243,11 +260,13 @@ abstract class RoborazziPlugin : Plugin<Project> {
roborazziProperties["roborazzi.test.verify"] == "true" ||
roborazziProperties["roborazzi.test.compare"] == "true"
}
val isCompareOutputIsNeededProvider = isImageInputUsedProvider

val projectAbsolutePathProvider = project.providers.provider {
project.projectDir.absolutePath
}
val outputDirRelativePathFromProjectProvider = outputDir.map { project.relativePath(it) }

val resultDirFileProperty =
project.layout.buildDirectory.dir(RoborazziReportConst.resultDirPathFromBuildDir)
val resultDirFileTree =
Expand All @@ -270,11 +289,6 @@ abstract class RoborazziPlugin : Plugin<Project> {
finalizeTestTask.infoln("Roborazzi: roborazziTestFinalizer.onlyIf doesRoborazziRun $doesRoborazziRun")
doesRoborazziRun
}
val taskPath = if (project.path == ":") {
":"
} else {
project.path + ":"
}
finalizeTestTask.doLast {
val startCopy = System.currentTimeMillis()
intermediateDir.get().asFile.mkdirs()
Expand All @@ -289,12 +303,12 @@ abstract class RoborazziPlugin : Plugin<Project> {
testTaskProvider
.configureEach { test: AbstractTestTask ->
val resultsDir = resultDirFileProperty.get().asFile
test.inputs.files(
isImageInputUsedProvider.map { isImageInputUsed ->
val imageInputProvider: Provider<FileCollection> =
isImageInputUsedProvider.flatMap { isImageInputUsed ->
if (!isImageInputUsed) {
// Note: this is not files in outputDir,
// but empty input when running in record mode.
outputDir.get().files()
outputDir.map { it.files(/* this means empty files*/) }
} else if (restoreOutputDirRoborazziTaskProvider.isPresent) {
// Previous outputs are an input when running in compare or verify mode.
// However, during record runs the output dir might not exist yet, so we use
Expand All @@ -317,7 +331,38 @@ abstract class RoborazziPlugin : Plugin<Project> {
}
}
}
test.inputs.files(
imageInputProvider
)
test.outputs.dirs(
compareOutputDirProvider.flatMap { compareOutputDir: Directory ->
isCompareOutputIsNeededProvider.flatMap { isImageInputUsed ->
imageInputProvider
.map { imageInput: FileCollection ->
if (isImageInputUsed) {
// If it is not compare or verify, we don't need to output anything for comparison
outputDir.files(/* empty files */)
} else if (imageInput.files.any {
// Check if the compare output directory is the same as the input directory
if (it.isDirectory) {
it.absolutePath == compareOutputDir.asFile.absolutePath
} else {
it.parentFile.absolutePath == compareOutputDir.asFile.absolutePath
}
}) {
outputDir.files(/* empty files */)
} else {
if (!compareOutputDir.asFile.exists()) {
compareOutputDir.asFile.mkdirs()
}
compareOutputDir
}
}
}
}.map {
test.infoln("Roborazzi: Set output dir ${it} to test task")
it
})
test.outputs.dir(intermediateDirForEachVariant.map {
test.infoln("Roborazzi: Set output dir $it to test task")
it
Expand Down Expand Up @@ -374,6 +419,10 @@ abstract class RoborazziPlugin : Plugin<Project> {
// Other properties
test.systemProperties["roborazzi.output.dir"] =
outputDirRelativePathFromProjectProvider.get()
if (compareOutputDirProvider.isPresent) {
test.systemProperties["roborazzi.compare.output.dir"] =
compareOutputDirProvider.get()
}
test.systemProperties["roborazzi.result.dir"] =
resultDirRelativePathFromProjectProvider.get()
test.systemProperties["roborazzi.project.path"] =
Expand Down

0 comments on commit 19f993e

Please sign in to comment.