[Legacy] Testing trong iOS project với XCTest Framework

Posted on April 18th, 2019

XCTest framework

XCTest là một testing framework được tích hợp vào Xcode cung cấp khả năng testing cho các Xcode project. Nó hỗ trợ 3 loại testing bao gồm: Unit testing, Performance testing và UI testing. XCTest được Apple tích hợp kể từ Xcode 5 và hoàn toàn tương thích với 2 ngôn ngữ chính trong ecosystem của hãng là Objective-C và mới hơn là Swift.

  • Ưu điểm

    • Dễ tiếp cận và làm quen
    • Không cần cài đặt gì thêm, ngoài Xcode
    • Hàng chính chủ nên sẽ nhanh hơn các framework bên thứ ba
  • Nhược điểm

    • Không support cross-platform (vì đi theo Xcode)
    • Không hỗ trợ viết test theo style BDD, TDD

XCTest class

Cung cấp những function được dùng chung bởi XCTestCase và XCTestSuite dành cho việc tạo mới, quản lý và thực thi test. Trong hầu hết trường hợp, nên dùng trực tiếp class con XCTestCase khi định nghĩa các bộ test trong dự án.

class XCTest: NSObject

XCTestCase class

Là class dùng cho việc định nghĩa test cases, test methods, performance tests. Trong đó, một test case là tập các test methods liên quan nhau, và có thể bao gồm setUp và tearDown chạy trước và sau mỗi test.

class XCTestCase: XCTest

Định nghĩa các test cases và test methods

Có thể thêm các test vào trong Xcode project bằng cách viết những test functions, trong đó mỗi function chịu trách nhiệm verify một phần trong code. Những test function có liên quan được nhóm lại với nhau trong một test case. Mỗi test case là một class kế thừa từ class XCTestCase

Các bước viết test script:

  • Tạo mới một class là subclass của XCTestCase
  • Thêm các test method vào class vừa tạo
  • Thêm các test assertion vào test method

Một test methods bắt buộc các điều kiện sau đây:

  • Không có tham số đầu vào
  • Không có giá trị trả về
  • Tên test method bắt đầu bằng chữ test. Xcode sẽ tự động detect ra các test methods trong Test Navigator
func testUserLogin(){
    // action
    // assertion
}

setUp và tearDown

Có nhiệm vụ khởi tạo các giá trị trước khi thực thi một test script, và dọn dẹp sau khi các test script chạy xong. Trong đó:

  • Có 2 loại setUp:

    • setUp class: chạy trước tất cả các test script
    • setUp instance: chạy trước mỗi test script
  • Có 3 loại tearDown

    • tearDown class: chạy sau khi tất cả test script đã chạy xong
    • tearDown instance: chạy sau mỗi test script
    • addTeardownBlock chạy sau một test script nhất định, mà có khai báo function này trong script.
import XCTest

class SampleSetupAndTeardownTestCase: XCTestCase {
    
    override class func setUp() { // 1.
        super.setUp()
        // This is the setUp() class method.
        // It is called before the first test method begins.
        // Set up any overall initial state here.
        print("setUp class method")
    }
    
    override func setUp() { // 2.
        super.setUp()
        // This is the setUp() instance method.
        // It is called before each test method begins.
        // Set up any per-test state here.
        print("setUp instance method")
    }
    
    func testMethod1() { // 3.
        // This is the first test method.
        // Your testing code goes here.
        addTeardownBlock { // 4.
            // Called when testMethod1() ends.
            print("testMethod1 - addTeardownBlock method")
        }
    }
    
    func testMethod2() { // 5.
        // This is the second test method.
        // Your testing code goes here.
        addTeardownBlock { // 6.
            // Called when testMethod2() ends.
            print("testMethod2 - addTeardownBlock1 method")
        }
        addTeardownBlock { // 7.
            // Called when testMethod2() ends.
            print("testMethod2 - addTeardownBlock2 method")
        }
    }
    
    override func tearDown() { // 8.
        // This is the tearDown() instance method.
        // It is called after each test method completes.
        // Perform any per-test cleanup here.
        super.tearDown()
        print("tearDown instance method")
    }
    
    override class func tearDown() { // 9.
        // This is the tearDown() class method.
        // It is called after all test methods complete.
        // Perform any overall cleanup here.
        super.tearDown()
        print("tearnDown class method")
    }
}