Skip to content

Unit Test Requirements

Tony Stone edited this page Apr 2, 2016 · 4 revisions

File Naming

Each class must have a corresponding test class of the same time suffixed with Test e.g. LinearRing+Surface.swift --> LinearRing+SurfaceTests.swift).

Test Class Naming

Within the single test file there must be a test class per combination of variants that will be tested named as follows:

<FileName-minus-extension>_<CoordinateType>_<PrecisionType>_<CoordinateReferenceSystemType>_Tests

Note that plus (+) signs in the file name should be translated to underscores (_).

For example, for the LinearRing+Surface.swift with several of its variants would look like:

class LinearRing_Surface_Coordinate2D_FixedPrecision_Cartesian_Tests: XCTestCase {}
class LinearRing_Surface_Coordinate2DM_FixedPrecision_Cartesian_Tests: XCTestCase {}
class LinearRing_Surface_Coordinate3D_FixedPrecision_Cartesian_Tests: XCTestCase {}

Test names will not include the variations but will follow the form:

test<Method-to-Test>_<Test-Variant-or-Parameter>_<Test-Variant-or-Parameter...>_<Result-Positive-Negative>

Examples:

func testArea_Triangle() {}
func testArea_RegularQuadrilateral() {}

MARK Requirement

Each class in the file must have a // MARK: Separator with the following form.

// MARK: - <CoordinateType>, <PrecisionType>, <CoordinateReferenceSystemType> -

Note that the dashes (-) are required so that the display in Xcode is enclosed with lines on top and bottom.

Example:

// MARK: - Coordinate2D, FixedPrecision, Cartesian -

class LinearRing_Surface_Coordinate2D_FixedPrecision_Cartesian_Tests: XCTestCase {}

// MARK: - Coordinate2DM, FixedPrecision, Cartesian -

class LinearRing_Surface_Coordinate2DM_FixedPrecision_Cartesian_Tests: XCTestCase {}

Assert Rules

Single Assert

Each test method should only have 1 assert statement testing the state of the object after the functionality was exercised unless there is no other way to test that the state of the object is correct.

Expressive failure messages

When asserting for equality of 2 Equatable types use of XCTAssertEquals in special cases where == is defined but the class is not Equatable, use XCTAssertTrue and XCTAssertFalse and explicitly add a message about what the test value is and the expected value.

Valid Examples:

XCTAssertEqual(Point<Coordinate2D>(coordinate: (x: 1.0, y: 1.0)), Point<Coordinate2D>(coordinate: (x: 1.0, y: 1.0)))

XCTAssertTrue(geometry == expected, "\(geometry) is not equal to \(expected)")

Invalid Examples:

XCTAssertEqual(Point<Coordinate2D>(coordinate: (x: 1.0, y: 1.0)) == Point<Coordinate2D>(coordinate: (x: 1.0, y: 1.0)), true)

Using XCTAssertEqual as in the above example should never be used because the result output on failure will be "Optional(0) is not equal to Optional(1)" which is a meaningless message.

Full Example

The example below is testing the Point.swift file and the test file itself is named PointTests.swift.

// MARK: - Coordinate2D, FloatingPrecision, Cartesian -

class Point_Coordinate2D_FloatingPrecision_Cartesian_Tests: XCTestCase {
    
    let precision = FloatingPrecision()
    let crs       = Cartesian()
    
    func testInit() {
        let point = Point<Coordinate2D>(coordinate: (x: 1.001, y: 1.001), precision: precision, coordinateReferenceSystem: crs)
        
        XCTAssertEqual(point.x, 1.001)
        XCTAssertEqual(point.y, 1.001)
    }
    
    func testEquals_IntOne_True() {
        XCTAssertEqual(Point<Coordinate2D>(coordinate: (x: 1.001, y: 1.001), precision: precision, coordinateReferenceSystem: crs), Point<Coordinate2D>(coordinate: (x: 1.001, y: 1.001), precision: precision, coordinateReferenceSystem: crs))
    }
    
    func testEquals_IntOne_False() {
        XCTAssertNotEqual(Point<Coordinate2D>(coordinate: (x: 1.001, y: 1.001), precision: precision, coordinateReferenceSystem: crs), Point<Coordinate2D>(coordinate: (x: 2.0, y: 2.0), precision: precision, coordinateReferenceSystem: crs))
    }
    
    func testIsEmpty() {
        XCTAssertEqual(Point<Coordinate2D>(coordinate: (x: 1.001, y: 1.001), precision: precision, coordinateReferenceSystem: crs).isEmpty(), false)
    }
}

Init method of this object required multiple asserts to completely test the state of the object after construction. Constructors are the rare example of when the 1 assert rule is not possible.