XCTest is the testing framework in Xcode 5, later in Xcode 6 the performance testing is added to XCTest. Before XCTest people commonly used OCUnit tests, which can be converted to XCTest.

  1. XCTestCase:

    1. A test is a function begins with “test”, takes no parameter, returns (void). Tests will be grouped in testClass – test class has to extend XCTestCase.

      – (void)testThatItDoesURLEncoding { // test code }

    2. To disable a test, simply change the name of function, for example:

      – (void) DISABLED_testThatItDoesURLEncoding

    3. A test is divided into 3 parts: given – when – then
      1. Given: set up the environments (creating objects) and state for the test
      2. When: the code we want to test (usually just 1 function call)
      3. Then: check the results (using Assertions)
    4. Test classes are grouped in test bundles.
  2. Assertions

    1. Unconditional fail: XCTFail
    2. Equality tests:
      1. XCTAssertEqualObjects
      2. XCTAssertNotEqualObjects
      3. XCTAssertEqual
      4. XCTAssertNotEqual
      5. XCTAssertEqualWithAccuracy
      6. XCTAssertNotEqualWithAccuracy
      7. XCTAssertGreaterThan
      8. XCTAssertGreaterThanOrEqual
      9. XCTAssertLessThan
      10. XCTAssertLessThanOrEqual
    3. Nil tests:
      1. XCTAssertNil
      2. XCTAssertNotNil
    4. Boolean tests:
      1. XCTAssertTrue (or just XCTAssert)
      2. XCTAssertFalse
    5. Exception tests:
      1. XCTAssertThrows: fail when expression does not throw an exception.
      2. XCTAssertThrowsSpecific:
      3. XCTAssertThrowsSpecificNamed
      4. XCTAssertNoThrows
      5. XCTAssertNoThrowsSpecific
      6. XCTAssertNoThrowsSpecificNamed
  3. Flow of test execution

    1. XCTest finds all the test classes and, for each class, runs all of its test methods. (All test classes inherit from XCTestCase.)
    2. First, it runs class setup method + (void)setUp // before all tests
    3. For each test method, a new instance of the class is allocated and its instance setup method –(void)setUp executed. After that it runs the test method, and after that the instance teardown method –(void)tearDown. (repeats for all the test methods in the class).
    4. Executes the class teardown method + (void)tearDown // after all tests
    5. Moves on to the next class.
    6. Having class method and instance method with same name is perfectly fine !!! (just not best practice)
  4. Testing Guidelines

    • Define API requirements. for each method or function that you add to your project. For requirements, include:
      1. input and output ranges,
      2. exceptions thrown and
      3. the conditions under which exceptions are raised,
      4. the type of values returned (especially if the values are instances of classes).
    • Write test cases as you write code. it’s harder to write tests for existing code than for code you are writing.
    • Check boundary conditions.  include the lowest and highest values of the range.
      1. For example, if a parameter can have values between 0 and 100, inclusive, the test should pass the values 0, 50, and 100 for the parameter.
    • Use negative tests. verify code behaves correctly when it receives invalid or unexpected input values, also that it returns error codes or raises exceptions when it should.
      1. For example, if an integer parameter must have values in the range 0 to 100, inclusive, create test cases that pass the values -1 and 101 to ensure that the procedure raises an exception or returns an error code.
    • Write comprehensive test cases. Although simple, isolated tests provide value, stacked tests exercise complex behaviors and tend to catch many more problems.
      1. For example, in addition to adding objects to an array, you could create the array, add several objects to it, remove a few of them using different methods, and then ensure that the set and number of remaining objects are correct.
    • Cover your bug fixes with test cases. always write tests cases that verify the fix.