{"id":19010311,"url":"https://github.com/railsware/sleipnir","last_synced_at":"2025-04-04T19:09:51.029Z","repository":{"id":17943155,"uuid":"20923386","full_name":"railsware/Sleipnir","owner":"railsware","description":"BDD-style framework for Swift","archived":false,"fork":false,"pushed_at":"2016-04-04T14:22:32.000Z","size":1602,"stargazers_count":841,"open_issues_count":10,"forks_count":48,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-03-28T18:11:14.071Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://railsware.com/blog/2014/07/04/bdd-style-testing-in-swift-with-sleipnir","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/railsware.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"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-06-17T13:00:55.000Z","updated_at":"2025-03-15T20:59:05.000Z","dependencies_parsed_at":"2022-08-27T19:40:08.995Z","dependency_job_id":null,"html_url":"https://github.com/railsware/Sleipnir","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2FSleipnir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2FSleipnir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2FSleipnir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railsware%2FSleipnir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/railsware","download_url":"https://codeload.github.com/railsware/Sleipnir/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247234921,"owners_count":20905854,"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":[],"created_at":"2024-11-08T19:10:50.363Z","updated_at":"2025-04-04T19:09:51.012Z","avatar_url":"https://github.com/railsware.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg height=\"300\" width=\"300\" src=\"logo.png\" /\u003e\n\u003c/p\u003e\n\n# Sleipnir\n\nSleipnir is a BDD-style framework for Swift. Sleipnir is highly inspired by [Cedar](https://github.com/pivotal/cedar). \nAlso\n\u003e In Norse mythology, [Sleipnir](http://en.wikipedia.org/wiki/Sleipnir) is Odin's steed, is the child of Loki and Svaðilfari, is described as the best of all horses, and is sometimes ridden to the location of Hel. \n  \n```swift\nclass SampleSpec : SleipnirSpec {\n    var spec : () = describe(\"Horse\") {\n        context(\"usual\") {\n            it(\"is not awesome\") {\n                let usualHorse = UsualHorse()\n                usualHorse.legsCount.should.equal(4)\n                expect(usualHorse.isAwesome()).to(beFalse())\n            }\n        }\n        \n        context(\"Sleipnir\") {\n            it(\"is awesome\") {\n                let sleipnirHorse = Sleipnir()\n                sleipnirHorse.legsCount.should.equal(8)\n                expect(sleipnirHorse.isAwesome()).to(beTrue())\n            }\n        }\n    }\n}\n```\n## Core principles\n\n* Sleipnir is not dependent of ```NSObject```, it is pure Swift BDD testing framework\n* Sleipnir is not using ```XCTest```\n* Sleipnir has nice command line output and support for custom test reporters\n* Other features, like seeded random tests invocation, focused and excluded examples/groups, etc.\n\n## Installation\n\n#### Manually (preferred way)\n\n1. Add Sleipnir as a submodule: `git submodule add https://github.com/railsware/sleipnir ThirdParty/Sleipnir`\n2. Drag'n'drop `Sleipnir.xcodeproj` to your test target\n3. Link `Sleipnir.framework`\n4. Start writing specs!\n\n#### Manually (from XCode Project template)\n\n1. Clone `Sleipnir` repo `git clone https://github.com/railsware/sleipnir /tmp/Sleipnir`\n2. Execute the following command `cd /tmp/Sleipnir \u0026\u0026 make install_templates`\n\nThe command will install templates for OSX and iOS projects and Spec file template as well.\n\n**Note:** this way you should manage framework updates on your own. Try to reinstall templates before creating new project/target from \"old\" ones\n\n#### Via CocoaPods\n\nYou can install statically built `Sleipnir.framework` into you project simply by adding it to the `Podfile`\n\n```\npod 'Sleipnir'\n```\n\n**Note: it is experimental way**\u003cbr\u003e\n**Current build does not work on iPhone Simulator, but works for OSX and iOS Devices**\n\n## Usage sample\n\nSee [LibrarySpec](https://github.com/railsware/Sleipnir/blob/master/Sample/Sample/LibrarySpec.swift) file in [Sample](https://github.com/railsware/Sleipnir/tree/master/Sample/Sample) project.\n\n## Writing specs\n\nAll spec classes should inherit from `SleipnirSpec`.\n\nRoot ExampleGroups in a spec should be assigned to some void variable. This allows specs to initialize correctly:\n```swift\nimport Sleipnir\n\nclass SomeSpec : SleipnirSpec {\n \n    let someSpec : () = describe(\"Some spec\") {\n        it(\"should pass\") {\n            expect(1).to(equal(1))\n        }\n    }\n    \n}\n```\n## Running specs\n\nIn order to run your specs you should invoke `Runner.run()` from the `main.swift` of your test target.\n\nThe default test runner will produce the following command line output, indicating all the failures and some meta information about each failure:\n```\nRunning With Random Seed: 1234\n\n.....F..\n\n\nFAILURE Some spec should pass:\n/Path/To/Your/Specs/TestSpec.swift:16 Expected \u003c1\u003e to equal \u003c2\u003e\n\n\nFinished in 0.0075 seconds\n\n8 examples, 1 failures\n```\n\n#### Seeded random specs run\n\nAll examples would run in random order with the random seed specified in output. If you would like to re-run tests in the same order you should pass a seed to `run()` method:\n```swift\nRunner.run(seed: 1234)\n```\n\n## Examples and ExampleGroups\n\nExampleGroups are created with `describe` or `context` keywords.\nWithin the block passed to ExampleGroup you can declare examples using the `it` keyword.\n\nExampleGroups can be nested in order to create clean structure of your tests.\n\nUnder the hood `describe` method creates an instance of `ExampleGroup` and evaluates the block passed to it. Blocks passed to examples are evaluated dynamically during the test execution.\n\n## Setup/Teardown code\n\nSleipnir supports some hooks to execute before or after examples. This allows to share some setup/teardown code between examples.\n\n`beforeEach` block will be executed before each example in the current group and all nested groups.\n\n`afterEach` block will be executed after each example.\n\n```swift\nclass SomeSpec : SleipnirSpec {\n \n    let someSpec : () = describe(\"Some spec\") {\n        var someArray: [Int]?\n        beforeEach {\n            someArray = [1, 2, 3]\n        }\n        \n        afterEach {\n            someArray = nil\n        }\n        \n        it(\"should pass\") {\n            expect(someArray).toNot(beNil())\n            expect(someArray).to(contain(3))\n        }\n    }\n    \n}\n```\nYou can also specify global setup/teardown blocks using `beforeAll` and `afterAll` keywords. \nThey will run once before or after all examples in the current group and all the nested groups.\n\n## Focused and excluded specs\n\nYou can specify examples and example groups to be focused by placing `f` letter before declaration: `fdescribe`, `fcontext`, `fit`. In this case the spec runner will only run focused examples/example groups and ignore all the others.\n\nYou can also mark an example or example group as `pending`. It won't run but will be printed along with the test results.\u003cbr\u003e \nTo mark something as `pending` add an `x` letter before declaration: `xdescribe`, `xcontext`, `xit`.\u003cbr\u003e\nExample can also be marked as `pending` by passing `PENDING` instead of spec block: \n```swift\nit(\"is pending\", PENDING)\n```\n## Shared example groups\n\nSleipnir supports extracting common specs through shared example groups.\u003cbr\u003e\nThey can include any number of `it`, `context`, `describe`, `before` and `after` blocks.\u003cbr\u003e\nYou can pass example-specific state into the shared example group through `sharedContext` dictionary.\n```swift\nvar nonNilObject : () =\n    sharedExamplesFor(\"a non-nil object\") { (sharedContext : SharedContext) in\n        var object: AnyObject?\n        beforeEach {\n            object = sharedContext()[\"object\"]\n        }\n        \n        it(\"should not be nil\") {\n            expect(object).toNot(beNil())\n        }\n    }\n\nvar spec : () = context(\"A non-nil object\") {\n    let someObject: String = \"Some Object\"\n    itShouldBehaveLike(\"a non-nil object\", { [\"object\" : someObject] })\n}\n```\n\nIf you don't need any context, you can use closures without parameters:\n```swift\nsharedExamplesFor(\"some awesome stuff\") {\n    it(\"should be awesome\") {\n        //...\n    }\n}\n\ndescribe(\"Some stuff\") {\n    itShouldBehaveLike(\"some awesome stuff\")\n}\n```\n\n## Expectations\n\nSleipnir supports defining expectations using `expect(someValue/expession).to(SomeMatcher)` syntax.\n```swift\nexpect(true).to(beTrue())\n```\n`expect` method supports passing values or a block of code in a closure:\n```swift\nexpect {\n    var x = 1\n    x++\n    return x\n}.to(equal(2))\n```\n\n### `Should` syntax\n\nIn addition to the `expect` syntax, Sleipnir supports the `should` syntax:\n```swift\nactual.should.equal(expected)\n[1, 2, 3].shouldNot.contain(4)\n```\n[See detailed information on the `should` syntax and its usage](https://github.com/railsware/Sleipnir/blob/master/ShouldSyntax.md)\n\n## Available matchers\n\n##### Equal\nValues must be [`Equatable`](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Equatable.html), [`Comparable`](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Comparable.html) or derive from `NSObject`.\n```swift\nexpect([1,2,3]).to(equal([1,2,3]))\nexpect(\"some string\").toNot(equal(\"another string\"))\nexpect(1) == 1\n```\n\n##### BeNil\n```swift\nexpect(nil).to(beNil())\nexpect(\"some string\").toNot(beNil())\n```\n\n##### BeTrue/BeFalse\n```swift\nexpect(true).to(beTrue())\nexpect(false).to(beFalse())\n```\n\n##### BeGreaterThan/BeLessThan\nValues must be [`Comparable`](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Comparable.html).\n```swift\nexpect(3).to(beGreaterThan(1))\nexpect(3) \u003e 1\n\nexpect(1).to(beLessThan(3))\nexpect(1) \u003c 3\n```\n\n##### BeGreaterThanOrEqualTo/BeLessThanOrEqualTo\nValues must be [`Comparable`](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Comparable.html).\n```swift\nexpect(3).to(beGreaterThanOrEqualTo(1))\nexpect(3) \u003e= 1\nexpect(1) \u003e= 1\n\nexpect(1).to(beLessThanOrEqualTo(3))\nexpect(1) \u003c= 3\nexpect(1) \u003c= 1\n```\n\n##### Collections/String matchers\nSleipnir supports some matchers on collections and strings:\n\n##### Contain\nMatches if an item is in the container. Supports Swift collections with [`Equatable`](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Equatable.html) elements, `NSArrays`, `NSSets` and `Strings`.\n```swift\nexpect([1,2,3]).to(contain(1))\nexpect(\"some string\").toNot(contain(\"another\"))\n```\n\n##### BeginWith/EndWith\nMatches if the container begins/ends with the specified element. Supports Swift collections with `Equatable` elements, `NSArrays` and `Strings`.\n```swift\nexpect([1,2,3]).to(beginWith(1))\nexpect(\"some string\").to(endWith(\"string\"))\n```\n\n##### BeEmpty\nMatches if a container is empty.\n```swift\nexpect(\"\").to(beEmpty())\nexpect([1,2,3]).toNot(beEmpty())\n```\n\n## TODO\n\n- [x] Ease of distribution (CocoaPods probably)\n- [x] XCode templates\n- [x] Shared examples support\n- [x] ```should``` syntax support\n- [ ] asynchronous matchers (```will```, ```willNot```, ```after```)\n\n## Who uses Sleipnir\n\n - [SGL](https://github.com/AlexDenisov/sgl) - Swift Generic Library\n\n## Contributing\n\nPlease read the [Contributor Guide](https://github.com/railsware/Sleipnir/blob/master/CONTRIBUTING.md).\n\n## License\n\nLicensed under MIT license. See the [LICENSE](https://github.com/railsware/Sleipnir/blob/master/LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsware%2Fsleipnir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frailsware%2Fsleipnir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailsware%2Fsleipnir/lists"}