{"id":13995676,"url":"https://github.com/krzysztofzablocki/Difference","last_synced_at":"2025-07-22T22:31:48.463Z","repository":{"id":26133429,"uuid":"107408832","full_name":"krzysztofzablocki/Difference","owner":"krzysztofzablocki","description":"Simple way to identify what is different between 2 instances of any type. Must have for TDD.","archived":false,"fork":false,"pushed_at":"2024-08-05T13:34:30.000Z","size":2761,"stargazers_count":1221,"open_issues_count":4,"forks_count":53,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-24T09:29:10.436Z","etag":null,"topics":["ios","macos","swift","testing","tvos","watchos"],"latest_commit_sha":null,"homepage":"http://merowing.info","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/krzysztofzablocki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"krzysztofzablocki"}},"created_at":"2017-10-18T13:01:12.000Z","updated_at":"2024-11-15T20:13:00.000Z","dependencies_parsed_at":"2023-12-14T10:37:33.629Z","dependency_job_id":"c86e8f5a-2448-4881-b8d0-078519bc8bd4","html_url":"https://github.com/krzysztofzablocki/Difference","commit_stats":{"total_commits":83,"total_committers":18,"mean_commits":4.611111111111111,"dds":0.7469879518072289,"last_synced_commit":"7eb73c5d28c87dd6c4bac805aa28f757648aa92c"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krzysztofzablocki%2FDifference","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krzysztofzablocki%2FDifference/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krzysztofzablocki%2FDifference/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krzysztofzablocki%2FDifference/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krzysztofzablocki","download_url":"https://codeload.github.com/krzysztofzablocki/Difference/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226594687,"owners_count":17656472,"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":["ios","macos","swift","testing","tvos","watchos"],"created_at":"2024-08-09T14:03:32.625Z","updated_at":"2025-07-22T22:31:48.451Z","avatar_url":"https://github.com/krzysztofzablocki.png","language":"Swift","funding_links":["https://github.com/sponsors/krzysztofzablocki"],"categories":["Swift"],"sub_categories":[],"readme":"[![Version](https://img.shields.io/cocoapods/v/Difference.svg?style=flat)](http://cocoapods.org/pods/Difference)\n[![License](https://img.shields.io/cocoapods/l/Difference.svg?style=flat)](http://cocoapods.org/pods/Difference)\n[![Platform](https://img.shields.io/cocoapods/p/Difference.svg?style=flat)](http://cocoapods.org/pods/Difference)\n\n# Difference\n\nBetter way to identify what's different between 2 instances.\n\nHave you ever written tests? \nUsually they use equality asserts, e.g. `XCTAssertEqual`, what happens if the objects aren't equal? Xcode throws a wall of text at you:\n\n![](Resources/before.png)\n\nThis forces you to manually scan the text and try to figure out exactly what's wrong, what if instead you could just learn which property is different?\n\n![](Resources/after.png)\n\n[**If you'd like to support my work and improve your engineering workflows, check out my SwiftyStack course**](https://www.swiftystack.com/)\n\n## Installation\n\n### CocoaPods\n\nAdd `pod 'Difference'` to your Podfile.\n\n### Carthage\n\nAdd `github \"krzysztofzablocki/Difference\"` to your Cartfile.\n\n### SwiftPM\n\nAdd `.package(url: \"https://github.com/krzysztofzablocki/Difference.git\", branch: \"master\")` dependency in your Package manifest.\n\n## Using lldb\n\nWrite the following to see the difference between 2 instances:\n\n`po dumpDiff(expected, received)`\n\n\n## Integrate with XCTest\nAdd this to your test target:\n\n```swift\npublic func XCTAssertEqual\u003cT: Equatable\u003e(_ expected: @autoclosure () throws -\u003e T, _ received: @autoclosure () throws -\u003e T, file: StaticString = #filePath, line: UInt = #line) {\n    do {\n        let expected = try expected()\n        let received = try received()\n        XCTAssertTrue(expected == received, \"Found difference for \\n\" + diff(expected, received).joined(separator: \", \"), file: file, line: line)\n    }\n    catch {\n        XCTFail(\"Caught error while testing: \\(error)\", file: file, line: line)\n    }\n}\n```\n\nReplace `#filePath` with `#file` if you're using Xcode 11 or earlier.\n\n## Integrate with Quick\nAdd this to your test target:\n\n```swift\npublic func equalDiff\u003cT: Equatable\u003e(_ expectedValue: T?) -\u003e Matcher\u003cT\u003e {\n    return Matcher.define { actualExpression in\n        let receivedValue = try actualExpression.evaluate()\n\n        if receivedValue == nil {\n            var message = ExpectationMessage.fail(\"\")\n            if let expectedValue = expectedValue {\n                message = ExpectationMessage.expectedCustomValueTo(\"equal \u003c\\(expectedValue)\u003e\", actual: \"nil\")\n            }\n            return MatcherResult(status: .fail, message: message)\n        }\n        if expectedValue == nil {\n            return MatcherResult(status: .fail, message: ExpectationMessage.fail(\"\").appendedBeNilHint())\n        }\n\n        return MatcherResult(bool: receivedValue == expectedValue, message: ExpectationMessage.fail(\"Found difference for \" + diff(expectedValue, receivedValue).joined(separator: \", \")))\n    }\n}\n```\n\nWrite the following to see the difference between 2 instances:\n`expect(received).to(equalDiff(expected))`\n\n## Integrate with The Composable Architecture\n\nIf you are using The Composable Architecture `nameLabels` configuration to get a diff that's more appropiate for reducer instrumentation\n\n```swift\ndiff(oldState, newState, indentationType: .pipe, nameLabels: .comparing)\n```\n\nYou can use this function in your own variant of [ReducerInstrumentation code based on this](https://github.com/pointfreeco/swift-composable-architecture/blob/e7dda73c35f1016c8ba82fd2b7c43757cce68e58/Sources/ComposableArchitecture/Debugging/ReducerDebugging.swift)\n\nThat way your diffs will look more like this:\n\n```swift\nReceived action:\n  AppAction.home(.howTo(.setSelectedSlide))\nState:\nhome:\n|\tselectedHowTo:\n|\t|\tselectedSlide:\n|\t|\t|\tCurrent: 8mnkni91h4fe\n|\t|\t|\tPrevious: exei4wpqsmdk\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrzysztofzablocki%2FDifference","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrzysztofzablocki%2FDifference","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrzysztofzablocki%2FDifference/lists"}