Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/uber/ios-snapshot-test-case

Snapshot view unit tests for iOS
https://github.com/uber/ios-snapshot-test-case

Last synced: 20 days ago
JSON representation

Snapshot view unit tests for iOS

Awesome Lists containing this project

README

        

# iOSSnapshotTestCase (previously [FBSnapshotTestCase](https://github.com/facebookarchive/ios-snapshot-test-case))

[![Build Status](https://github.com/uber/ios-snapshot-test-case/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/uber/ios-snapshot-test-case/actions)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/iOSSnapshotTestCase.svg)](https://img.shields.io/cocoapods/v/iOSSnapshotTestCase.svg)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Swift Package Manager](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)

## What it does

A "snapshot test case" takes a configured `UIView` or `CALayer` and uses the necessary UIKit or Core Animation methods to generate an image snapshot of its contents. It
compares this snapshot to a "reference image" stored in your source code
repository and fails the test if the two images don't match.

## Why?

We write a lot of UI code. There are a lot of edge
cases that we want to handle correctly when you are creating `UIView` instances:

- What if there is more text than can fit in the space available?
- What if an image doesn't match the size of an image view?
- What should the highlighted state look like?

It's straightforward to test logic code, but less obvious how you should test
views. You can do a lot of rectangle asserts, but these are hard to understand
or visualize. Looking at an image diff shows you exactly what changed and how
it will look to users.

`iOSSnapshotTestCase` was developed to make snapshot tests easy.

## Installation

### Step 1: Add iOSSnapshotTestCase to your project

#### CocoaPods

Add the following lines to your Podfile:

```ruby
target "Tests" do
use_frameworks!
pod 'iOSSnapshotTestCase'
end
```

If your test target is Objective-C only use `iOSSnapshotTestCase/Core` instead, which doesn't contain Swift support.

#### Carthage

Add the following line to your Cartfile:

```carthage
github "uber/ios-snapshot-test-case" ~> 8.0.0
```

#### Swift Package Manager

Add the following line to your `Package.swift`:

```spm
dependencies: [
.package(url: "https://github.com/uber/ios-snapshot-test-case.git", from: "8.0.0"),
],
```

...or integrate with Xcode via `File -> Swift Packages -> Add Package Dependency...` using the URL of the repository. We recommend using "Up to Next Major" with the Version field, as we use Semantic Versioning and only put breaking changes in major versions.

### Step 2: Setup Test Scheme
Replace "Tests" with the name of your test project.

1. There are [three ways](https://github.com/uber/ios-snapshot-test-case/blob/main/src/iOSSnapshotTestCaseCore/Public/FBSnapshotTestCase.h#L17-L31) of setting reference image directories, the recommended one is to define `FB_REFERENCE_IMAGE_DIR` in your scheme. This should point to the directory where you want reference images to be stored. We normally use this:

|Name|Value|
|:---|:----|
|`FB_REFERENCE_IMAGE_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages`|
|`IMAGE_DIFF_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/FailureDiffs`|

Define the `IMAGE_DIFF_DIR` to the directory where you want to store diffs of failed snapshots. There are also [three ways](https://github.com/uber/ios-snapshot-test-case/blob/main/src/iOSSnapshotTestCaseCore/Public/FBSnapshotTestCase.h#L33-L45) to set failed image diff directories.

![](FBSnapshotTestCaseDemo/Scheme_FB_REFERENCE_IMAGE_DIR.png)

## Creating a snapshot test

1. Subclass `FBSnapshotTestCase` instead of `XCTestCase`.
2. From within your test, use `FBSnapshotVerifyView`.
3. Run the test once with `self.recordMode = YES;` in the test's `-setUp`
method. (This creates the reference images on disk.)
4. Remove the line enabling record mode and run the test.

## Features

- Automatically names reference images on disk according to test class and
selector.
- Prints a descriptive error message to the console on failure. (Bonus:
failure message includes a one-line command to see an image diff if
you have [Kaleidoscope](http://www.kaleidoscopeapp.com) installed.)
- Supply an optional "identifier" if you want to perform multiple snapshots
in a single test method.
- Support for `CALayer` via `FBSnapshotVerifyLayer`.
- `usesDrawViewHierarchyInRect` to handle cases like `UIVisualEffect`, `UIAppearance` and Size Classes.
- `fileNameOptions` to control appending the device model (`iPhone`, `iPad`, `iPod Touch`, etc), OS version, screen size and screen scale to the images (allowing to have multiple tests for the same «snapshot» for different `OS`s and devices).

## Notes

Your unit tests _should_ be inside an "application" bundle, not a "logic/library" test bundle. (That is, it
should be run within the Simulator so that it has access to UIKit.)

*However*, if you are writing snapshot tests inside a library/framework, you might want to keep your test bundle as a library test bundle without a Test Host.

Read more on this [here](docs/LibraryVsApplicationTestBundles.md).

## Authors

`iOSSnapshotTestCase` was written at Facebook by
Jonathan Dann with significant contributions by
Todd Krabach.

Today it is maintained by [Uber](https://github.com/uber).

## License

`iOSSnapshotTestCase` is MIT–licensed. See [`LICENSE`](https://github.com/uber/ios-snapshot-test-case/blob/master/LICENSE).