SlideShare une entreprise Scribd logo
1  sur  116
Télécharger pour lire hors ligne
testing?
doesyourappdo
whatyouthink
itdoes?
how?
runtheapp
println()
notthat
simple
bigapp?
workingwith
others?
works?
manualtesting
doesn’tscale
manualtesting
isvague
automated
testsarefast
automated
testsareprecise
testingapps
isawesome
testingappsiscoolwhen
you’repartofateam
sometestsaremore
awesomethanothers
goodtests
areclear
ARRANGE
ACT
ASSERT
ARRANGE
ACT
ASSERT
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
let dataSource = RecipientsTableViewDataSource()
let controller = RecipientsViewController(dataSource: dataSource)
let _ = controller.view
// Act: Perform the action that triggers the change we want to test
dataSource.recipients.append(Recipient(name: "Galois"))
// Assert: Confirm the action had the intended effects
XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2,
"Expected view controller's table view to contain two cells")
let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath)
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS",
"Expected cell for newly added person would be first in the table")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Arrange: Prepare the view controller
// Act: None in this case
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(cell!.textLabel!.text!, "+")
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(cell!.textLabel!.text!, "GALOIS")
}
func testTableViewAfterAddingPersonStillContainsAddCell() {
// Arrange: Prepare the view controller
// Act: Add a person
XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1)
XCTAssertEqual(lastCell!.textLabel!.text!, "+")
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
class RecipientsViewControllerTests: XCTestCase {
var dataSource: RecipientsTableViewDataSource!
var viewController: RecipientsViewController!
override func setUp() {
// Arrange: Prepare the view controller
dataSource = RecipientsTableViewDataSource()
viewController = RecipientsViewController(dataSource: dataSource)
}
func testTableViewBeforeAddingAnyCellsContainsAddCell() {
// Act: None in this case
// Assert: One cell in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
}
incremental
arrange
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
func testTableViewAfterAddingPersonContainsACellForThatPerson() {
// Act: Add a person
// Assert: First cell in table is "GALOIS"
}
func testTableViewWhenFullDoesNotContainAddCell() {
// Arrange: Add 5 people to table
// Act: None in this case
// Assert: Last cell in table view is not "+"
}
func testTableViewWhenFullDoesNotAddPeople() {
// Arrange: Add 5 people to table
// Act: Add another person
// Assert: Still only 5 people in table
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
var controller: RecipientsViewController!
var dataSource: RecipientsTableViewDataSource!
var fullController: RecipientsViewController!
var fullDataSource: RecipientsTableViewDataSource!
override func setUp() {
// Arrange #1: Prepare the empty view controller
dataSource = RecipientsTableViewDataSource()
controller = RecipientsViewController(dataSource: dataSource)
// Arrange #2: Prepare the full view controller
fullDataSource = RecipientsTableViewDataSource()
fullDataSource.recipients.extend([
Recipient(name: "Galois"),
Recipient(name: "Lagrange"),
Recipient(name: "Gauss"),
Recipient(name: "Riemann"),
Recipient(name: "Poincaré"),
])
fullController = RecipientsViewController(dataSource: fullDataSource)
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
describe("RecipientsTableViewDataSource") {
var dataSource: RecipientsTableViewDataSource!
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
describe("isFull") {
context("when it contains 5 or fewer people") {
it("returns false") { /* ... */ }
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois"), ...])
}
it("returns true") { /* ... */ }
}
}
}
example=test
examplegroup
=groupoftests
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias BeforeEachClosure = () -> ()
class ExampleGroup {
var beforeEachClosures = [BeforeEachClosure]()
var examples = [Example]()
weak var parent: ExampleGroup?
var children = [ExampleGroup]()
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
typealias ExampleClosure = () -> ()
class Example {
let exampleGroup: ExampleGroup
let closure: ExampleClosure
func run() { runBeforeEach(); closure() }
func runBeforeEach() {
var beforeEachClosures = [BeforeEachClosure]()
var group: ExampleGroup? = exampleGroup
while (group != nil) {
beforeEachClosures.extend(group!.beforeEachClosures.reverse())
group = group!.parent
}
for closure in beforeEachClosures.reverse() { closure() }
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
describe("isFull") {
beforeEach {
dataSource = RecipientsTableViewDataSource()
}
context("when it contains 5 or fewer people") {
it("returns false") {
XCTAssertFalse(dataSource.isFull)
}
}
context("when it contains 6 or more people") {
beforeEach {
dataSource.recipients.extend([Recipient(name: "Galois")])
}
it("returns true") {
XCTAssert(dataSource.isFull)
}
}
}
incrementalarrangeisa
killerfeature
✓ incremental teardown
✓ incremental teardown
afterEach {
// ...
}
✓ incremental teardown
✓ suite-wide arrange
beforeSuite {
// ...
}
✓ incremental teardown
✓ suite-wide arrange
✓ suite-wide teardown
beforeSuite {
// ...
}
afterSuite {
// ...
}
✓ incremental teardown
✓ suite-wide arrange
✓ suite-wide teardown
✓ shared assertions
sharedExamples("person cell") {
it("shows their name") {
// ...
}
}
itBehavesLike("person cell")
✓ incremental teardown
✓ suite-wide arrange
✓ suite-wide teardown
✓ shared assertions
✓ better asserts with Nimble
expect([1, 2, 3]).to(contain(2))
✓ incremental teardown
✓ suite-wide arrange
✓ suite-wide teardown
✓ shared assertions
✓ better asserts with Nimble
✓ custom asserts
expect(view).to(
haveValidSnapshot())
✓ incremental teardown
✓ suite-wide arrange
✓ suite-wide teardown
✓ shared assertions
✓ better asserts with Nimble
✓ custom asserts
✓ configurable
github.com/Quick/Quick
CiaraBrocklebank
<ciara.brocklebank@fb.com>
[Flatiron]FBNYHappyHour

Contenu connexe

Tendances

Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POPNatasha Murashev
 
Deep Dive into React Hooks
Deep Dive into React HooksDeep Dive into React Hooks
Deep Dive into React HooksFelix Kühl
 
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiNew improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiRobert Nyman
 
Owl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOwl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOdoo
 
Adventures In JavaScript Testing
Adventures In JavaScript TestingAdventures In JavaScript Testing
Adventures In JavaScript TestingThomas Fuchs
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testingjeresig
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascriptcrgwbr
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기NAVER SHOPPING
 
Simplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackSimplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackGabor Varadi
 
Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)Natasha Murashev
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript Glenn Stovall
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyMatthew Beale
 
State management in android applications
State management in android applicationsState management in android applications
State management in android applicationsGabor Varadi
 
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]Iakiv Kramarenko
 
Swift Montevideo Meetup - iPhone, una herramienta medica
Swift Montevideo Meetup - iPhone, una herramienta medicaSwift Montevideo Meetup - iPhone, una herramienta medica
Swift Montevideo Meetup - iPhone, una herramienta medicaWashington Miranda
 

Tendances (18)

Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
Deep Dive into React Hooks
Deep Dive into React HooksDeep Dive into React Hooks
Deep Dive into React Hooks
 
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiNew improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, Helsinki
 
Owl: The New Odoo UI Framework
Owl: The New Odoo UI FrameworkOwl: The New Odoo UI Framework
Owl: The New Odoo UI Framework
 
Adventures In JavaScript Testing
Adventures In JavaScript TestingAdventures In JavaScript Testing
Adventures In JavaScript Testing
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
 
04 Advanced Javascript
04 Advanced Javascript04 Advanced Javascript
04 Advanced Javascript
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기
 
Simplified Android Development with Simple-Stack
Simplified Android Development with Simple-StackSimplified Android Development with Simple-Stack
Simplified Android Development with Simple-Stack
 
Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)Protocol-Oriented MVVM (extended edition)
Protocol-Oriented MVVM (extended edition)
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript
 
Testing Ember Apps: Managing Dependency
Testing Ember Apps: Managing DependencyTesting Ember Apps: Managing Dependency
Testing Ember Apps: Managing Dependency
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
React lecture
React lectureReact lecture
React lecture
 
State management in android applications
State management in android applicationsState management in android applications
State management in android applications
 
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
Selenide alternative in Python - Introducing Selene [SeleniumCamp 2016]
 
Swift Montevideo Meetup - iPhone, una herramienta medica
Swift Montevideo Meetup - iPhone, una herramienta medicaSwift Montevideo Meetup - iPhone, una herramienta medica
Swift Montevideo Meetup - iPhone, una herramienta medica
 

Similaire à Quick: Better Tests via Incremental Setup

Cocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersCocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersStijn Willems
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF Luc Bors
 
Js 单元测试框架介绍
Js 单元测试框架介绍Js 单元测试框架介绍
Js 单元测试框架介绍louieuser
 
Test-driven Development with AEM
Test-driven Development with AEMTest-driven Development with AEM
Test-driven Development with AEMJan Wloka
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 SpringKiyotaka Oku
 
Accessing data with android cursors
Accessing data with android cursorsAccessing data with android cursors
Accessing data with android cursorsinfo_zybotech
 
Accessing data with android cursors
Accessing data with android cursorsAccessing data with android cursors
Accessing data with android cursorsinfo_zybotech
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Kevin Octavian
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportAnton Arhipov
 
The Ring programming language version 1.6 book - Part 70 of 189
The Ring programming language version 1.6 book - Part 70 of 189The Ring programming language version 1.6 book - Part 70 of 189
The Ring programming language version 1.6 book - Part 70 of 189Mahmoud Samir Fayed
 
Selenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkSelenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkDavid Rajah Selvaraj
 
Unittesting JavaScript with Evidence
Unittesting JavaScript with EvidenceUnittesting JavaScript with Evidence
Unittesting JavaScript with EvidenceTobie Langel
 

Similaire à Quick: Better Tests via Incremental Setup (20)

Cocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollersCocoa heads testing and viewcontrollers
Cocoa heads testing and viewcontrollers
 
Easy Button
Easy ButtonEasy Button
Easy Button
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
Js 单元测试框架介绍
Js 单元测试框架介绍Js 单元测试框架介绍
Js 单元测试框架介绍
 
iOS Talks 6: Unit Testing
iOS Talks 6: Unit TestingiOS Talks 6: Unit Testing
iOS Talks 6: Unit Testing
 
Test-driven Development with AEM
Test-driven Development with AEMTest-driven Development with AEM
Test-driven Development with AEM
 
Calculon
CalculonCalculon
Calculon
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
Jason parsing
Jason parsingJason parsing
Jason parsing
 
JJUG CCC 2011 Spring
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
 
Accessing data with android cursors
Accessing data with android cursorsAccessing data with android cursors
Accessing data with android cursors
 
Accessing data with android cursors
Accessing data with android cursorsAccessing data with android cursors
Accessing data with android cursors
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1Windows 8 Training Fundamental - 1
Windows 8 Training Fundamental - 1
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience Report
 
The Ring programming language version 1.6 book - Part 70 of 189
The Ring programming language version 1.6 book - Part 70 of 189The Ring programming language version 1.6 book - Part 70 of 189
The Ring programming language version 1.6 book - Part 70 of 189
 
Selenium Webdriver with data driven framework
Selenium Webdriver with data driven frameworkSelenium Webdriver with data driven framework
Selenium Webdriver with data driven framework
 
Deep dive into Oracle ADF
Deep dive into Oracle ADFDeep dive into Oracle ADF
Deep dive into Oracle ADF
 
Unittesting JavaScript with Evidence
Unittesting JavaScript with EvidenceUnittesting JavaScript with Evidence
Unittesting JavaScript with Evidence
 

Plus de Brian Gesiak

Property-Based Testing in Objective-C & Swift with Fox
Property-Based Testing in Objective-C & Swift with FoxProperty-Based Testing in Objective-C & Swift with Fox
Property-Based Testing in Objective-C & Swift with FoxBrian Gesiak
 
Intel® Xeon® Phi Coprocessor High Performance Programming
Intel® Xeon® Phi Coprocessor High Performance ProgrammingIntel® Xeon® Phi Coprocessor High Performance Programming
Intel® Xeon® Phi Coprocessor High Performance ProgrammingBrian Gesiak
 
iOS UI Component API Design
iOS UI Component API DesigniOS UI Component API Design
iOS UI Component API DesignBrian Gesiak
 
iOS UI Component API Design
iOS UI Component API DesigniOS UI Component API Design
iOS UI Component API DesignBrian Gesiak
 
Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered HarmfulBrian Gesiak
 
アップルのテンプレートは有害と考えられる
アップルのテンプレートは有害と考えられるアップルのテンプレートは有害と考えられる
アップルのテンプレートは有害と考えられるBrian Gesiak
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversBrian Gesiak
 
iOS Behavior-Driven Development
iOS Behavior-Driven DevelopmentiOS Behavior-Driven Development
iOS Behavior-Driven DevelopmentBrian Gesiak
 
iOSビヘイビア駆動開発
iOSビヘイビア駆動開発iOSビヘイビア駆動開発
iOSビヘイビア駆動開発Brian Gesiak
 

Plus de Brian Gesiak (10)

iOS API Design
iOS API DesigniOS API Design
iOS API Design
 
Property-Based Testing in Objective-C & Swift with Fox
Property-Based Testing in Objective-C & Swift with FoxProperty-Based Testing in Objective-C & Swift with Fox
Property-Based Testing in Objective-C & Swift with Fox
 
Intel® Xeon® Phi Coprocessor High Performance Programming
Intel® Xeon® Phi Coprocessor High Performance ProgrammingIntel® Xeon® Phi Coprocessor High Performance Programming
Intel® Xeon® Phi Coprocessor High Performance Programming
 
iOS UI Component API Design
iOS UI Component API DesigniOS UI Component API Design
iOS UI Component API Design
 
iOS UI Component API Design
iOS UI Component API DesigniOS UI Component API Design
iOS UI Component API Design
 
Apple Templates Considered Harmful
Apple Templates Considered HarmfulApple Templates Considered Harmful
Apple Templates Considered Harmful
 
アップルのテンプレートは有害と考えられる
アップルのテンプレートは有害と考えられるアップルのテンプレートは有害と考えられる
アップルのテンプレートは有害と考えられる
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
 
iOS Behavior-Driven Development
iOS Behavior-Driven DevelopmentiOS Behavior-Driven Development
iOS Behavior-Driven Development
 
iOSビヘイビア駆動開発
iOSビヘイビア駆動開発iOSビヘイビア駆動開発
iOSビヘイビア駆動開発
 

Dernier

Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 

Dernier (20)

Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 

Quick: Better Tests via Incremental Setup

  • 1.
  • 2.
  • 7.
  • 8.
  • 18.
  • 19.
  • 26. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 27. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 28. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 29. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 30. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 31. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller let dataSource = RecipientsTableViewDataSource() let controller = RecipientsViewController(dataSource: dataSource) let _ = controller.view // Act: Perform the action that triggers the change we want to test dataSource.recipients.append(Recipient(name: "Galois")) // Assert: Confirm the action had the intended effects XCTAssertEqual(controller.tableView.numberOfRowsInSection(0), 2, "Expected view controller's table view to contain two cells") let cellIndexPath = NSIndexPath(forRow: 0, inSection: 0) let cell = controller.tableView.cellForRowAtIndexPath(cellIndexPath) XCTAssertEqual(cell!.textLabel!.text!, "GALOIS", "Expected cell for newly added person would be first in the table") }
  • 32. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 33. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 34. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 35. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 36. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 37. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 38. func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Arrange: Prepare the view controller // Act: None in this case XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(cell!.textLabel!.text!, "+") } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(cell!.textLabel!.text!, "GALOIS") } func testTableViewAfterAddingPersonStillContainsAddCell() { // Arrange: Prepare the view controller // Act: Add a person XCTAssertEqual(viewController.tableView.numberOfRowsInSection(0), 1) XCTAssertEqual(lastCell!.textLabel!.text!, "+") }
  • 39. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 40. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 41. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 42. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 43. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 44. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 45. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 46. class RecipientsViewControllerTests: XCTestCase { var dataSource: RecipientsTableViewDataSource! var viewController: RecipientsViewController! override func setUp() { // Arrange: Prepare the view controller dataSource = RecipientsTableViewDataSource() viewController = RecipientsViewController(dataSource: dataSource) } func testTableViewBeforeAddingAnyCellsContainsAddCell() { // Act: None in this case // Assert: One cell in table } func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } }
  • 47.
  • 48.
  • 50.
  • 51.
  • 52. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 53. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 54. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 55. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 56. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 57. func testTableViewAfterAddingPersonContainsACellForThatPerson() { // Act: Add a person // Assert: First cell in table is "GALOIS" } func testTableViewWhenFullDoesNotContainAddCell() { // Arrange: Add 5 people to table // Act: None in this case // Assert: Last cell in table view is not "+" } func testTableViewWhenFullDoesNotAddPeople() { // Arrange: Add 5 people to table // Act: Add another person // Assert: Still only 5 people in table }
  • 58. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 59. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 60. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 61. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 62. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 63. var controller: RecipientsViewController! var dataSource: RecipientsTableViewDataSource! var fullController: RecipientsViewController! var fullDataSource: RecipientsTableViewDataSource! override func setUp() { // Arrange #1: Prepare the empty view controller dataSource = RecipientsTableViewDataSource() controller = RecipientsViewController(dataSource: dataSource) // Arrange #2: Prepare the full view controller fullDataSource = RecipientsTableViewDataSource() fullDataSource.recipients.extend([ Recipient(name: "Galois"), Recipient(name: "Lagrange"), Recipient(name: "Gauss"), Recipient(name: "Riemann"), Recipient(name: "Poincaré"), ]) fullController = RecipientsViewController(dataSource: fullDataSource) }
  • 64.
  • 65.
  • 66.
  • 67. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 68. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 69. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 70. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 71. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 72. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 73. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 74. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 75. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 76. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 77. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 78. describe("RecipientsTableViewDataSource") { var dataSource: RecipientsTableViewDataSource! beforeEach { dataSource = RecipientsTableViewDataSource() } describe("isFull") { context("when it contains 5 or fewer people") { it("returns false") { /* ... */ } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois"), ...]) } it("returns true") { /* ... */ } } } }
  • 81. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 82. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 83. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 84. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 85. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 86. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 87. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 88. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 89. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 90. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 91. typealias BeforeEachClosure = () -> () class ExampleGroup { var beforeEachClosures = [BeforeEachClosure]() var examples = [Example]() weak var parent: ExampleGroup? var children = [ExampleGroup]() }
  • 92. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 93. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 94. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 95. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 96. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 97. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 98. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 99. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 100. typealias ExampleClosure = () -> () class Example { let exampleGroup: ExampleGroup let closure: ExampleClosure func run() { runBeforeEach(); closure() } func runBeforeEach() { var beforeEachClosures = [BeforeEachClosure]() var group: ExampleGroup? = exampleGroup while (group != nil) { beforeEachClosures.extend(group!.beforeEachClosures.reverse()) group = group!.parent } for closure in beforeEachClosures.reverse() { closure() } } }
  • 101. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 102. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 103. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 104. describe("isFull") { beforeEach { dataSource = RecipientsTableViewDataSource() } context("when it contains 5 or fewer people") { it("returns false") { XCTAssertFalse(dataSource.isFull) } } context("when it contains 6 or more people") { beforeEach { dataSource.recipients.extend([Recipient(name: "Galois")]) } it("returns true") { XCTAssert(dataSource.isFull) } } }
  • 108. ✓ incremental teardown ✓ suite-wide arrange beforeSuite { // ... }
  • 109. ✓ incremental teardown ✓ suite-wide arrange ✓ suite-wide teardown beforeSuite { // ... } afterSuite { // ... }
  • 110. ✓ incremental teardown ✓ suite-wide arrange ✓ suite-wide teardown ✓ shared assertions sharedExamples("person cell") { it("shows their name") { // ... } } itBehavesLike("person cell")
  • 111. ✓ incremental teardown ✓ suite-wide arrange ✓ suite-wide teardown ✓ shared assertions ✓ better asserts with Nimble expect([1, 2, 3]).to(contain(2))
  • 112. ✓ incremental teardown ✓ suite-wide arrange ✓ suite-wide teardown ✓ shared assertions ✓ better asserts with Nimble ✓ custom asserts expect(view).to( haveValidSnapshot())
  • 113. ✓ incremental teardown ✓ suite-wide arrange ✓ suite-wide teardown ✓ shared assertions ✓ better asserts with Nimble ✓ custom asserts ✓ configurable
  • 115.