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

Testes - A que será que se destina?

Testes - A que será que se destina?

Uma talk baseada em exemplos reais de implementações de testes, a partir de experências práticas e conceitos teóricos. Os objetivos são: encorajar a implementação da cultura de testes; Para aqueles que já o fazem, aprimorar a qualidade de testes implantados; E que o conteúdo apresentado seja orientador para os que se interessem pelo tema.

Ronan Rodrigo Nunes

November 09, 2019
Tweet

More Decks by Ronan Rodrigo Nunes

Other Decks in Programming

Transcript

  1. Testes: A que será
    que se destina?
    Breve história sobre testes, boas e más práticas no ecossistema
    Apple
    Ronan Rodrigo Nunes

    View Slide

  2. Arqueologia

    View Slide

  3. View Slide

  4. …1956
    Debugging-oriented
    Sem distinção entre testes e
    debugging

    View Slide

  5. 1957 ~ 78
    Demonstration-oriented
    Garantir o atendimento de
    requisitos de software

    View Slide

  6. 1979 ~ 82
    Destruction-Oriented
    Detectar falhas de implementações

    View Slide

  7. 1983 ~ 87
    Evaluation-Oriented
    Detectar falhas nos requisitos e no
    design e implementação

    View Slide

  8. 1988…
    Prevention-Oriented
    Evitar falhas nos requisitos, design
    e implementação

    View Slide

  9. 2003
    Xcode 1.0
    Sem tool para testes

    View Slide

  10. 2005
    Xcode 2.1
    Primeira versão com suporte a
    testes unitários (OCUnit)

    View Slide

  11. 2007
    Xcode 3.0
    Primeiro com SDK do iOS

    View Slide

  12. 2013
    Xcode 5.0
    Substituição do OCUnit por XCTest

    View Slide

  13. 2015
    Xcode 7.0
    Primeiro com XCUITest

    View Slide

  14. Cultura

    View Slide

  15. View Slide

  16. Meu código funciona
    perfeitamente, por
    que eu testaria?

    View Slide

  17. Não vejo benefício;

    View Slide

  18. Até APP com testes
    tem bugs

    View Slide

  19. Não sei como, nem o
    que testar.

    View Slide

  20. Não temos tempo

    View Slide

  21. É difícil e complicado

    View Slide

  22. Como melhorar a
    cultura de testes do
    meu time?

    http://mobster.cc

    View Slide

  23. O que testar

    View Slide

  24. Pirâmide de
    testes

    View Slide

  25. Unit
    Integration
    UI
    Mais
    Isolamento
    Mais
    Integração
    Rápido
    Lento

    View Slide

  26. Boas práticas &
    Smells &
    Armadilhas

    View Slide

  27. func test_primaryButtonTapped_doesRouteToFullSheet() {
    // given
    XCTAssertTrue(router.routeToFullSheetCallCount == 0)
    // when
    interactor.primaryButtonTapped()
    // then
    XCTAssertTrue(router.routeToFullSheetCallCount == 1)
    }

    View Slide

  28. func test_primaryButtonTapped_doesRouteToFullSheet() {
    XCTAssertTrue(router.routeToFullSheetCallCount == 0)
    interactor.primaryButtonTapped()
    XCTAssertTrue(router.routeToFullSheetCallCount == 1)
    }

    View Slide

  29. func test_primaryButtonTapped_doesRouteToFullSheet() {
    interactor.primaryButtonTapped()
    XCTAssertTrue(router.routeToFullSheetCallCount == 1)
    }

    View Slide

  30. func test_primaryButtonTapped_doesRouteToFullSheet() {
    interactor.primaryButtonTapped()
    XCTAssertEqual(router.routeToFullSheetCallCount, 1)
    }

    View Slide

  31. func test_startReport_doesRouteToReportFlow() {
    interactor.startReport()
    XCTAssertEqual(router.routeToReportFlowCallCount, 1)
    }

    View Slide

  32. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    // ...
    guard let expectedGroupedFoods = expectedGroupedFoods,
    firstGroup = expectedGroupedFoods.first else {
    XCTFail("empty expectedGroupedFoods")
    }
    XCTAssertFalse(firstGroup.foods.isEmpty)
    }

    View Slide

  33. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    // ...
    XCTAssertFalse(expectedGroupedFoods!.first!.foods.isEmpty)
    }

    View Slide

  34. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    // ...
    if let expectedGroupedFoods = expectedGroupedFoods {
    if let firstGroup = expectedGroupedFoods.first {
    XCTAssertFalse(firstGroup.foods.isEmpty)
    }
    }
    }

    View Slide

  35. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    // ...
    XCTAssertEqual(expectedGroupedFoods?.first?.foods.isEmpty,
    false)
    XCTAssertEqual(expectedGroupedFoods?.first?.foods.count, 4)
    }

    View Slide

  36. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    let month = MonthGatewayFactory.make().month(number: 1)
    gateway.all(byMonth: month) { expectedGroupedFoods = $0.data }
    XCTAssertEqual(expectedGroupedFoods?.isEmpty, false)
    }

    View Slide

  37. func test_allByMonth_existingMonth_callCompletionWithItems() {
    var expectedGroupedFoods: [GroupedFoods]?
    let month = MonthGatewayFactory.make().month(number: 1)
    gateway.all(byMonth: month) {
    expectedGroupedFoods = $0.data
    }
    XCTAssertEqual(expectedGroupedFoods?.isEmpty, false)
    }

    View Slide

  38. func test_finishReport_completeFlow() {
    var completed = false
    interactor.waitForCompletion().subscribe { _ in
    completed = true
    }
    .disposed(by: disposeBag)
    interactor.finish()
    XCTAssertTrue(completed)
    }

    View Slide

  39. func test_finishReport_completeFlow() {
    var completed = false
    onCompleteFlow(completed = true)
    interactor.finish()
    XCTAssertTrue(completed)
    }
    func onCompleteFlow(_ fn: @escaping @autoclosure () -> ()) {
    interactor.waitForCompletion()
    .subscribe { _ in fn() }
    .disposeOnTearDown(testCase: self)
    }

    View Slide

  40. class ReportTripInteractorTests: XCTestCase
    class ReportTripInteractor_StartTripTests:
    ReportTripInteractorTests
    class ReportTripInteractor_FinishingTripTests:
    ReportTripInteractorTests
    class ReportTripInteractor_SearchingTripTests:
    ReportTripInteractorTests
    class ReportTripInteractor_WaintingTripTests:
    ReportTripInteractorTests

    View Slide

  41. func test_start_validInteractor_createEventAtStream() {
    let expectedResponse = Response(uuid: "id")
    shareService.fetchHandler = { _ in .just(expectedResponse) }
    worker.start(interactor)
    someStream.dataSubject
    .subscribe(onNext: { eventResponse in
    XCTAssertEqual(expectedResponse, eventResponse)
    })
    .disposed(by: disposeBag)
    }

    View Slide

  42. class Worker {
    func start(_ interactor: AnyInteractor) {
    someObservable
    .subscribe(someStream.dataSubject)
    .disposeOnStop(self)
    }
    }
    .subscribe(someStream.dataSubject)

    View Slide

  43. class Worker {
    func start(_ interactor: AnyInteractor) {
    someObservable
    .disposeOnStop(self)
    }
    }

    View Slide

  44. func test_start_validInteractor_createEventAtStream() {
    let expectedResponse = Response(uuid: "id")
    shareService.fetchHandler = { _ in .just(expectedResponse) }
    var eventResponse: Response?
    someStream.dataSubject
    .subscribe(onNext: { eventResponse = $0 })
    .disposed(by: disposeBag)
    worker.start(interactor)
    XCTAssertEqual(expectedResponse, eventResponse)
    }

    View Slide

  45. final class ListFoodPresenterViewControllerTests: XCTestCase {
    private let bindable: ListFoodTableViewControllerBindMock!
    private let presenter: ListFoodPresenterViewController!
    override func setUp() {
    super.setUp()
    bindable = ListFoodTableViewControllerBindMock()
    presenter = ListFoodPresenterViewController()
    presenter.bindable = bindable
    }
    }
    !

    View Slide

  46. final class ListFoodPresenterViewControllerTests: XCTestCase {
    private let bindable = ListFoodTableViewControllerBindMock()
    private let presenter = ListFoodPresenterViewController()
    override func setUp() {
    super.setUp()
    presenter.bindable = bindable
    }
    }

    View Slide

  47. final class ListFoodPresenterViewControllerTests: XCTestCase {
    private let bindable = ListFoodTableViewControllerBindMock()
    private lazy var presenter: ListFoodPresenterViewController = {
    let presenter = ListFoodPresenterViewController()
    presenter.bindable = bindable
    return presenter
    }()
    }

    View Slide

  48. Obrigado

    View Slide

  49. Obrigado
    ronanrodrigo.com

    View Slide