Tag: #Unit-Test

  • Unit Test – How to unwrap optional value in XCTest

    Unit Test – How to unwrap optional value in XCTest

    Trước khi Xcode 11 ra mắt, để unwrap một optional value chúng ta vẫn thường phải dùng Guard/if let, điều này khá bất tiện trong khi viết Unit test. Khi viết test case chúng ta không nên đưa các câu lệnh điều kiện vào trong các func test vì nó sẽ tạo ra một logic mới trong Unit Test nó khiến test case của chúng ta rắc rối và phức tạp.

    Để các bạn dễ hình dung hơn, mình có tạo một Struct Person có thuộc tính address là optional (có thể nil) như dưới đây:

    struct Person {
        let name: String
        let address: String?
    }

    Thông thường chúng ta sẽ thực hiện unwrap như sau:

    func test_Address_caseNil() throws {
        let personModel: Person = Person(name: "John", address: nil)
        // unwrap optional value 
        guard let address = personModel.address else {
            XCTFail("Expected non-nil address")// throw fail
            return
        }
        
        XCTAssertEqual(address, "Hanoi")
    }

    Trong trường hợp này địa chỉ đang nil nên test case này sẽ bị lỗi và throw thông báo “Expected non-nil address”

    Có một cách thông dụng hơn là không unwrap mà sử dụng trực tiếp giá trị optional để verify test case như sau:

    func test_address_caseNil() throws {
        let personModel: Person = Person(name: "John", address: nil)
        
        XCTAssertEqual(personModel.address, "Hanoi")
    }

    Khi chạy test case này ta nhận được thông báo lỗi như sau:

    test_address_caseNil(): XCTAssertEqual failed: ("nil") is not equal to ("Optional("Hanoi")")

    Sử dụng cách này thì khá là tiện và nhanh, tuy nhiên nó có một nhược điểm là các thông báo lỗi thường không rõ ràng. Ngoài ra nó cũng sẽ không sử dụng được trong các trường hợp đặc biệt.

    Sử dụng XCTUnwrap

    XCTUnwrap() được giới thiệu trên Xcode 11, nó làm nhiệm vụ kiểm tra giá trị optional có nil hay không? nếu nil nó sẽ throw ra lỗi, không nil thì trả về giá trị. Từ đó ta có thể thoải mái sử dụng giá trị đó để thực hiện việc testing.

    func test_address_caseNil() throws {
        let personModel: Person = Person(name: "John", address: nil)
        // result
        let result = try XCTUnwrap(personModel.address)
        XCTAssertEqual(personModel.address, "Hanoi")
    }

    Sử dụng XCTUnwrap giúp source code của chúng ta gọn gàng sạch sẽ hơn rất nhiều so với các cách thông thường khác.

    Để sử dụng được XCTUnwrap bạn nhớ thêm throws cho func test để khi kiểm tra dữ liệu bị nil nó sẽ throw lỗi và đánh dấu test case này bị fail. Nếu bạn muốn thông báo rõ ràng hơn hay đơn giản là bạn muốn viết thông báo lỗi dễ hiểu bạn có thể thêm thuộc tính như sau

     let result = try XCTUnwrap(personModel.address, "Width is nil, please config data for test case")

    Thông báo lỗi ta nhận được sẽ như sau:

    test_address_caseNil(): XCTUnwrap failed: expected non-nil value of type "String" - Width is nil, please config data for test case

    Lúc này thông báo lỗi đã rõ ràng hơn, từ đó bạn có thể xử lí vấn đề một cách nhanh hơn.

    Hi vọng bài viết sẽ giúp cho các bạn có thêm lựa chọn để xử lí các tình huống khi viết Unit Test, từ đó sử dụng nó một cách hiệu quả và phù hợp với các tình huống.

  • Unit Test – Các cách chạy test trên Xcode

    Unit Test – Các cách chạy test trên Xcode

    Thông thường khi các bạn mới vào nghề khi viết xong các test case của mình các bạn thường sử dụng Command + U để chạy. Điều này không sai, tuy nhiên nếu bạn đang thực hiện trên một project lớn thì mình nghĩ bạn không nên dùng cách này vì nó có thể khiến bạn mất rất nhiều thời gian để có được kết quả test. Sau đây mình sẽ giới thiệu cho các bạn một số cách để bạn chạy test case một cách nhanh chóng và hiệu quả hơn.

    Chạy test case trên Test Navigator

    Các bạn có thể tuỳ chọn việc test cả một file hay test từng test case một trên Test Navigator

    1. Chạy test cho cả Target tests: Dùng khi bạn muốn chạy test và lấy báo cáo cho cả target này, khi này Xcode sẽ chạy nhiều test case cùng lúc nên có thể sẽ mất nhiều thời gian
    2. Chạy test cho chỉ một file tests: Dùng khi bạn viết xong toàn bộ test case của một file và muốn chạy test để kiểm tra báo cáo hay khi bạn muốn kiểm tra xem giữa các test case có bị conflict hay không?
    3. Chạy test một case cụ thể: Dùng khi bạn vừa viết xong test case và muốn kiểm tra xem func đã chạy đúng hay chưa, đây là trường hợp bạn nên dùng khi viết UT vì nó chạy nhanh nên tốn ít thời gian mà vẫn đảm bảo mục đích của bạn

    Bạn có thể chạy một hoặc nhiều test case mà bạn muốn bằng cách chọn các test case đó -> chuột phải -> Run x Methods

    Chạy test case trực tiếp trên file Tests

    Khi các bạn viết xong các test case của mình và bấm Command + S, trên func test case của bạn sẽ xuất hiện một button cho bạn chạy test luôn, điều này giúp bạn dễ dàng kiểm tra được test case của mình. Ngoài ra Xcode cũng cung cấp cho chúng ta một nút chạy test cho toàn bộ file ở trên đầu của file. Bạn có thể xem chi tiết ở hình dưới đây

    Chạy lại test case vừa test

    Để chạy lại test các test case bạn vừa mới test thì bạn dùng tổ hợp phím sau:

    ⌃ Control + ⌥ Option + ⌘ Command + G

    Đây là tổ hợp phím rất hữu dụng và được sử dụng thường xuyên vì nó giúp bạn chạy lại test case một cách nhanh chóng khi các bạn phải sửa lại các test case bị fail do viết sai input/output.

    Chạy test tất cả file trong Test Plan

    Khi bạn muốn xem báo cáo tất cả cho file Test Plan của bạn, bạn chỉ cần nhấn tổ hợp phím Command + U.

    Bật Code Coverage trên Sidebar

    Theo mặc định thì code coverage sẽ được bật khi bạn chạy test, tuy nhiên nếu bạn nhỡ tay tắt nó đi mà không biết bật nó ở đâu thì làm theo hướng dẫn sau: Adjust Editor Options -> Code Coverage

    Khi này Xcode sẽ cho bạn biết được dòng code đó của bạn được chạy qua bao nhiêu lần, nếu con số là 0 thì có vẻ bạn chưa có test case nào được viết để test đoạn code đó. Từ dữ liệu đó bạn có thể thực hiện viết thêm test case nếu cần.

    Hi vọng bài viết giúp ích cho các bạn. Xin cảm ơn!