func testImageProcessing() {
// arrange
let image = UIImage(named: "cats")!
let manager = CatsProcessingManager()
// act
var cuteCats = 0
// creating an expectation to get number of cats.
let expectation = self.expectation(description: "Counting number of cats") //1
manager.findCuteCats(image: image) { (numberOfCuteCats) in
cuteCats = numberOfCuteCats
// we've got an answer. our expectation is fulfilled!
expectation.fulfill() //2
}
// assert
// let's wait 5 seconds before asserting...
waitForExpectations(timeout: 5.0, handler: nil) //3
XCTAssertEqual(cuteCats, 3)
}
Multiple fullfill, one expectation. expectedFulfillmentCount
- Dummy - Does nothing. Purpose: to fill the gap of instantiating objects
- Fake - always returns the same value
- Stub - control return value
- Spy - does not return anything. To record calls that can be asserted later
- Mock - assertion happens in Mock via `verify()` via `Bool`
Complete vs Partial Mocking - Partial is when mocking is done via subclassing. Partial should be avoided if possible
Avoid test doubles if possible
Test doubles considered as a code smell.
Types of Coupling
Subclass
Shared Objects - diff objects mutating properties of shared obj
//3
class func addNewTest(
withNames names : [String],
expectedResult : String,
testSuite : XCTestSuite
) {
for invocation in self.testInvocations {
let newTestCase = FullNamesGeneratorTests(invocati
on: invocation)
newTestCase.names = names
newTestCase.expectedFullName = expectedResult
testSuite.addTest(newTestCase)
}
}
//4
func testFullNameGenerator() {
var fullName = ""
for name in names {
fullName += name
if name != names.last! {
fullName += " "
}
}
XCTAssertEqual(fullName, expectedFullName)
}
}
1) `names`, `expectedFullName` - input and expected output from test method
2) Creation of new test suite with several test cases
3) `addNewTest` - for every `invocation` creates new test case into test suite
4) actual test method
By: Avi Tsadok 2020
Writing Tests
#file
and#line
- allows custom function to show fail feedback on correct test that failedXCTestExpectation
XCTestExpectation Pattern (see
//1
,//2
,//3
)expectedFulfillmentCount
isInverted
Test Doubles
Comparing
Equatable
protocol. egXCTAssertEqual(person1, person2)
Comparable
protocol. egXCTAssertGreaterThan(person1, person2)
XCTAssertEqual(image1, image2)
Parameterized Unit Tests
runTest
func testGenerateLayout_abstractMethod1() { var events = [Event]() events.append(Event(...)) // different data set ...
}
func testGenerateLayout_abstractMethod2() { var events = [Event]() events.append(Event(...)) ...
}
Invoke tests dynamically
defaultTestSuite()
variable - return own own XCTestSuite//2 override class var defaultTestSuite: XCTestSuite { get { let testSuite = XCTestSuite(name: NSStringFromClass(self))
}
//3 class func addNewTest( withNames names : [String], expectedResult : String, testSuite : XCTestSuite ) { for invocation in self.testInvocations {
}
//4 func testFullNameGenerator() { var fullName = "" for name in names { fullName += name if name != names.last! { fullName += " " } }
} }
<reading> expect more </reading>