SleipnirBDD style testing for Swift
Who we are• Mobile team at railsware.com
• Open source fans railsware.github.io/
Outline• What is BDD
• Testing in Swift - XCTest vs BDD style
• What Sleipnir is
• How to use it
• Questions
BDD
BDDBehavior Driven Development
BDDBehavior Driven Development
• BDD specifies that tests of any unit of software should be specified in terms of the desired behaviour of the unit. (from Wiki)
!• BDD is all about specifications
BDDdescribe("Calculator") { ! describe("#add") { ! it("returns the sum of its arguments") { expect(Calculator().add(1, 2)).to(equal(3)) } } }
Testing in Swift
Testing in Swift - XCTestclass BookTest : XCTestCase { func testPersonHasName() { let person = Person(name: "John Doe”) ! XCTAssertNotNil(person.name, "name should not be nil") XCTAssertEqual(person.name, "John Doe", "incorrect name") } }
Testing in Swift - XCTestclass BookTest : XCTestCase { func testPersonHasName() { let person = Person(name: "John Doe”) ! XCTAssertNotNil(person.name, "name should not be nil") XCTAssertEqual(person.name, "John Doe", "incorrect name") } }
Does not specify behavior of the `Person` class
Testing in Swift - BDDclass PersonSpec : SleipnirSpec { var personSpec = describe("Person") { let person = Person(name: "John Doe") context("name") { it("should not be nil") { expect(person.name).toNot(beNil()) } it("should be correct") { expect(person.name).to(equal("John Doe")) } } } }
Testing in Swift - BDD
Test code is a specification of a class:
• Person name should not be nil
• Person name should be correct
Introducing Sleipnirhttps://github.com/railsware/Sleipnir
What Sleipnir isMythological steed of Odin, Norse God
What Sleipnir isBDD-style framework for Swift
What Sleipnir isclass HorseSpec : SleipnirSpec { var spec = describe("Horse") { context("usual") { it("is not awesome") { let usualHorse = UsualHorse() expect(usualHorse.legsCount).to(equal(4)) usualHorse.isAwesome.should.beFalse() } } context("Sleipnir") { it("is awesome") { let sleipnirHorse = Sleipnir() expect(sleipnirHorse.legsCount).to(equal(8)) sleipnirHorse.isAwesome.should.beTrue() } } } }
Core principles• Not using XCTest
• Pure Swift BDD testing framework
• Command line output
• Seeded random tests invocation
How to use it
Running specs
1. Create a test target in Xcode
2. Invoke Runner.run() method in main.swift
3. Run test target
Running specsRunning With Random Seed: 7197 !...F...... !!FAILURE Some spec should pass: /Path/To/Your/Specs/SomeSpec.swift:27 Expected <1> to equal <3> !!Finished in 0.0102 seconds !10 examples, 1 failures
Setup/Teardown blocks
• beforeEach { }
• afterEach { }
• beforeAll { }
• afterAll { }
Setup/Teardown blockslet someSpec = describe("Some spec") { var someArray: [Int]? ! beforeEach { someArray = [1, 2, 3] } afterEach { someArray = nil } it("should pass") { expect(someArray).toNot(beNil()) expect(someArray).to(contain(3)) } }
Focused specs
Focus means “Run only focused stuff”
Useful in a project with a lot of specs
Focused specsdescribe("Some spec") { fit("focused") { // WILL RUN } it("not focused") { // WILL NOT RUN } }
Focused specsfdescribe("focused group") { // ... } !fcontext("focused group") { // ... } fit("focused example") { // ... }
Pending specs
Pending means “Don’t run this stuff”
Useful to denote an example that does not pass yet
Pending specs
xdescribe("Pending group") { it("will not run") { expect(false).to(beTrue()) } it("is pending", PENDING) }
Running With Random Seed: 2428 !...P....... !PENDING Pending group is pending !!Finished in 0.0062 seconds !11 examples, 0 failures, 1 pending
Shared example groups
Useful for extracting common specs
Allow to run same specs in different context
Shared example groupssharedExamplesFor("some awesome stuff") { (sharedContext : SharedContext) in var stuff: Stuff? beforeEach { stuff = sharedContext()["stuff"] as Stuff } it("should be awesome") { expect(stuff.awesome).to(beTrue()) } }
Matchers
• equal
• beNil
• beFalse/beTrue
• beGreaterThan/beLessThan
expect(3).to(equal(3))
expect(3).toNot(beNil())
expect(true).to(beTrue())
expect(3).to(beGreaterThan(1))
Matchers on collections/strings
• contain
• beginWith/endWith
• beEmpty
expect([1,2,3]).to(contain(1,2))
expect("foobar").to(beginWith("foo"))
expect([1,2,3]).toNot(beEmpty())
Questions?https://github.com/railsware/Sleipnir
Top Related