Skip to content

Releases: takahirom/roborazzi

1.15.0

07 May 01:20
bcee2ce
Compare
Choose a tag to compare

Improvements

  • Resolved a Race Condition in Roborazzi Gradle Integration Tests: In version 1.14.0, we identified an intermittent issue where images from Roborazzi did not always appear in the output directory during certain test scenarios, particularly when test results were cached. Despite efforts to resolve this in 1.14.0, the issue persisted due to its elusive nature. In this release, we have successfully addressed this problem, ensuring that images are now consistently placed in the output directory under similar conditions. This improvement has been verified through our integration tests. This issue may occur in user projects, so we recommend updating to this version.
    We continue to refine our testing processes to prevent similar issues in future releases.

What's Changed

  • Update CompileSdk 34 by @takahirom in #344
  • Add debug code for flaky test by @takahirom in #346
  • Fix issue where finalizedTask is skipped unexpectedly by @takahirom in #347
  • Improve performance for race condition workaround by @takahirom in #348
  • Improve performance for race condition workaround2 by @takahirom in #349
  • [CI]Pin dependencies by @renovate in #329
  • [CI]Update actions/checkout action to v3.6.0 by @renovate in #334
  • [CI]Update actions/setup-java action to v3.13.0 by @renovate in #335
  • [CI]Update dawidd6/action-download-artifact action to v2.28.0 by @renovate in #338
  • [Sample]Update dependency androidx.appcompat:appcompat to v1.6.1 by @renovate in #339
  • [Sample]Update dependency androidx.constraintlayout:constraintlayout to v2.1.4 by @renovate in #330

Full Changelog: 1.14.0...1.15.0

1.14.0

04 May 04:35
b9dedca
Compare
Choose a tag to compare

Bug fixes

Cache-related Flakiness in Comparison Results: We've identified and resolved an intermittent issue where cached data could sometimes prevent users from seeing comparison results in Roborazzi.
#323

What's Changed

New Contributors

Full Changelog: 1.13.0...1.14.0

1.13.0

20 Apr 01:03
d59cede
Compare
Choose a tag to compare

Add experimental, minimal support for iOS in Compose Multiplatform

Roborazzi has supported Compose Desktop, but we hadn't yet supported iOS, which could be a major use case for Compose Multiplatform. Therefore, I have added support for iOS.
Now, you can record, compare, and verify just as you would with Android support.
https://takahirom.github.io/roborazzi/compose-multiplatform.html#experimental-feature-ios-support

ios_button_compare

However, Roborazzi is fundamentally based on the JVM. Currently, we offer only minimal features. If you are interested in helping to improve these features, please take a look at these issues:
#302 #305

Changes Affecting Existing Support

To support iOS, we have made some dependency changes for Android and Compose Desktop. I believe these changes will not affect existing behavior. However, if you notice anything, please let me know.

All
Kotlin:
1.8.22 -> 1.9.21

dropbox/differ:
0.0.1 -> 0.0.2

Desktop Compose Version

Compose Multiplatform:
1.4.3 -> 1.6.1

What's Changed

Full Changelog: 1.12.0...1.13.0

1.12.0

11 Apr 23:28
20aeee1
Compare
Choose a tag to compare

Bug Fixes

  • Fixed an issue where recorded images with a transparent background and a scaling option (e.g., 0.5F) were always detected as changes. Thanks for reporting this, @yongsuk44!
  • Addressed a bug related to robolectric.screenshot.hwrdr.native introduced in Robolectric 4.12, which caused unwanted shadows when using Compose's roboCaptureImage{} with this new option. This has now been corrected by @lukas-mercari. Thanks for your contribution!

What's Changed

  • Hide action bar to avoid shadow creeping into images captured using captureRoboImage by @lukas-mercari in #283
  • [CI]Compare with base branch by @takahirom in #284
  • update robolectric version from 4.10.3 to 4.12.1 by @sanao1006 in #289
  • Add roundTransparentResizeCompose test by @takahirom in #297
  • Fix false positive issue in verification of scaled transparent images by @takahirom in #298

New Contributors

Full Changelog: 1.11.0...1.12.0

1.11.0

18 Mar 02:22
08af633
Compare
Choose a tag to compare

New feature

In Roborazzi, if you specify outputDir in the Gradle settings, you can use the build cache. Now, Roborazzi passes the setting into the test.

build.gradle

roborazzi {
    outputDir = "src/your/screenshot/folder"
}

gradle.propeties

roborazzi.record.filePathStrategy=relativePathFromRoborazziContextOutputDirectory 

Test

captureRoboImage()
-> saved src/your/screenshot/folder/package.class.method.png


captureRoboImage("test.png")

