{"id":2090,"url":"https://github.com/typelift/SwiftCheck","last_synced_at":"2025-08-06T14:31:29.051Z","repository":{"id":19349890,"uuid":"22589240","full_name":"typelift/SwiftCheck","owner":"typelift","description":"QuickCheck for Swift","archived":false,"fork":false,"pushed_at":"2022-04-03T14:57:09.000Z","size":1630,"stargazers_count":1415,"open_issues_count":22,"forks_count":105,"subscribers_count":46,"default_branch":"master","last_synced_at":"2024-12-06T19:05:56.465Z","etag":null,"topics":["property-based-testing","quickcheck","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typelift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-04T02:19:19.000Z","updated_at":"2024-12-02T03:30:49.000Z","dependencies_parsed_at":"2022-08-07T09:15:14.596Z","dependency_job_id":null,"html_url":"https://github.com/typelift/SwiftCheck","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FSwiftCheck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FSwiftCheck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FSwiftCheck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelift%2FSwiftCheck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typelift","download_url":"https://codeload.github.com/typelift/SwiftCheck/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905550,"owners_count":17989782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["property-based-testing","quickcheck","swift"],"created_at":"2024-01-05T20:16:03.275Z","updated_at":"2024-12-09T14:31:17.679Z","avatar_url":"https://github.com/typelift.png","language":"Swift","readme":"[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Build Status](https://travis-ci.org/typelift/SwiftCheck.svg?branch=master)](https://travis-ci.org/typelift/SwiftCheck)\n[![Gitter chat](https://badges.gitter.im/DPVN/chat.png)](https://gitter.im/typelift/general?utm_source=share-link\u0026utm_medium=link\u0026utm_campaign=share-link)\n \n \nSwiftCheck\n==========\n\nQuickCheck for Swift.\n\nFor those already familiar with the Haskell library, check out the source.  For\neverybody else, see the [Tutorial Playground](Tutorial.playground) for a\nbeginner-level introduction to the major concepts and use-cases of this library.\n \nIntroduction\n============\n\nSwiftCheck is a testing library that automatically generates random data for \ntesting of program properties.  A property is a particular facet of an algorithm\nor data structure that must be invariant under a given set of input data,\nbasically an `XCTAssert` on steroids.  Where before all we could do was define\nmethods prefixed by `test` and assert, SwiftCheck allows program properties and \ntests to be treated like *data*.\n\nTo define a program property the `forAll` quantifier is used with a type\nsignature like `(A, B, C, ... Z) -\u003e Testable where A : Arbitrary, B : Arbitrary ...\nZ : Arbitrary`.  SwiftCheck implements the `Arbitrary` protocol for most Swift \nStandard Library types and implements the `Testable` protocol for `Bool` and \nseveral other related types.  For example, if we wanted to test the property \nthat every Integer is equal to itself, we would express it as such:\n\n```swift\nfunc testAll() {\n    // 'property' notation allows us to name our tests.  This becomes important\n    // when they fail and SwiftCheck reports it in the console.\n    property(\"Integer Equality is Reflexive\") \u003c- forAll { (i : Int) in\n        return i == i\n    }\n}\n```\n\nFor a less contrived example, here is a program property that tests whether\nArray identity holds under double reversal:\n\n```swift\nproperty(\"The reverse of the reverse of an array is that array\") \u003c- forAll { (xs : [Int]) in\n    // This property is using a number of SwiftCheck's more interesting \n    // features.  `^\u0026\u0026^` is the conjunction operator for properties that turns\n    // both properties into a larger property that only holds when both sub-properties\n    // hold.  `\u003c?\u003e` is the labelling operator allowing us to name each sub-part\n    // in output generated by SwiftCheck.  For example, this property reports:\n    //\n    // *** Passed 100 tests\n    // (100% , Right identity, Left identity)\n    return\n        (xs.reversed().reversed() == xs) \u003c?\u003e \"Left identity\"\n        ^\u0026\u0026^\n        (xs == xs.reversed().reversed()) \u003c?\u003e \"Right identity\"\n}\n```\n\nBecause SwiftCheck doesn't require tests to return `Bool`, just `Testable`, we\ncan produce tests for complex properties with ease:\n\n```swift\nproperty(\"Shrunken lists of integers always contain [] or [0]\") \u003c- forAll { (l : [Int]) in\n    // Here we use the Implication Operator `==\u003e` to define a precondition for\n    // this test.  If the precondition fails the test is discarded.  If it holds\n    // the test proceeds.\n    return (!l.isEmpty \u0026\u0026 l != [0]) ==\u003e {\n        let ls = self.shrinkArbitrary(l)\n        return (ls.filter({ $0 == [] || $0 == [0] }).count \u003e= 1)\n    }\n}\n```\n\nProperties can even depend on other properties:\n\n```swift\nproperty(\"Gen.one(of:) multiple generators picks only given generators\") \u003c- forAll { (n1 : Int, n2 : Int) in\n    let g1 = Gen.pure(n1)\n    let g2 = Gen.pure(n2)\n    // Here we give `forAll` an explicit generator.  Before SwiftCheck was using\n    // the types of variables involved in the property to create an implicit\n    // Generator behind the scenes.\n    return forAll(Gen.one(of: [g1, g2])) { $0 == n1 || $0 == n2 }\n}\n```\n\nAll you have to figure out is what to test.  SwiftCheck will handle the rest.  \n\nShrinking\n=========\n \nWhat makes QuickCheck unique is the notion of *shrinking* test cases.  When fuzz\ntesting with arbitrary data, rather than simply halt on a failing test, SwiftCheck\nwill begin whittling the data that causes the test to fail down to a minimal\ncounterexample.\n\nFor example, the following function uses the Sieve of Eratosthenes to generate\na list of primes less than some n:\n\n```swift\n/// The Sieve of Eratosthenes:\n///\n/// To find all the prime numbers less than or equal to a given integer n:\n///    - let l = [2...n]\n///    - let p = 2\n///    - for i in [(2 * p) through n by p] {\n///          mark l[i]\n///      }\n///    - Remaining indices of unmarked numbers are primes\nfunc sieve(_ n : Int) -\u003e [Int] {\n    if n \u003c= 1 {\n        return []\n    }\n\n    var marked : [Bool] = (0...n).map { _ in false }\n    marked[0] = true\n    marked[1] = true\n\n    for p in 2..\u003cn {\n        for i in stride(from: 2 * p, to: n, by: p) {\n            marked[i] = true\n        }\n    }\n\n    var primes : [Int] = []\n    for (t, i) in zip(marked, 0...n) {\n        if !t {\n            primes.append(i)\n        }\n    }\n    return primes\n}\n\n/// Short and sweet check if a number is prime by enumerating from 2...⌈√(x)⌉ and checking \n/// for a nonzero modulus.\nfunc isPrime(n : Int) -\u003e Bool {\n    if n == 0 || n == 1 {\n        return false\n    } else if n == 2 {\n        return true\n    }\n    \n    let max = Int(ceil(sqrt(Double(n))))\n    for i in 2...max {\n        if n % i == 0 {\n            return false\n        }\n    }\n    return true\n}\n\n```\n\nWe would like to test whether our sieve works properly, so we run it through \nSwiftCheck with the following property:\n\n```swift\nimport SwiftCheck\n\nproperty(\"All Prime\") \u003c- forAll { (n : Int) in\n    return sieve(n).filter(isPrime) == sieve(n)\n}\n```\n\nWhich produces the following in our testing log:\n\n```\nTest Case '-[SwiftCheckTests.PrimeSpec testAll]' started.\n*** Failed! Falsifiable (after 10 tests):\n4\n```\n\nIndicating that our sieve has failed on the input number 4.  A quick look back\nat the comments describing the sieve reveals the mistake immediately:\n\n```diff\n- for i in stride(from: 2 * p, to: n, by: p) {\n+ for i in stride(from: 2 * p, through: n, by: p) {\n```\n\nRunning SwiftCheck again reports a successful sieve of all 100 random cases:\n\n```\n*** Passed 100 tests\n```\n\nCustom Types\n============\n\nSwiftCheck implements random generation for most of the types in the Swift \nStandard Library. Any custom types that wish to take part in testing must \nconform to the included `Arbitrary` protocol.  For the majority of types, this\nmeans providing a custom means of generating random data and shrinking down to \nan empty array. \n\nFor example:\n\n```swift\nimport SwiftCheck\n \npublic struct ArbitraryFoo {\n    let x : Int\n    let y : Int\n\n    public var description : String {\n        return \"Arbitrary Foo!\"\n    }\n}\n\nextension ArbitraryFoo : Arbitrary {\n    public static var arbitrary : Gen\u003cArbitraryFoo\u003e {\n        return Gen\u003c(Int, Int)\u003e.zip(Int.arbitrary, Int.arbitrary).map(ArbitraryFoo.init)\n    }\n}\n\nclass SimpleSpec : XCTestCase {\n    func testAll() {\n        property(\"ArbitraryFoo Properties are Reflexive\") \u003c- forAll { (i : ArbitraryFoo) in\n            return i.x == i.x \u0026\u0026 i.y == i.y\n        }\n    }\n}\n```\n\nThere's also a `Gen.compose` method which allows you to procedurally compose \nvalues from multiple generators to construct instances of a type:\n\n``` swift\npublic static var arbitrary : Gen\u003cMyClass\u003e {\n    return Gen\u003cMyClass\u003e.compose { c in\n        return MyClass(\n            // Use the nullary method to get an `arbitrary` value.\n            a: c.generate(),\n\n            // or pass a custom generator\n            b: c.generate(Bool.suchThat { $0 == false }),\n\n            // .. and so on, for as many values and types as you need.\n            c: c.generate(), ...\n        )\n    }\n}\n```\n\n`Gen.compose` can also be used with types that can only be customized with setters:\n\n``` swift\npublic struct ArbitraryMutableFoo : Arbitrary {\n    var a: Int8\n    var b: Int16\n    \n    public init() {\n        a = 0\n        b = 0\n    }\n    \n    public static var arbitrary: Gen\u003cArbitraryMutableFoo\u003e {\n        return Gen.compose { c in\n            var foo = ArbitraryMutableFoo()\n            foo.a = c.generate()\n            foo.b = c.generate()\n            return foo\n        }\n    }\n}\n```\n\nFor everything else, SwiftCheck defines a number of combinators to make working\nwith custom generators as simple as possible:\n\n```swift\nlet onlyEven = Int.arbitrary.suchThat { $0 % 2 == 0 }\n\nlet vowels = Gen.fromElements(of: [ \"A\", \"E\", \"I\", \"O\", \"U\" ])\n\nlet randomHexValue = Gen\u003cUInt\u003e.choose((0, 15))\n\nlet uppers = Gen\u003cCharacter\u003e.fromElements(in: \"A\"...\"Z\")\nlet lowers = Gen\u003cCharacter\u003e.fromElements(in: \"a\"...\"z\")\nlet numbers = Gen\u003cCharacter\u003e.fromElements(in: \"0\"...\"9\")\n \n/// This generator will generate `.none` 1/4 of the time and an arbitrary\n/// `.some` 3/4 of the time\nlet weightedOptionals = Gen\u003cInt?\u003e.frequency([\n    (1, Gen\u003cInt?\u003e.pure(nil)),\n    (3, Int.arbitrary.map(Optional.some))\n])\n```\n \nFor instances of many complex or \"real world\" generators, see \n[`ComplexSpec.swift`](Tests/SwiftCheckTests/ComplexSpec.swift).\n\nSystem Requirements\n===================\n\nSwiftCheck supports OS X 10.9+ and iOS 7.0+.\n\nSetup\n=====\n\nSwiftCheck can be included one of two ways:\n \n**Using The Swift Package Manager**\n\n- Add SwiftCheck to your `Package.swift` file's dependencies section:\n\n```swift\n.package(url: \"https://github.com/typelift/SwiftCheck.git\", from: \"0.8.1\")\n```\n \n**Using Carthage**\n\n- Add SwiftCheck to your Cartfile\n- Run `carthage update`\n- Drag the relevant copy of SwiftCheck into your project.\n- Expand the Link Binary With Libraries phase\n- Click the + and add SwiftCheck\n- Click the + at the top left corner to add a Copy Files build phase\n- Set the directory to `Frameworks`\n- Click the + and add SwiftCheck\n\n**Using CocoaPods**\n\n- Add [our Pod](https://cocoapods.org/pods/SwiftCheck) to your podfile.\n- Run `$ pod install` in your project directory.\n \n**Framework**\n\n- Drag SwiftCheck.xcodeproj into your project tree\n  as a subproject\n- Under your project's Build Phases, expand Target Dependencies\n- Click the + and add SwiftCheck\n- Expand the Link Binary With Libraries phase\n- Click the + and add SwiftCheck\n- Click the + at the top left corner to add a Copy Files build phase\n- Set the directory to Frameworks\n- Click the + and add SwiftCheck\n\nLicense\n=======\n\nSwiftCheck is released under the MIT license.\n","funding_links":[],"categories":["Testing","Libs","Swift","Testing [🔝](#readme)","The Index"],"sub_categories":["TDD / BDD","Testing","Other free courses","Graphics"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelift%2FSwiftCheck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypelift%2FSwiftCheck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelift%2FSwiftCheck/lists"}