Skip to content

Commit 4a6704a

Browse files
stephencelismbrandonw
authored andcommittedDec 3, 2018
Update README (pointfreeco#118)
* wip * Update README.md * Update README.md * Update README.md * Update * Update README.md * Update README.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update CODE_OF_CONDUCT.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * typo * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md
1 parent e168bfb commit 4a6704a

File tree

4 files changed

+109
-87
lines changed

4 files changed

+109
-87
lines changed
 

‎.github/snapshot-test-1.png

352 KB
Loading

‎CODE_OF_CONDUCT.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
3434

3535
## Enforcement
3636

37-
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mbw234@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
37+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@pointfree.co. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
3838

3939
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
4040

‎CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
## Code of Conduct
44

5-
This project and everyone participating in it is governed by its [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to mbw234@gmail.com.
5+
This project and everyone participating in it is governed by its [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to support@pointfree.co.

‎README.md

+107-85
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
# SnapshotTesting
1+
# 📸 SnapshotTesting
22

33
[![Swift 4.2](https://img.shields.io/badge/swift-4.2-ED523F.svg?style=flat)](https://swift.org/download/) [![iOS/macOS/tvOS CI](https://img.shields.io/circleci/project/github/pointfreeco/swift-snapshot-testing/master.svg?label=ios/macos/tvos)](https://circleci.com/gh/pointfreeco/swift-snapshot-testing) [![Linux CI](https://img.shields.io/travis/pointfreeco/swift-snapshot-testing/master.svg?label=linux)](https://travis-ci.org/pointfreeco/swift-nonempty) [![@pointfreeco](https://img.shields.io/badge/contact-@pointfreeco-5AA9E7.svg?style=flat)](https://twitter.com/pointfreeco)
44

5-
Snapshot testing for views, data, and more!
5+
Delightful Swift snapshot testing.
66

7-
## Getting Started
7+
<!--
8+
![An example of a snapshot failure in Xcode.](.github/snapshot-test-1.png)
9+
-->
10+
11+
## Usage
812

9-
Once the library [is installed](#installation), no additional configuration is required. You can import the `SnapshotTesting` module into a test and pass a value to the `assertSnapshot` function.
13+
Once [installed](#installation), _no additional configuration is required_. You can import the `SnapshotTesting` module and call the `assertSnapshot` function.
1014

1115
``` swift
1216
import SnapshotTesting
@@ -21,15 +25,15 @@ class MyViewControllerTests: XCTestCase {
2125
}
2226
```
2327

24-
When the test first runs, a snapshot is recorded automatically to disk and the test will fail and print out the file path of the reference.
28+
When an assertion first runs, a snapshot is automatically recorded to disk and the test will fail, printing out the file path of any newly-recorded reference.
2529

2630
> 🛑 failed - Recorded: …
2731
>
2832
> "…/MyAppTests/\_\_Snapshots\_\_/MyViewControllerTests/testMyViewController.png"
2933
30-
Repeat test runs will load this reference for comparison. If the images don't match, the test will fail and print out the file path of each image for further inspection.
34+
Repeat test runs will load this reference and compare it with the runtime value. If they don't match, the test will fail and describe the difference.
3135

32-
You can record a new reference by setting `record` mode to `true` on the assertion or globally.
36+
You can record a new reference by setting the `record` mode to `true` on the assertion or globally.
3337

3438
``` swift
3539
assertSnapshot(matching: vc, as: .image, record: true)
@@ -40,11 +44,74 @@ record = true
4044
assertSnapshot(matching: vc, as: .image)
4145
```
4246

43-
<!--
44-
## Configuration
47+
## Snapshot Anything
4548

46-
TODO
47-
-->
49+
While most snapshot testing libraries in the Swift community are limited to `UIView`s and `UIImage`s, SnapshotTesting can work with _any_ value and _any_ format on _any_ Swift platform!
50+
51+
The `assertSnapshot` function accepts a value and any snapshot strategy that value supports. This means that a [view](Documentation/Available-Snapshot-Strategies.md#uiview) or [view controller](Documentation/Available-Snapshot-Strategies.md#uiviewcontroller) can be tested against an image representation _and_ against a textual representation of its properties and subview hierarchy.
52+
53+
``` swift
54+
assertSnapshot(matching: vc, as: .image)
55+
assertSnapshot(matching: vc, as: .recursiveDescription)
56+
```
57+
58+
View testing is [highly configurable](Documentation/Available-Snapshot-Strategies.md#uiviewcontroller). You can override trait collections (for specific size classes and content size categories) and generate device-agnostic snapshots, all from a single simulator.
59+
60+
``` swift
61+
assertSnapshot(matching: vc, as: .image(on: .iPhoneSe))
62+
assertSnapshot(matching: vc, as: .image(on: .iPhoneSe(.landscape)))
63+
assertSnapshot(matching: vc, as: .image(on: .iPhoneX))
64+
assertSnapshot(matching: vc, as: .image(on: .iPadMini(.portrait)))
65+
```
66+
67+
Better yet, SnapshotTesting isn't limited to views and view controllers! There are [a number of available snapshot strategies](Documentation/Available-Snapshot-Strategies.md) to choose from.
68+
69+
For example, you can snapshot test URL requests (_e.g._, those that your API client prepares).
70+
71+
``` swift
72+
assertSnapshot(matching: urlRequest, as: .raw)
73+
// POST http://localhost:8080/account
74+
// Cookie: pf_session={"userId":"1"}
75+
//
76+
// email=blob%40pointfree.co&name=Blob
77+
```
78+
79+
And you can snapshot test `Encodable` values against their JSON _and_ property list representations.
80+
81+
``` swift
82+
assertSnapshot(matching: user, as: .json)
83+
// {
84+
// "bio" : "Blobbed around the world.",
85+
// "id" : 1,
86+
// "name" : "Blobby"
87+
// }
88+
89+
assertSnapshot(matching: user, as: .plist)
90+
// <?xml version="1.0" encoding="UTF-8"?>
91+
// <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
92+
// <plist version="1.0">
93+
// <dict>
94+
// <key>bio</key>
95+
// <string>Blobbed around the world.</string>
96+
// <key>id</key>
97+
// <integer>1</integer>
98+
// <key>name</key>
99+
// <string>Blobby</string>
100+
// </dict>
101+
// </plist>
102+
```
103+
104+
In fact, _[any](Documentation/Available-Snapshot-Strategies.md#any)_ value can be snapshot-tested by default using its [mirror](https://developer.apple.com/documentation/swift/mirror)!
105+
106+
``` swift
107+
assertSnapshot(matching: user, as: .dump)
108+
// ▿ User
109+
// - bio: "Blobbed around the world."
110+
// - id: 1
111+
// - name: "Blobby"
112+
```
113+
114+
If your data can be represented as an image, text, or data, you can write a snapshot test for it! Check out [all of the snapshot strategies](Documentation/Available-Snapshot-Strategies.md) that ship with SnapshotTesting and [learn how to define your own custom strategies](Documentation/Defining-Custom-Snapshot-Strategies.md).
48115

49116
## Installation
50117

@@ -53,7 +120,7 @@ TODO
53120
If you use [Carthage](https://github.com/Carthage/Carthage), you can add the following dependency to your `Cartfile`:
54121

55122
``` ruby
56-
github "pointfreeco/swift-snapshot-testing" "master"
123+
github "pointfreeco/swift-snapshot-testing" <~ 1.0
57124
```
58125

59126
### CocoaPods
@@ -62,7 +129,7 @@ If your project uses [CocoaPods](https://cocoapods.org), add the pod to any appl
62129

63130
```ruby
64131
target 'MyAppTests' do
65-
pod 'SnapshotTesting', :git => 'https://github.com/pointfreeco/swift-snapshot-testing.git'
132+
pod 'SnapshotTesting', '<~ 1.0'
66133
end
67134
```
68135

@@ -72,88 +139,43 @@ If you want to use SnapshotTesting in a project that uses [SwiftPM](https://swif
72139

73140
```swift
74141
dependencies: [
75-
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", .branch("master")),
142+
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.0.0"),
76143
]
77144
```
78145

79-
## Usage
80-
81-
Snapshot Testing provides an `assertSnapshot` function, which records data structures as text or images accordingly.
82-
83-
Here's how you might test a URL request you've prepared for your app's API client:
84-
85-
```swift
86-
import SnapshotTesting
87-
import XCTest
88-
89-
class ApiServiceTests: XCTestCase {
90-
func testUrlRequestPreparation() {
91-
let service = ApiService()
92-
let request = service
93-
.prepare(endpoint: .createArticle("Hello, world!"))
94-
95-
assertSnapshot(matching: request)
96-
}
97-
}
98-
```
99-
100-
The above will render as the following text to `__Snapshots__/ApiServiceTests/testUrlRequestPreparation.0.txt`:
101-
102-
```
103-
▿ https://api.site.com/articles?oauth_token=deadbeef
104-
▿ url: Optional(https://api.site.com/articles?oauth_token=deadbeef)
105-
▿ some: https://api.site.com/articles?oauth_token=deadbeef
106-
- _url: https://api.site.com/articles?oauth_token=deadbeef #0
107-
- super: NSObject
108-
- cachePolicy: 0
109-
- timeoutInterval: 60.0
110-
- mainDocumentURL: nil
111-
- networkServiceType: __ObjC.NSURLRequest.NetworkServiceType
112-
- allowsCellularAccess: true
113-
▿ httpMethod: Optional("POST")
114-
- some: "POST"
115-
▿ allHTTPHeaderFields: Optional(["App-Version": "42"])
116-
▿ some: 1 key/value pairs
117-
▿ (2 elements)
118-
- key: "App-Version"
119-
- value: "42"
120-
▿ httpBody: Optional(19 bytes)
121-
▿ some: "body=Hello%20world!"
122-
- httpBodyStream: nil
123-
- httpShouldHandleCookies: true
124-
- httpShouldUsePipelining: false
125-
```
126-
127-
Renderable data will write as an image. This includes `UIImage`s and `NSImage`s, but also data that is typically viewed visually, like `UIView`s and `NSView`s.
128-
129-
Given a view:
130-
131-
``` swift
132-
import SnapshotTesting
133-
import XCTest
134-
135-
class HomepageTests: XCTestCase {
136-
func testRender() {
137-
let size = CGSize(width: 800, height: 600)
138-
let webView = UIWebView(frame: .init(origin: .zero, size: size))
139-
webView.loadHTMLString(renderHomepage())
140-
141-
assertSnapshot(matching: webView)
142-
}
143-
}
144-
```
146+
## Features
145147

146-
The above will write to an image on disk. If that image ever renders differently in the future, the assertion will fail and produce a diff for inspection.
148+
- [**Dozens of snapshot strategies**](Documentation/Available-Snapshot-Strategies.md). Snapshot testing isn't just for `UIView`s and `CALayer`s. Write snapshots against _any_ value.
149+
- [**Write your own snapshot strategies**](Documentation/Defining-Custom-Snapshot-Strategies.md). If you can convert it to an image, string, data, or your own diffable format, you can snapshot test it! Build your own snapshot strategies from scratch or transform existing ones.
150+
- **No configuration required.** Don't fuss with scheme settings and environment variables. Snapshots are automatically saved alongside your tests.
151+
- **More hands-off.** New snapshots are recorded whether `record` mode is `true` or not.
152+
- **Subclass-free.** Assert from any XCTest case or Quick spec.
153+
- **Device-agnostic snapshots.** Render views and view controllers for specific devices and trait collections from a single simulator.
154+
- **First-class Xcode support.** Image differences are captured as XCTest attachments. Text differences are rendered in inline error messages.
155+
- **Supports any platform that supports Swift.** Write snapshot tests for iOS, Linux, macOS, and tvOS.
156+
- **SceneKit, SpriteKit, and WebKit support.** Most snapshot testing libraries don't support these view subclasses.
157+
- **`Codable` support**. Snapshot encodable data structures into their [JSON](Documentation/Available-Snapshot-Strategies.md#json) and [property list](Documentation/Available-Snapshot-Strategies.md#plist) representations.
158+
- **Custom diff tool integration**.
147159

148-
![A screen shot failure.](.github/kaleidoscope-diff.png)
160+
## Learn More
149161

162+
SnapshotTesting was designed with [witness-oriented programming](https://www.pointfree.co/episodes/ep39-witness-oriented-library-design).
150163

151-
## Related Tools
164+
This concept (and more) are explored thoroughly in a series of episodes on [Point-Free](https://www.pointfree.co), a video series exploring functional programming and Swift hosted by [Brandon Williams](https://github.com/mbrandonw) and [Stephen Celis](https://github.com/stephencelis).
152165

153-
- [`FBSnapshotTestCase`](https://github.com/facebook/ios-snapshot-test-case) helped introduce screen shot testing to a broad audience in the iOS community. Experience with it inspired the creation of this library.
166+
Witness-oriented programming was explored in the following episodes:
154167

155-
- [`Jest`](http://facebook.github.io/jest/) brought generalized snapshot testing to the front-end with a polished user experience. Several features of this library (diffing, tracking outdated snapshots) were directly influenced.
168+
- [Episode 33](https://www.pointfree.co/episodes/ep33-protocol-witnesses-part-1): Protocol Witnesses: Part 1
169+
- [Episode 34](https://www.pointfree.co/episodes/ep34-protocol-witnesses-part-1): Protocol Witnesses: Part 2
170+
- [Episode 35](https://www.pointfree.co/episodes/ep35-advanced-protocol-witnesses-part-1): Advanced Protocol Witnesses: Part 1
171+
- [Episode 36](https://www.pointfree.co/episodes/ep36-advanced-protocol-witnesses-part-2): Advanced Protocol Witnesses: Part 2
172+
- [Episode 37](https://www.pointfree.co/episodes/ep37-protocol-oriented-library-design-part-1): Protocol-Oriented Library Design: Part 1
173+
- [Episode 38](https://www.pointfree.co/episodes/ep38-protocol-oriented-library-design-part-2): Protocol-Oriented Library Design: Part 2
174+
- [Episode 39](https://www.pointfree.co/episodes/ep39-witness-oriented-library-design): Witness-Oriented Library Design
156175

176+
<a href="https://www.pointfree.co/episodes/ep26-domain-specific-languages-part-1">
177+
<img alt="video poster image" src="https://d1hf1soyumxcgv.cloudfront.net/0039-witness-oriented-library-design/poster.jpg" width="480">
178+
</a>
157179

158180
## License
159181

0 commit comments

Comments
 (0)
Please sign in to comment.