-> saved src/your/screenshot/folder/test.png

What's Changed

  • Add helpful error message for class cast exception by @takahirom in #267
  • Use 'verify' task when specifying both 'compare' and 'verify' by @takahirom in #269
  • Respect gradle build dir for reports by @takahirom in #270
  • Add "The images taken from Roborazzi seem broken" FAQ by @takahirom in #277

Full Changelog: 1.10.1...1.11.0

1.10.1

18 Feb 08:01
bd23cf7
Compare
Choose a tag to compare

Changes from 1.10.0

This release includes a bug fix for a Javascript error that prevented the HTML report from being displayed.

Changes from 1.9.0

New experimental feature

Custom context data for images and reports

Custom context data enables the addition of information to images and reports in Roborazzi's tests, which I believe is very important. For example, it can include the test class name of a screenshot or whether it is in dark mode.
You can now add custom context data using RoborazziOptions, and Roborazzi will add the test class name metadata if you use RoborazziRule. If you have any opinions about this feature, please let me know at #257.
Furthermore, this opens up possibilities with AI. Given that AI now possesses multimodal capabilities, it has become feasible for AI to process images.
This feature was made possible thanks to @sanao1006 's contribution of migrating from org.json to gson.

    onView(ViewMatchers.isRoot())
      .captureRoboImage(
        roborazziOptions = RoborazziOptions(
          contextData = mapOf(
            "context_data_key" to "context_data_value"
          )
        )
      )
  }
image

Important bug fix

Gradle attempts to load the test cache whenever possible, but there was an issue where Roborazzi couldn't restore images from the cache. This release includes a fix for this problem. Thank you, @francescocervone, for reporting this issue.

What's Changed

New Contributors

Full Changelog: 1.9.0...1.10.0

1.10.0

18 Feb 02:23
4a90856
Compare
Choose a tag to compare

New experimental feature

Custom context data for images and reports

Custom context data enables the addition of information to images and reports in Roborazzi's tests, which I believe is very important. For example, it can include the test class name of a screenshot or whether it is in dark mode.
You can now add custom context data using RoborazziOptions, and Roborazzi will add the test class name metadata if you use RoborazziRule. If you have any opinions about this feature, please let me know at #257.
Furthermore, this opens up possibilities with AI. Given that AI now possesses multimodal capabilities, it has become feasible for AI to process images.
This feature was made possible thanks to @sanao1006 's contribution of migrating from org.json to gson.

    onView(ViewMatchers.isRoot())
      .captureRoboImage(
        roborazziOptions = RoborazziOptions(
          contextData = mapOf(
            "context_data_key" to "context_data_value"
          )
        )
      )
  }
image

Important bug fix

Gradle attempts to load the test cache whenever possible, but there was an issue where Roborazzi couldn't restore images from the cache. This release includes a fix for this problem. Thank you, @francescocervone, for reporting this issue.

What's Changed

New Contributors

Full Changelog: 1.9.0...1.10.0

1.9.0

26 Jan 09:28
89c2286
Compare
Choose a tag to compare

Announcement: Simplified Release Strategy for Roborazzi

We're making some changes to our release strategy to enhance your experience. Moving forward, we will be streamlining our versioning system. Instead of maintaining separate alpha/rc/stable versions, we will integrate experimental features directly into stable releases, marked with clear experimental annotations. This approach aims to simplify updates and improve clarity while ensuring you still have access to the latest features and improvements.

We value your input and experience. If you have any thoughts or feedback on this change, please feel free to share them with us on GitHub Issue #243.

New Experimental Features

  • Introduction of captureScreenRoboImage() Function:
    This function executes screenshot tests that include dialogs on the screen, offering an alternative to the conventional use of Espresso's ViewInteraction or Compose Test's SemanticsNodeInteraction captureRoboImage(). Thank you, @nelletto, for bringing this issue with dialog screenshots to our attention.

    Before:

    onRoot().captureRoboImage()
    onView(isRoot()).captureRoboImage()

    After:

    captureScreenRoboImage()
image
  • RoborazziTaskType Property:
    I developed Roborazzi to facilitate layout viewing during UI tests, addressing the limitations in Robolectric's layout visibility. Initially, Roborazzi couldn't support just viewing layouts during the verification task (roborazziVerifyDebug). Hence, I've introduced a feature allowing task type alteration during test executions.

    onView(ViewMatchers.isRoot())
      .captureRoboImage(
        roborazziOptions = RoborazziOptions(
          taskType = roborazziSystemPropertyTaskType().convertVerifyingToComparing()
        )
      )

