Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Property-Based Testing with SwiftCheck
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
TJ Usiyan
September 06, 2016
Programming
1
5.5k
Property-Based Testing with SwiftCheck
These are the slides for my talk at try! swift NYC on 2016-09-02
TJ Usiyan
September 06, 2016
Tweet
Share
More Decks by TJ Usiyan
See All by TJ Usiyan
Musical Phantoms
griotspeak
0
82
Speaking in Types
griotspeak
0
34
Other Decks in Programming
See All in Programming
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
450
CSC307 Lecture 04
javiergs
PRO
0
660
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
370
Apache Iceberg V3 and migration to V3
tomtanaka
0
160
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.6k
カスタマーサクセス業務を変革したヘルススコアの実現と学び
_hummer0724
0
700
CSC307 Lecture 01
javiergs
PRO
0
690
高速開発のためのコード整理術
sutetotanuki
1
400
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
1.8k
フルサイクルエンジニアリングをAI Agentで全自動化したい 〜構想と現在地〜
kamina_zzz
0
400
CSC307 Lecture 03
javiergs
PRO
1
490
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
210
Featured
See All Featured
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
320
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
210
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
270
How to make the Groovebox
asonas
2
1.9k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
77
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
140
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.4k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
300
Rebuilding a faster, lazier Slack
samanthasiow
85
9.4k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Building an army of robots
kneath
306
46k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.2k
Transcript
Property-Based Testing with SwiftCheck 1
Tests are difficult to write 2
Tests are difficult to write 3
Test cases are difficult to write 4
How are test cases difficult to write? 5
How are test cases difficult to write? • We need
to find all of the meaninful test cases 5
How are test cases difficult to write? • We need
to find all of the meaninful test cases • We need to organize them in a meaningful way 5
How are test cases difficult to write? • We need
to find all of the meaninful test cases • We need to organize them in a meaningful way • How many cases are enough? 5
How can we find test cases? 6
How can we find test cases? • Randomness 6
How can we find test cases? • Randomness • Reproducible
6
How can we find test cases? • Randomness • Reproducible
• Simplify failing case (when possible) 6
7
Let's Get Testing public struct Rational { public let numerator
: Int public let denominator : Int } 8
Arbitrary public protocol Arbitrary { /// The generator for this
particular type. public static var arbitrary: SwiftCheck.Gen<Self> { get } } 9
Gen Gen represents a generator for random arbitrary values of
a type. public struct Gen<A> 10
Conforming to Arbitrary public static var arbitrary: SwiftCheck.Gen<Rational> { return
Gen.compose { comp in return Rational(comp.generate(), comp.generate()) } } 11
Conforming to Arbitrary return Rational(comp.generate(), comp.generate()) 12
Filtering Generated values Int.arbitrary.suchThat { $0 != 0 } //
Denominator 13
Filtering Generated values extension Rational : Arbitrary { public static
var arbitrary: SwiftCheck.Gen<Rational> { return Gen<Rational>.compose { comp in let denGen = Int.arbitrary.suchThat { $0 != 0 } return Rational( comp.generate(), comp.generate(using: denGen) } } 14
OK, What to test? 15
Properties! 16
Round Trip Properties property("round trip to string") <- forAll {
(i: Int) in return Int(i.description)! == i } 17
Round Trip Properties // for all foo: [Int] foo.reverse().reverse() ==
foo 18
Commuting Diagram Properties • ----- | | | | |
! -----" 19
Commuting Diagram Properties property("base64 encoding commutes with Apple's ") <-
forAll { (data: Data) in return data.base64Encoding == data.myBase64Encoding } 20
Properties func testAddition() { property("Addition is commutative") <- forAll {
(i: Rational, j: Rational) in return (i + j) == (j + i) } } 21
Properties property("Addition is commutative 2") <- forAll { (i: Rational,
j: Rational, k: Rational) in let caseOne = (i + j + k) let caseTwo = ((i + j) + k) let caseThree = (i + (j + k)) return (caseOne == caseTwo) && (caseTwo == caseThree) } 22
Replay 23
Replay let (seedl, seedr) = (1640744780, 1403884642) let replayArgs =
CheckerArguments(replay: .some(StdGen(seedl, seedr), 3)) property("x / y", arguments: replayArgs) <- forAll { … 24
Mixed Testing func testEquality() { let oneOverTwo = Rational(1, 2)!
let twoOverFour = Rational(2, 4)! let ichiUeNi = Rational(1, 2)! XCTAssertEqual(oneOverTwo == twoOverFour, true) XCTAssertEqual(twoOverFour == ichiUeNi, true) XCTAssertEqual(ichiUeNi == oneOverTwo, true) XCTAssertEqual(oneOverTwo ≡ twoOverFour, false) XCTAssertEqual(twoOverFour ≡ ichiUeNi, false) XCTAssertEqual(ichiUeNi ≡ oneOverTwo, true) let halfIntMax = (Int.max / 2) - 1 property("value holds") <- forAll { (value: Rational) in return ((value.numerator < halfIntMax) && (value.denominator < halfIntMax)) ==> { let doubledSame = Rational(value.numerator * 2, value.denominator * 2)! return (value == doubledSame) && ((value ≡ doubledSame) == false) } } } 25
Shrinking 26
So? 27
So? • Less time writing tests? 27
So? • Less time writing tests? • Better tests 27
So? • Less time writing tests? • Better tests •
Easier diagnosis 27
So? • Less time writing tests? • Better tests •
Easier diagnosis • You will and should still write test cases! 27
For Our Friends in Obj-C https://github.com/jeffh/Fox 28
TJ Usiyan @griotspeak 29