https://github.com/jmp/assertthat
More readable assertions in Swift.
https://github.com/jmp/assertthat
swift swift-assertions swift-generics testing
Last synced: 12 months ago
JSON representation
More readable assertions in Swift.
- Host: GitHub
- URL: https://github.com/jmp/assertthat
- Owner: jmp
- License: mit
- Created: 2020-12-20T11:52:19.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-02-09T19:33:25.000Z (over 3 years ago)
- Last Synced: 2025-06-27T23:42:28.408Z (12 months ago)
- Topics: swift, swift-assertions, swift-generics, testing
- Language: Swift
- Homepage:
- Size: 82 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# AssertThat


[](https://codecov.io/gh/jmp/assert-that)
This library tries to make [AssertJ](https://assertj.github.io/doc/)-style readable assertions usable in Swift.
It is currently experimental and **super work in progress**. 🚧
## Motivation
The idea is that instead of having to write things like `XCTAssertEqual(someVar, "foo")` we can write
something like this instead:
```swift
assertThat(someVar).isEqualTo("foo")
```
This also allows more complicated assertion chains, for example:
```swift
assertThat("The quick brown fox")
.startsWith("The")
.contains("brown")
.endsWith("fox")
```
It should also allow the use of extensions to support custom assertions.
## Existing solutions
As far as I know, there is no port of AssertJ or similar library available for Swift. The closest match is
probably [Swift Hamcrest](https://github.com/nschum/SwiftHamcrest), which is quite mature and a very
nice alternative for Swift. The main difference is the syntax and how the assertions read. Another
noteworthy project is [Nimble](https://github.com/Quick/Nimble), which also has slightly different way
of expressing the assertions.
## How does it work
It makes use of Swift generics and extensions. The generic function `assertThat` returns an
`Assertion` struct holding the subject of the assertion. Literally everything else is implemented as
an extension of `Assertion`.
For example, `startsWith` is implemented as an extension of `Assertion` whose subject conforms to
`StringProtocol`. If the subject conforms to the `Comparable` protocol, then things like `isLessThan`
and `isBetween` can be used.
We can even have assertions for subjects that conform to multiple protocols at the same time.
For example, let's say we want to assert that a value is positive (strictly greater than zero). Creating
an assertion for a `Numeric` subject would allow us to assert something on `Numeric` types. However,
not all `Numeric` types are `Comparable`. To solve this, we can restrict the subject to comparable numeric
types by using `Numeric & Comparable`.
To implement assertions for your own types, chances are some of the built-in ones (like those for
`Equatable`) already work. But it's also trivial to write your own by writing extensions for
`Assertion`.
## Example usage
See example repository in [AssertThatExample](https://github.com/jmp/AssertThatExample).
First, import the module:
```swift
import AssertThat
```
Common assertions for optionals:
```swift
assertThat(x).isNil()
assertThat(x).isNotNil()
```
Booleans:
```swift
assertThat(x).isTrue()
assertThat(x).isFalse()
```
Equatables:
```swift
assertThat(x).isEqualTo(y)
assertThat(x).isNotEqualTo(y)
assertThat(x).isIn(someSequence)
assertThat(x).isNotIn(someSequence)
```
Comparables:
```swift
assertThat(x).isGreaterThanOrEqualTo(y)
assertThat(x).isLessThan(y)
assertThat(x).isBetween(y, z)
assertThat(x).isStrictlyBetween(y, z)
```
Strings:
```swift
assertThat(someString).isEmpty()
assertThat(someString).isNotEmpty()
// Chaining is also supported
assertThat(someString)
.startsWith("foo")
.contains("bar")
.endsWith("baz")
.matches("^foobar.+$")
.doesNotMatch("^Test$")
```
Sequences:
```swift
assertThat(sequence).contains(x)
assertThat(sequence).doesNotContain(x)
```
Collections:
```swift
assertThat(collection).isEmpty()
assertThat(collection).isNotEmpty()
```
Note that since a `Collection` also conforms to the `Sequence` protocol,
you can use any of the assertions of `Sequence` with collections:
```swift
assertThat(collection).contains(x)
assertThat(collection).doesNotContain(x)
```
Errors:
```swift
assertThat { someBlockOfCode }.throws(SomeErrorType.someSpecificError)
assertThat { someBlockOfCode }.throws(SomeErrorType.self)
assertThat { someBlockOfCode }.doesNotThrow(someError)
assertThat { someBlockOfCode }.throwsAnError() // Throws any error
assertThat { someBlockOfCode }.doesNotThrowAnError() // Doesn't throws any error
```
Browse the code and test cases for more complete examples.