Behavior Changes

  • Adjustments for Upcoming Robolectric Shadow Rendering Support:
    While Robolectric is in the process of introducing technical support for shadow rendering, Roborazzi is adapting its screenshot capture method accordingly. We're shifting towards using the PixelCopy class more extensively instead of relying solely on the View draw method. If you notice any issues with this change, please report them to us. Thank you, @sergio-sastre, for highlighting the advantages of using PixelCopy.

Bug Fixes

  • Fixed Potential Memory Leak:
    Addressed a memory leak issue occurring when using compose captureRoboImage{} multiple times within a single test. (Thanks for reporting this @vetoketju )
  • Resolved File Path Duplication:
    Corrected an issue where not specifying a file path with relativePathFromRoborazziContextOutputDirectory resulted in duplicated file paths, like build/output/roborazzi/build/output/roborazzi/xxxx.png.
  • Fixed a bug in window ordering for screenshots: Windows are now accurately layered by type for more reliable and consistent screenshot results.
  • Fixed the issue where captureScreenRoboImage() failed to capture Material3 Compose dialogs and bottom sheets.
    @marianeum Thank you for reporting this issue!
  • Resolved the issue causing comparison images to enlarge when using the scale option.

Others

  • Documentation Enhancement:
    Added comprehensive documentation using Writerside, a documentation tool from JetBrains.
    Roborazzi Documentation
    Thank you, @timothyfroehlich, @sergio-sastre, and @ZacSweers, for your suggestions regarding documentation tools.

  • Thanks to @itochan's contribution, Roborazzi has moved to a version catalog, reduced unwanted dependencies and organized

  • Enhanced performance.

  • Fix Bug Causing Comparison Image to Enlarge and Enhance Performance by Avoiding Creation of Unnecessary Canvases

  • Use ComposeTestRule interface instead of concrete AndroidComposeTestRule class by @GisoBartels in #241

  • Pass the default output directory setting from Gradle

What's Changed

New Contributors

Full Changelog: 1.8.0...1.9.0

1.8.0

22 Jan 01:27
17046b8
Compare
Choose a tag to compare

Announcement: Simplified Release Strategy for Roborazzi

We're making some changes to our release strategy to enhance your experience. Moving forward, we will be streamlining our versioning system. Instead of maintaining separate alpha/rc/stable versions, we will integrate experimental features directly into stable releases, marked with clear experimental annotations. This approach aims to simplify updates and improve clarity while ensuring you still have access to the latest features and improvements.

We value your input and experience. If you have any thoughts or feedback on this change, please feel free to share them with us on GitHub Issue #243.

Fix from 1.8.0-rc-1

  • Use ComposeTestRule interface instead of concrete AndroidComposeTestRule class.
    @GisoBartels, Thank you for your code contribution!
    #241

New Feature from 1.7

Introducing the experimental roboOutputName() function

Streamline the customization of Roborazzi image file names. This utility is especially effective in parameterized tests, allowing for dynamic file naming based on test parameters. For an example of its usage, see the snippet below, which demonstrates generating screenshots before and after UI interactions.

@Test
fun launchScreen() {
  // Generates a file named "org.your.pkg.TestClassName.launchScreen_before.png"
  onView(ViewMatchers.isRoot()).captureRoboImage("${roboOutputName()}_before.png")
  // Replace with specific actions, e.g., onView(xxx).performClick()
  
  // Generates a file named "org.your.pkg.TestClassName.launchScreen_after.png"
  onView(ViewMatchers.isRoot()).captureRoboImage("${roboOutputName()}_after.png")
}

Tailor your file naming convention in gradle.properties for even more control, such as omitting the package name.
Set roborazzi.record.namingStrategy=testClassAndMethod for a streamlined naming pattern.
Learn more: Roborazzi Documentation

Enhanced Comparison with Grid and Labels ๐Ÿš€

This update introduces a new grid and label feature, making visual comparisons more intuitive and effective. The grid layout provides a structured view, while labels offer clear identification, streamlining the testing process.

