Skip to main content

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ả!

Comments

Popular posts from this blog

MVVM và VIPER: Con đường trở thành Senior

Trong bài viết trước chúng ta đã tìm hiểu về MVC và MVP để ứng dụng cho một iOS App đơn giản. Bài này chúng ta sẽ tiếp tục ứng dụng 2 mô hình MVVM và VIPER . Nhắc lại là ứng dụng của chúng ta cụ thể khi chạy sẽ như sau: Source code đầy đủ cho tất cả mô hình MVC, MVP, MVVM và VIPER các bạn có thể download tại đây . MVVM MVVM có thể nói là mô hình kiến trúc được rất nhiều các cư dân trong cộng đồng ưa chuộng. Điểm tinh hoa của kiến trúc này là ở ViewModel , mặc dù rất giống với Presenter trong MVP tuy nhiên có 2 điều làm nên tên tuổi của kiến trúc này đó là: ViewModel không hề biết gì về View , một ViewModel có thể được sử dụng cho nhiều View (one-to-many). ViewModel sử dụng Observer design pattern để liên lạc với View (thường được gọi là binding data , có thể là 1 chiều hoặc 2 chiều tùy nhu cầu ứng dụng). Chính đặc điểm này MVVM thường được phối hợp với các thư viện hỗ trợ Reactive Programming hay Event/Data Stream , đây là triết lý lập trình hiện đại và hiệu

Alamofire vs URLSession

Alamofire vs URLSession: a comparison for networking in Swift Alamofire and URLSession both help you to make network requests in Swift. The URLSession API is part of the foundation framework, whereas Alamofire needs to be added as an external dependency. Many  developers  doubt  whether it’s needed to include an extra dependency on something basic like networking in Swift. In the end, it’s perfectly doable to implement a networking layer with the great URLSession API’s which are available nowadays. This blog post is here to compare both frameworks and to find out when to add Alamofire as an external dependency. Build better iOS apps faster Looking for a great mobile CI/CD solution that has tons of iOS-specific tools, smooth code signing, and even real device testing? Learn more about Bitrise’s iOS specific solutions! This shows the real power of Alamofire as the framework makes a lot of things easier. What is Alamofire? Where URLSession can be found within the s

Fileprivate vs private: Giải thích sự khác biệt

Fileprivate vs private in Swift: The differences explained Fileprivate and private are part of the access control modifiers in Swift. These keywords, together with internal, public, and open, make it possible to restrict access to parts of your code from code in other source files and modules. The private access level is the lowest and most restrictive level whereas open access is the highest and least restrictive. The documentation of Swift will explain all access levels in detail to you, but in this blog post, I’m going to explain the differences between two close friends: fileprivate and private. Build better iOS apps faster Looking for a great mobile CI/CD solution that has tons of iOS-specific tools, smooth code signing, and even real device testing? Learn more about Bitrise’s iOS specific solutions! Open access is the highest (least restrictive) access level and private access is the lowest (most restrictive) access level. This will improve readability and mak