Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BDD DEVit

BDD DEVit

Pawel Dudek

June 11, 2018
Tweet

More Decks by Pawel Dudek

Other Decks in Programming

Transcript

  1. A method by which individual units of source code, sets

    of one or more program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use. --Kolawa, Adam; Huizinga, Dorota (2007) 5
  2. A method by which individual units of source code, sets

    of one or more program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use. --Kolawa, Adam; Huizinga, Dorota (2007) 7
  3. An app is a set of behaviors created by a

    programmer and expected by the user. 9
  4. class DolphinSpec: QuickSpec { override func spec() { it("is friendly")

    { expect(Dolphin().isFriendly).to(beTruthy()) } it("is smart") { expect(Dolphin().isSmart).to(beTruthy()) } } }
  5. class DolphinSpec: QuickSpec { override func spec() { it("is friendly")

    { expect(Dolphin().isFriendly).to(beTruthy()) } it("is smart") { expect(Dolphin().isSmart).to(beTruthy()) } } }
  6. describe("a dolphin") { describe("its click") { it("is loud") { let

    click = Dolphin().click() expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { let click = Dolphin().click() expect(click.hasHighFrequency).to(beTruthy()) } } }
  7. describe("a dolphin") { describe("its click") { it("is loud") { let

    click = Dolphin().click() expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { let click = Dolphin().click() expect(click.hasHighFrequency).to(beTruthy()) } } }
  8. describe("a dolphin") { describe("its click") { it("is loud") { let

    click = Dolphin().click() expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { let click = Dolphin().click() expect(click.hasHighFrequency).to(beTruthy()) } } }
  9. describe("a dolphin") { var dolphin: Dolphin! beforeEach { dolphin =

    Dolphin() } describe("its click") { var click: Click! beforeEach { click = dolphin.click() } it("is loud") { expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { expect(click.hasHighFrequency).to(beTruthy()) } } }
  10. describe("a dolphin") { var dolphin: Dolphin! beforeEach { dolphin =

    Dolphin() } describe("its click") { var click: Click! beforeEach { click = dolphin.click() } it("is loud") { expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { expect(click.hasHighFrequency).to(beTruthy()) } } }
  11. describe("a dolphin") { var dolphin: Dolphin! beforeEach { dolphin =

    Dolphin() } describe("its click") { var click: Click! beforeEach { click = dolphin.click() } it("is loud") { expect(click.isLoud).to(beTruthy()) } it("has a high frequency") { expect(click.hasHighFrequency).to(beTruthy()) } } }
  12. class PhotoUploadViewController: UIViewController { let photoUploader: PhotoUploader required init(photoUploader: PhotoUploader)

    { self.photoUploader = photoUploader super.init(nibName: nil, bundle: nil) navigationItem.rightBarButtonItem = UIBarButtonItem( title: "Done", target: self, action: #selector(PhotoUploadViewController.onTap(_:))) } @objc func onTap(_ item: UIBarButtonItem?) { photoUploader.upload(photo: UIImage()) { success in print("\(success)") } } }
  13. protocol PhotoUploader { func upload(photo: UIImage, completion: (_ success: Bool)

    -> Void) } class MockPhotoUploader: PhotoUploader { fileprivate(set) var photoUploadCalled: Bool = false func upload(photo: UIImage, completion: (_ success: Bool) -> Void) { self.photoUploadCalled = true } }
  14. var sut: PhotoUploadViewController! var mockPhotoUploader: MockPhotoUploader! beforeEach { mockPhotoUploader =

    MockPhotoUploader() sut = PhotoUploadViewController(photoUploader: mockPhotoUploader) } afterEach { sut = nil }
  15. // non-bdd describe("right bar button item") { var rightBarButtonItem: UIBarButtonItem?

    beforeEach { rightBarButtonItem = sut.navigationItem.rightBarButtonItem } it("should have a target") { let actual = rightBarButtonItem?.target as? PhotoUploadViewController expect(actual).to(equal(sut)) } it("should have an action") { let expected = #selector(PhotoUploadViewController.onTap(_:)) expect(rightBarButtonItem?.action).to(equal(expected)) } }
  16. // non-bdd describe("right bar button item action") { beforeEach {

    let rightBarButtonItem = sut.navigationItem.rightBarButtonItem sut.onTap(rightBarButtonItem) } it("should tell the photo uploader to upload photo") { expect(fakePhotoUploader.photoUploadCalled).to(beTruthy()) } }
  17. // bdd describe("right bar button item") { var rightBarButtonItem: UIBarButtonItem?

    beforeEach { rightBarButtonItem = sut.navigationItem.rightBarButtonItem } describe("when it is tapped") { beforeEach { rightBarButtonItem?.specSimulateTap() } it("should tell the photo uploader to upload photo") { expect(fakePhotoUploader.photoUploadCalled).to(beTruthy()) } } }
  18. BDD - recap » Tests influence your architecture » No

    such thing as untestable behavior » Think examples/behaviors, not tests » Don’t test implementation, work outside-in » Use ubiquitous language to make examples easily understandable 61