You can use the old style by setting ComparisonStyle to ComparisonStyle.Simple in RoborazziOptions

  data class CompareOptions(
...
    val comparisonStyle: ComparisonStyle = ComparisonStyle.Grid(),
  ) {
    @ExperimentalRoborazziApi
    sealed interface ComparisonStyle {
      @ExperimentalRoborazziApi
      data class Grid(
        val bigLineSpaceDp: Int? = 16,
        val smallLineSpaceDp: Int? = 4,
        val hasLabel: Boolean = true
      ) : ComparisonStyle

      object Simple : ComparisonStyle
    }

image

Make Roborazzi's ImageComparator customizable.

You can now modify the ImageComparator using CompareOptions.imageComparator.

Behavior changes ๐Ÿ”ง

Set the default value of CompareOptions.changeThreshold to zero. This means it will detect even a single pixel change.

What's Changed

  • Make Roborazzi's ImageComparator customizable by @takahirom in #182
  • Set Default Value of CompareOptions.changeThreshold to Zero by @takahirom in #183
  • Fixed a bug where options set via RoborazziRule were ignored by @takahirom in #187
  • Fix the issue of keeping the previous test reports by @takahirom in #189
  • [CI]Speed up integration tests by @takahirom in #190
  • Refactor processOutputImageAndReport by @takahirom in #191
  • Fix the bug where the test reports are not updated when the tests fail by @takahirom in #194
  • Add a document about experimental output parameter by @takahirom in #195
  • Migrate Robolectric to gradle version catalog by @takahirom in #196
  • Add default parameter for CompareOptions.resultValidator by @takahirom in #203
  • Enhance Flexibility with Custom File Naming in Roborazzi via roboOutputName() Function by @takahirom in #205
  • Fix the issue where errors are ignored and occur when changing the size during GIF recording. by @takahirom in #210
  • Add labels and grid lines for the comparison image by @takahirom in #206
  • Fix simple comparison image by @takahirom in #213

Full Changelog: 1.7.0...1.8.0

1.8.0-rc-2

09 Jan 12:02
96d1840
Compare
Choose a tag to compare

Fix from 1.8.0-rc-1

  • Use ComposeTestRule interface instead of concrete AndroidComposeTestRule class.
    @GisoBartels, Thank you for your code contribution!
    #241

New Feature from 1.7

Introducing the experimental roboOutputName() function

Streamline the customization of Roborazzi image file names. This utility is especially effective in parameterized tests, allowing for dynamic file naming based on test parameters. For an example of its usage, see the snippet below, which demonstrates generating screenshots before and after UI interactions.

@Test
fun launchScreen() {
  // Generates a file named "org.your.pkg.TestClassName.launchScreen_before.png"
  onView(ViewMatchers.isRoot()).captureRoboImage("${roboOutputName()}_before.png")
  // Replace with specific actions, e.g., onView(xxx).performClick()
  
  // Generates a file named "org.your.pkg.TestClassName.launchScreen_after.png"
  onView(ViewMatchers.isRoot()).captureRoboImage("${roboOutputName()}_after.png")
}

Tailor your file naming convention in gradle.properties for even more control, such as omitting the package name.
Set roborazzi.record.namingStrategy=testClassAndMethod for a streamlined naming pattern.
Learn more: Roborazzi Documentation

Enhanced Comparison with Grid and Labels ๐Ÿš€

This update introduces a new grid and label feature, making visual comparisons more intuitive and effective. The grid layout provides a structured view, while labels offer clear identification, streamlining the testing process.

You can use the old style by setting ComparisonStyle to ComparisonStyle.Simple in RoborazziOptions

  data class CompareOptions(
...
    val comparisonStyle: ComparisonStyle = ComparisonStyle.Grid(),
  ) {
    @ExperimentalRoborazziApi
    sealed interface ComparisonStyle {
      @ExperimentalRoborazziApi
      data class Grid(
        val bigLineSpaceDp: Int? = 16,
        val smallLineSpaceDp: Int? = 4,
        val hasLabel: Boolean = true
      ) : ComparisonStyle

      object Simple : ComparisonStyle
    }

image

Make Roborazzi's ImageComparator customizable.

You can now modify the ImageComparator using CompareOptions.imageComparator.

Behavior changes ๐Ÿ”ง

Set the default value of CompareOptions.changeThreshold to zero. This means it will detect even a single pixel change.

What's Changed

  • Make Roborazzi's ImageComparator customizable by @takahirom in #182
  • Set Default Value of CompareOptions.changeThreshold to Zero by @takahirom in #183
  • Fixed a bug where options set via RoborazziRule were ignored by @takahirom in #187
  • Fix the issue of keeping the previous test reports by @takahirom in #189
  • [CI]Speed up integration tests by @takahirom in #190
  • Refactor processOutputImageAndReport by @takahirom in #191
  • Fix the bug where the test reports are not updated when the tests fail by @takahirom in #194
  • Add a document about experimental output parameter by @takahirom in #195
  • Migrate Robolectric to gradle version catalog by @takahirom in #196
  • Add default parameter for CompareOptions.resultValidator by @takahirom in #203
  • Enhance Flexibility with Custom File Naming in Roborazzi via roboOutputName() Function by @takahirom in #205
  • Fix the issue where errors are ignored and occur when changing the size during GIF recording. by @takahirom in #210
  • Add labels and grid lines for the comparison image by @takahirom in #206
  • Fix simple comparison image by @takahirom in #213

Full Changelog: 1.7.0...1.8.0-rc-1