{"id":19808730,"url":"https://github.com/lurado/lldo","last_synced_at":"2025-05-01T07:32:43.300Z","repository":{"id":42392678,"uuid":"173332515","full_name":"lurado/LLDO","owner":"lurado","description":"LLDB Automation with Swift","archived":false,"fork":false,"pushed_at":"2023-01-21T06:28:28.000Z","size":1717,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-02-28T08:06:01.375Z","etag":null,"topics":["debugging-tools","lldb","ui-automation"],"latest_commit_sha":null,"homepage":"https://lurado.github.io/LLDO/","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/lurado.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-01T16:17:57.000Z","updated_at":"2022-04-07T08:53:09.000Z","dependencies_parsed_at":"2023-02-12T08:16:20.546Z","dependency_job_id":null,"html_url":"https://github.com/lurado/LLDO","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lurado%2FLLDO","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lurado%2FLLDO/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lurado%2FLLDO/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lurado%2FLLDO/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lurado","download_url":"https://codeload.github.com/lurado/LLDO/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224245854,"owners_count":17279649,"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":["debugging-tools","lldb","ui-automation"],"created_at":"2024-11-12T09:14:39.558Z","updated_at":"2024-11-12T09:14:40.340Z","avatar_url":"https://github.com/lurado.png","language":"Swift","readme":"\n# LLDO - LLDB Automation with Swift\n\nWrite debugging helpers in Swift, combine them into powerful automation actions and run them as LLDB commands.\n\n\n## Example\n\n![LLDO Example](Screenshots/example.png)\n\nLet's say your app starts with a login form.\nHow often do you fill out that form every day?\nWouldn't it be nice to automate this? \nThat's what LLDO is for. \n\n\nSimply write some automation steps in a `login.swift` file\n\n```swift\nUIView.find(byAccessibilityID: \"username_input\")?.enterText(\"lldo@lurado.com\")\nUIView.find(byAccessibilityID: \"password_input\")?.enterText(\"awesome\")\nUISwitch.first()?.slide()\nUIButton.first()?.tap()\n```\n\nand call the combined action from LLDB: `(lldb) login`.\n\n\n### Try It\n\n1. Clone this repo\n1. Open `Example/LLDOSwiftHelper.xcodeproj`\n1. Run in the Simulator and wait to hit the breakpoint in `AppDelegate.applicationDidBecomeActive`.\n1. Type the following commands in the LLDB prompt:\n  - `command script import /path/to/LLDO` (make the LLDO commands available in LLDB)\n  - `lldo ../lldo_actions` (load LLDO helpers and automation actions)\n  - `login` (call `login` action)\n\nOf course, this works for all kinds of forms. Every workflow that brings your app into a desired state can be automated.\n\n\n## Helpers\n\nLLDO comes with a bunch of helper methods that make writing common automation actions very easy.\nIf you're using the example app, you can try out a few of them:\n\n```swift\n// Poking around\npo UIButton.first()\npo UIView.current.all(UILabel.self)\npo UIView.grep(\"Pass\")\npo UIView.find(byAccessibilityID: \"username_input\")\npo UIView.current.tree().filter { $0.isHidden }\n\n// Changing stuff\npo UITextField.first()?.enterText(\"mail@company.com\")\npo UISwitch.first()?.slide()\npo UIButton.first()?.tap()\n```\n\nCheck the documentation at [lurado.github.io/LLDO](https://lurado.github.io/LLDO) for a complete list.\n\n### Custom Helpers\n\nHelpers need to be extensions on existing classes (see `(lldb) help load_swift_file` for details).\nYou can develop them like any other code in a Xcode project. \n\n1. Run an application and pause it to start LLDB\n1. Use the `load_swift_file` command to load the file\n1. Call your helpers\n1. Adjust the implementation\n1. GOTO 1 (unfortunately loading a files twice in a LLDB session results in duplicate symbols)\n\n⚠️ Do **NOT** add these files to your target!\nHelpers commonly contain code that you would never write in your production app.\nFor debugging it's fine though.\n\n\n## Automation Actions\n\nLLDO actions are simple Swift files that contain a series of commands.\nEach file corresponds to an action of the same name, for example [`login.swift`](Example/lldo_actions/login.swift) will be turned into a `login` action.\n\nTo load all actions in a folder, use the `lldo` or `load_lldo_actions` commands. \nBy default these commands look for a `lldo_actions` folder, located next to the source file of the current breakpoint.\n\n⚠️ Again, do **NOT** add these files to your target either! \nThey are for debugging purpose only and should not be shipped with your app.\n\n\n## Setup and Usage\n\nTo not have to manually import the path to LLDO in every LLDB session, add the following line to your `~/.lldbinit`:\n\n```\ncommand script import /path/to/LLDO\n```\n\nThis always loads LLDO's LLDB commands and makes them available in every project.\n\nYou can use breakpoints to further automate the initialization.\nFor example a symbolic breakpoint in `@objc \u003cmodule\u003e.\u003cAppDelegate\u003e.init` (e.g. `@objc LLDO.AppDelegate.init`) can be used to load LLDO.\n\n![Symbolic Breakpoint to load LLDO](Screenshots/lldo_breakpoint.png)\n\nThis would also load all actions in a `lldo_actions` folder next to your Xcode project/workspace file.\n\nLikewise breakpoints can be used to trigger actions. \nFor instance a breakpoint in `applicationDidBecomeActive` can be used to call the `login` action in the example app.\n\n![Breakpoint to call the login action](Screenshots/login_breakpoint.png)\n\nIt's important to check \"Automatically continue\" for those breakpoints. \nOtherwise you would have to press \"Continue\" every time the breakpoints are hit.\n\nIf your whole team uses LLDO, you can share common breakpoints by right clicking them and selecting \"Share Breakpoint\".\n\n\n### Pure Objective-C Projects On a Device\n\nTo be able to use the Swift helpers (and thus LLDO) in an Objective-C project on an iOS device, you need to bundle the necessary Swift runtime libraries:\n\n1. Add a single Swift file\n1. Do **not** create a bridging header\n1. make sure you `import UIKit`\n\nIf you are curious why this is necessary, see `(lldb) help load_swift_runtime` for details.\n\n\n## Credits\n\nThis project has been heavily inspired by [@kastiglione](https://twitter.com/kastiglione). You should check out his [talk](https://www.youtube.com/watch?v=9Io2_W1iDLQ).\n\n## LICENSE\n\nMIT - see [LICENSE](LICENSE) file.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flurado%2Flldo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flurado%2Flldo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flurado%2Flldo/lists"}