Ở phần trước, thì mình đã demo về việc dựng 1 project ios demo sử dụng Bazel để build. Thì bài này sẽ là bắt đầu trình bày việc giải quyết các vấn đề khi migrate project sang Bazel. Bài hôm nay sẽ tập trung vào việc migrate Unit Tests như thế nào.
1. Migrate ios unit tests
Để bắt đầu thì mình có 1 file như này.
Để thêm unit test vào project, thì cũng không có gì là phức tạp. Mình sẽ vẫn tạo build target trong file BUILD thôi.
Nội dung file BUILD sẽ bao gồm define build target cho module ProjectManagement và unit test là ProjectManagementTests.
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
load("@build_bazel_rules_apple//apple:ios.bzl","ios_unit_test")
swift_library(
name = "ProjectManagement",
module_name = "ProjectManagement",
srcs = glob(["Sources/*.swift"]),
visibility = ["//visibility:public"],
)
swift_library(
name = "ProjectManagementTestSuite",
srcs = glob(["Tests/*.swift"]),
deps = [
":ProjectManagement",
]
)
ios_unit_test(
name = "ProjectManagementTests",
deps = [
"ProjectManagementTestSuite",
],
minimum_os_version = "12.0",
test_host = "//App:ios_app",
visibility = ["//visibility:public"],
)
Để config unit test ta cần làm 2 việc. Đầu tiên là config build target chứa những file unit test bằng rule swift_library
và sau đó config unit test bằng rule ios_unit_test
và cho nó phụ thuộc vào build target chứa những file unit test.
Để run unit test mình sẽ dùng lệnh bazel test //ProjectManagement:ProjectManagementTests
hoặc là để run tất cả các test trong project thì mình có thể dùng lệnh bazel test //...
2. Add Mock class
Mình hay thường gen các Mock class để phục vụ việc unit test dễ dàng hơn. Để đơn giản mình sẽ dùng công cụ Mockolo của Uber để gen file Mock. Bạn có thể tham khảo ở đây https://github.com/uber/mockolo
Mình sẽ đặt file mock này ở trong thư mục ProjectManagement và update file BUILD để add mock vào project
swift_library(
name = "ProjectManagement",
module_name = "ProjectManagement",
srcs = glob(["Sources/*.swift", "*.swift"]),
visibility = ["//visibility:public"],
)
Ơ thế nếu như này thì lúc release thì file mock cũng bao gồm trong phần mềm à. Thế thì hơi dở nhỉ 😅. Thế nên mới sinh ra phần tiếp theo trong bài này.
3. Config setting
Do mình muốn khi release app mà phần code mock trên sẽ k bao gồm trong binary. Thế nên mình sẽ dùng 1 tính năng trong bazel chính là config setting.
Config setting giống như một cái biến giúp cho chúng ta xác định những điều kiện build khác nhau. Ở đây thì mình sẽ cấu hình setting để biết được là chúng ta có đang build release hay không.
Mình sẽ tạo 1 thư mục tên config ở gốc project. Và tạo 1 file BUILD như sau
config_setting(
name = "is_release",
values = { "define" : "release=true" }
)
Mình vừa tạo 1 config setting có tên là is_release. Config setting này sẽ có hiệu lực khi mình define 1 cái biến release=true khi mà mình gọi bazel command.
Để sử dụng config setting thì chúng ta sẽ dùng hàm select trong bazel để cấu hình sẽ build như nào. Bạn theo dõi ở bên dưới này là build target ProjectManagement sau khi được update
MOCK_FILES = select({
"//config:is_release": [],
"//conditions:default": ["Mock.swift"],
})
swift_library(
name = "ProjectManagement",
module_name = "ProjectManagement",
srcs = glob(["Sources/*.swift"]) + MOCK_FILES,
visibility = ["//visibility:public"],
)
Ở bên trên là mình define 1 biến MOCK_FILES chứa list file mock, thì mình dùng hàm select để chọn ra điều kiện build. Hàm select sẽ trả về rỗng nếu config setting ios_release được kích hoạt. Còn không thì mình sẽ compile target ProjectManagement đi kèm với Mock.swift.
Khi muốn build release, để kích hoạt is_release config thì mình sẽ define thêm 1 biến release như sau.
bazel build //App:ios_app --define release=true
Project project mình được đặt ở đây: https://github.com/vikage/DemoBazelUnitTest
Tham khảo thêm:
https://docs.bazel.build/versions/main/skylark/config.html
https://github.com/bazelbuild/rules_apple/blob/master/doc/rules-ios.md
Tuyệt vời quá. Series chi tiết dễ hiểu. Hóng các phần tiếp theo ạ