[iOS] - Bắt đầu viết Unit Test từ con số 0

Chào các bạn, hôm nay tôi xin chia sẽ những gì mình đã rút ra được qua quá trình mò mẫm và tìm kiếm về Unit Test trong iOS. Tôi là một lập trình viên iOS với kinh nghiệm về Unit Test là zero, tôi chưa từng viết test, trên bất cứ nền tảng nào, trong bất kỳ ngôn ngữ nào, và đếch thể ngờ được là dự án mình làm khách lại yêu cầu viết test 😢

Thôi không sao, mình quẩy thôi! Và thế là vào khoảng 3 tuần trước, tôi đã viết những dòng code test đầu tiên. Thời gian đầu, ngồi research, không biết tại sao nhưng tôi thực sự cảm thấy bí quá chừng vì thực sự là, tôi chẳng biết phải làm cái đếch gì luôn. Nhưng rồi dần dần nhiều thứ nó cũng vỡ ra, và sau đây tôi chia sẻ những gì mình biết.

Giai đoạn 1: Mò mẫm, research

Viết test là làm cái gì ? Không phải có QA, Tester rồi hay sao ?

QA, Tester chỉ có thể kiểm thử hộp đen, họ kiểm tra sản phẩm có đúng theo yêu cầu của khách hàng không, các trường hợp mà user có thể sử dụng gây ra lỗi, các nguyên tắc đảm bảo sản phẩm đến tay người dùng cuối là hoàn thiện... Còn chúng ta, các developer, viết test là để kiểm thử hộp trắng. Nghĩa là sao ?

Là chúng ta test chính những dòng code chúng ta viết ra.

Chúng ta định nghĩa ra một function, một class, một module, chúng ta đặt ra đầu vào, đầu ra của các function, class và module đó. Chúng ta phải đảm bảo nó hoạt động đúng như những gì chúng ta muốn, phải đảm bảo những dòng code trong hàm, trong class, trong module đó biến một đầu vào tương ứng trở thành đầu ra tương ứng...

Từ việc viết test này, chúng ta có thể nhận ra những sai lầm của chính mình, bắt bạn phải nắm rõ spec của hệ thống, từng bước đi của các dòng code, từ đó chất lượng code được nâng cao, code ít bug hơn, hiệu suất của cả quá trình sẽ được tăng lên và thậm chí là tốt cho việc maintenance.

Giai đoạn 2: Khởi động

Ờ thế là mình biết test là cái gì rồi, thế giờ bắt đầu làm cái gì nhở !? (ngồi đơ nhìn project...)

Nói chung là ở giai đoạn này, bạn cần phải đọc vài tutorial trên mạng về viết unit test để trước tiên bạn biết cách tạo ra test bundle và configure project để có thể bắt đầu viết test được, recommend tutorial của Ray Wenderlich: iOS Unit Testing and UI Testing Tutorial

Tiếp theo, bạn cần lựa chọn tool để viết test, có hai lựa chọn phổ biến là:

Cá nhân mình chọn option thứ hai, mình sử dụng Quick và Nimble để viết test vì thấy nó rất là tiện và cách cấu trúc rất rõ ràng. Sau khi chọn được công cụ mong muốn, việc tiếp theo của bạn là tổ chức thư mục cho test code Bạn có thể tổ chức theo bất kì cách nào bạn muốn, còn đây là ví dụ về cách mình tổ chức:

  • MockClass: // Thư mục chứa các mock class
  • FakeData: // Thư mục chứa các fake data, chủ yếu là file json vì app mình sử dụng http services trả về json response
  • Helpers: // Các class mang ý nghĩa helper
  • Tests: // Test code đặt tại đây, các thư mục con trong này mình tổ chức giống hệt như code thật.
    • Scenes
      • LoginScene
        • LoginViewSpec.swift // Test code here
        • LoginPresenterSpec.swift
        • ...
      • ...
      • SignUpScene
        • SignUpViewSpec.swift
        • SignUpPresenterSpec.swift
        • ...
      • ...
    • APIServices
    • ...

Giai đoạn 3: Bắt đầu viết test

Ầu dia thế là phần setup đã xong, cuối cùng cũng được động vào code

Đừng tưởng bở, đây vốn là phần ngu người nhất.

Dù sau vài tutorial ở giai đoạn trước, bạn có thể viết test theo mẫu, nhưng rồi bạn nhận ra là với cái code của mình bạn chẳng hiểu phải test thế nào, nếu như bạn đang sử dụng kiến trúc MVC của iOS, testing là một điều gì đó rất chi là mệt, và đặc biệt là khi bạn đã quá quen việc viết các lớp service dưới dạng static, mocking trở thành một cơn ác mộng...

Cơ mà nếu bạn bắt đầu từ con số 0 giống như tôi, bạn sẽ chỉ biết đơ lại và chả hiểu phải làm thế nào mà thôi, thế nên lời khuyên của tôi là bạn nên tìm hiểu các khái niệm sau, rồi bạn sẽ thấy thế nào là mặt trời chân lý chói qua tim:

  • Dependency Injection
  • Mock
  • Fake
  • Stub
  • MVP (cái này optional thôi, nhưng mình khuyên nếu viết theo MVP thay vì MVC thì sẽ dễ viết test hơn nhiều)
  • Spy (optional)
  • Dummy (optional)

Sau những nỗ lực tìm hiểu và nắm bắt các khái niệm trên, tôi xin giới thiệu cho bạn Mockingjay - Một thư viện quá ngon để stub HTTP request trong Swift.

Bắt đầu từ bây giờ, bạn đã giống tôi của 3 tuần trước, bạn đã có thế đặt tay vào những dòng test đầu tiên, chúc vui!

Nếu còn băn khoăn trong việc sử dụng Quick, tôi recommend cho bạn một tutorial trên medium.com: TDD using Quick & Nimble và link github của tiền bối của tôi DhtUnitTest, có ví dụ về việc sử dụng Quick trong đó.

Về việc nên test những gì, thì tôi xin chia sẻ thật tình là có cả tỉ thứ để test, các tiền bối luôn nói: "Thời gian để viết test có thể gấp đôi thời gian phát triển tính năng", vì thế nên là có test thì test vừa thôi, test coverage đạt 85% là ổn, kinh nghiệm của tôi thì cứ nhìn vào hàm mà viết test, kiểm tra xem các hàm viết trong class có thực hiện đúng đầu vào đầu ra mong muốn không ? bao nhiêu if thì bấy nhiêu case.

Giai đoạn 4: Mở rộng

Bạn đã có những dòng test code đầu tiên khi bước qua giai đoạn 3, và sau đây là những góp ý của mình để bạn có thể mở rộng kiến thức.

Test Driven Development (TDD) - đó là từ khóa dành cho bạn, tìm hiểu những nó và những vấn đề và bài viết xoay quanh nó, bạn có thể sẽ thay đổi cái mindset trước giờ của mình trong việc lập trình.

Kết:

Bài viết này của mình không chứa code, những gì mình chia sẻ ở đây không phải là một cách giải quyết một vấn đề cụ thể nào trong lập trình, mà ở đây mình chỉ muốn chia sẻ cái hướng đi mà mình đã làm để có thể viết test từ con số 0, mong rằng sẽ giúp cho việc tìm hiểu một vấn đề mới được dễ dàng hơn, thay vì phải loay hoay rất mất thời gian như mình. Cám ơn các bạn đã chịu khó đọc đến đây. Chúc các bạn có một ngày làm việc hiệu quả!