In the previous post we described an approach to testing known as property-based testing. Instead of writing examples to test our code, we write properties that the output must have. We can keep writing properties that constraint this output until we have an accurate specification of what we need our software to do.
Although it is possible to perform this type of testing without any kind of library, there are tools that will ease these tasks for us. In Swift, we can use SwiftCheck, an open-source library in the spirit of Haskell’s QuickCheck.
Including SwiftCheck in your project is as easy as using CocoaPods. Just add
pod 'SwiftCheck', '~> <version>', replacing
<version> with the latest release of the library. Install your pods and you are ready to go!
Writing Property-based Tests with SwiftCheck
In the previous post we used a String concatenation example. We can rewrite the three property-based tests using SwiftCheck:
Let’s break down the structure of these tests:
- We have to create a regular unit test by extending XCTestCase and adding methods prefixed with
- Inside each unit test, we create a
Stringdescribing what we want to test.
- With operator
<-, we invoke
forAll, which receives a closure. This closure accepts a number of arguments whose types implement the
Arbitraryprotocol. Don’t worry about this for now, the library extends the basic Swift types for us. The arguments to this closure will be random Strings for our property-based test (the ones that we were creating with
randomString()in the previous post).
- In the body of the closure, we execute the methods or functions we want to test.
- Finally, we don’t need to write an assertion, but to return a
Testableexpression. In our case, we return a
Boolfrom the comparison we are performing.
Running these tests will execute our closures multiple times. By default, each property is run 100 times, although this number can be increased or decreased.
As you can see, it is very easy to write property-based tests using SwiftCheck. In the final post of these series, we will show how the input to these tests can be constrained (sometimes we may be interested in a certain subset of the input type) and how to provide input for our custom types.
Tomás Ruiz-López DEVELOPMENT
swift iOS testing property based testing functional programming