Kiểm thử tích hợp xác minh tính đúng đắn của sự tương tác giữa các thành phần của ứng dụng di động — mô-đun, dịch vụ, cơ sở dữ liệu và API bên ngoài. Không giống như kiểm thử đơn vị cô lập từng thành phần, kiểm thử tích hợp phát hiện lỗi ở các điểm kết nối: không tương thích định dạng dữ liệu, lỗi truyền tham số và xử lý không chính xác các phản hồi từ máy chủ. Theo Martin Fowler, 2018, kiểm thử tích hợp bao phủ tới 40% các lỗi nghiêm trọng mà kiểm thử đơn vị bỏ sót và mang lại sự tự tin về độ ổn định của hệ thống trước khi phát hành.
Điểm chính
Kiểm thử tích hợp là giai đoạn xác minh phần mềm đánh giá tính đúng đắn của sự tương tác giữa các mô-đun hoặc hệ thống con riêng lẻ của ứng dụng. Trong khi kiểm thử đơn vị kiểm tra từng thành phần một cách riêng lẻ, kiểm thử tích hợp tập hợp các thành phần này lại với nhau và kiểm tra cách chúng hoạt động cùng nhau. Các kịch bản điển hình bao gồm truyền dữ liệu giữa lớp mạng và kho lưu trữ, ghi vào cơ sở dữ liệu qua ORM và xử lý phản hồi từ API bên thứ ba.
Trong bối cảnh phát triển di động, kiểm thử tích hợp bao phủ các tương tác giữa lớp UI, logic nghiệp vụ và nguồn dữ liệu. Ví dụ, một kiểm thử có thể xác minh rằng sau khi nhấp vào nút “Đăng nhập”, ứng dụng gửi yêu cầu đến máy chủ, nhận token và lưu nó vào bộ nhớ cục bộ. Sự xác minh này khẳng định rằng chuỗi thành phần hoạt động không có lỗi.
Theo World Quality Report 2023, các công ty thường xuyên áp dụng kiểm thử tích hợp giảm số lượng sự cố sản xuất tới 35% so với các dự án chỉ dựa vào kiểm thử đơn vị. Điều này làm cho kiểm tra tích hợp trở thành một yếu tố bắt buộc trong chiến lược đảm bảo chất lượng trong phát triển thương mại.
Ứng dụng di động bao gồm nhiều thành phần kết nối với nhau: yêu cầu mạng, cơ sở dữ liệu cục bộ, thông báo push, dịch vụ hệ thống và SDK bên thứ ba. Mỗi thành phần này được phát triển riêng biệt, nhưng trong thời gian chạy, chúng trao đổi dữ liệu theo thời gian thực. Kiểm thử tích hợp phát hiện các lỗi không thể tìm thấy thông qua xác minh mô-đun riêng lẻ.
Các vấn đề điển hình được kiểm thử tích hợp phát hiện bao gồm không khớp kiểu dữ liệu giữa API và mô hình ứng dụng, lỗi tuần tự hóa JSON, xử lý không chính xác thời gian chờ mạng và lỗi khi truy cập cơ sở dữ liệu đồng thời qua Room hoặc Core Data. Nếu không có kiểm tra tích hợp, những lỗi này sẽ vào sản xuất và chỉ xuất hiện với người dùng thực tế.
Nghiên cứu từ Google Testing Blog (2021) cho thấy chi phí sửa lỗi được phát hiện trong giai đoạn kiểm thử tích hợp thấp hơn 5 lần so với sau khi phát hành. Điều này là do ở giai đoạn đầu, nhà phát triển có ngữ cảnh đầy đủ của lỗi và có thể sửa nó mà không cần chu kỳ hotfix khẩn cấp. Đầu tư thời gian vào việc viết kiểm thử tích hợp sẽ được đền đáp thông qua giảm chi phí bảo trì và tăng niềm tin của người dùng.
Có ba phương pháp chính để tổ chức kiểm thử tích hợp: Big Bang, Bottom-Up và Top-Down. Việc lựa chọn chiến lược phụ thuộc vào quy mô dự án, kiến trúc ứng dụng và tính sẵn có của các thành phần tại thời điểm viết kiểm thử. Mỗi phương pháp có ưu điểm và hạn chế riêng cần cân nhắc khi lập kế hoạch phủ sóng kiểm thử.
Big Bang — phương pháp kết nối tất cả các thành phần hệ thống đồng thời, sau đó thực hiện một lần chạy kiểm thử tổng thể. Phương pháp này đơn giản để thực hiện: không cần viết stubs hoặc mô phỏng các mô-đun riêng lẻ. Tuy nhiên, khi phát hiện lỗi, rất khó xác định thành phần nào gây ra lỗi. Big Bang phù hợp với các dự án nhỏ có kiến trúc đơn giản với số lượng mô-đun không quá năm.
Bottom-Up — chiến lược kiểm thử tích hợp bắt đầu từ các thành phần cấp thấp: cơ sở dữ liệu, lớp mạng, dịch vụ hệ thống. Sau khi xác minh từng cấp, các kiểm thử dần dần kết nối các mô-đun cấp cao hơn — kho lưu trữ, lớp Use Case và ViewModel. Lợi thế chính là phát hiện sớm các lỗi ở các lớp nền tảng của ứng dụng, giảm nguy cơ lỗi dây chuyền ở các giai đoạn phát triển sau.
Top-Down — phương pháp kiểm thử bắt đầu từ các thành phần cấp cao — màn hình UI và điều hướng, trong khi các mô-đun cấp thấp hơn được mô phỏng bằng stubs hoặc mocks. Điều này cho phép kiểm tra các kịch bản người dùng trước khi phía máy chủ hoặc cơ sở dữ liệu được triển khai đầy đủ. Top-Down đặc biệt hữu ích trong quá trình phát triển song song phần client và server khi backend chưa sẵn sàng cho tích hợp thực tế.
Đối với kiểm thử tích hợp ứng dụng di động, một loạt các công cụ chuyên dụng được sử dụng, chia thành ba loại: thư viện mô phỏng máy chủ, framework làm việc với cơ sở dữ liệu và công cụ xác minh dịch vụ hệ thống. Việc lựa chọn công cụ cụ thể phụ thuộc vào nền tảng — Android hoặc iOS — và ngăn xếp công nghệ của dự án.
Hãy xem các ví dụ thực tế về kiểm thử tích hợp cho Android và iOS. Đối với nền tảng Android, chúng tôi sử dụng MockWebServer cùng với JUnit, cho iOS — XCTest với thư viện OHHTTPStubs. Cả hai ví dụ đều xác minh kịch bản nhận dữ liệu từ API và lưu nó vào kho lưu trữ cục bộ.
Kiểm thử này xác minh rằng một yêu cầu Retrofit đến máy chủ được mô phỏng trả về JSON chính xác và kho lưu trữ chuyển đổi phản hồi thành mô hình miền. MockWebServer chặn yêu cầu và trả về JSON được chỉ định, sau đó kiểm thử so sánh kết quả mong đợi với kết quả thực tế.
class UserRepositoryTest {
private val mockServer = MockWebServer()
@Before
fun setup() {
mockServer.start()
}
@Test
fun fetchUser_returnsCorrectData() {
val json = "{ \`"id\`": 1, \`"name\`": \`"Alice\`" }"
mockServer.enqueue(MockResponse()
.setBody(json)
.setResponseCode(200))
val repository = UserRepository(
createRetrofit(mockServer.url("/").toString()))
val user = repository.fetchUser(1)
assertEquals(1, user.id)
assertEquals("Alice", user.name)
}
@After
fun tearDown() {
mockServer.shutdown()
}
}
Đối với iOS, một kiểm thử tương tự sử dụng OHHTTPStubs để chặn các yêu cầu URL. Thư viện thay thế phản hồi của máy chủ ở cấp framework hệ thống URL Loading System, cho phép kiểm thử bất kỳ thư viện mạng nào — URLSession, Alamofire hoặc Moya.
import XCTest
import OHHTTPStubs
import OHHTTPStubsSwift
class UserRepositoryTests: XCTestCase {
func testFetchUser_returnsCorrectData() {
stub(condition: isPath("/users/1")) { _ in
return HTTPStubsResponse(
jsonObject: ["id": 1, "name": "Alice"],
statusCode: 200,
headers: nil
)
}
let repository = UserRepository()
let expectation = expectation(description: "fetch user")
repository.fetchUser(id: 1) { user in
XCTAssertEqual(user.id, 1)
XCTAssertEqual(user.name, "Alice")
expectation.fulfill()
}
waitForExpectations(timeout: 2.0)
}
}
Kiểm thử tích hợp hiệu quả yêu cầu tuân thủ một tập hợp các thực hành giúp tăng độ ổn định của kiểm thử và giảm chi phí bảo trì. Cô lập các phụ thuộc bên ngoài: sử dụng cơ sở dữ liệu trong bộ nhớ thay vì phiên bản sản xuất và mô phỏng API bên thứ ba bằng thư viện stub. Điều này loại bỏ các lỗi không xác định do tính khả dụng của mạng hoặc trạng thái dịch vụ bên ngoài gây ra.
Duy trì tính độc lập của kiểm thử: mỗi kiểm thử tích hợp nên hoạt động riêng lẻ, không phụ thuộc vào kết quả của các kiểm thử khác. Sử dụng chú thích @Before và @After trong JUnit hoặc setUp và tearDown trong XCTest để chuẩn bị và dọn dẹp môi trường kiểm thử. Điều này ngăn chặn ảnh hưởng lẫn nhau giữa các kiểm thử và đơn giản hóa chẩn đoán lỗi.
Bao phủ các trường hợp biên: kiểm thử tích hợp không chỉ nên xác minh các kịch bản thành công (happy path) mà còn xử lý lỗi — thời gian chờ, mã HTTP 4xx và 5xx, phản hồi trống, JSON bị lỗi. Theo Google Testing Blog (2022), 60% sự cố sản xuất liên quan đến xử lý không chính xác các trường hợp biên không được kiểm thử bao phủ.
Câu hỏi thường gặp
Kiểm thử đơn vị kiểm tra một lớp hoặc hàm riêng lẻ, thay thế các phụ thuộc bằng stubs. Kiểm thử tích hợp xác minh sự tương tác của nhiều thành phần thực — ví dụ, kết nối mạng và cơ sở dữ liệu đồng thời.
Chạy kiểm thử tích hợp thường mất từ 2 đến 15 phút tùy thuộc vào số lượng kiểm thử và độ phức tạp của môi trường. Đối với các dự án lớn, nên chia các kiểm thử thành các công việc song song trong hệ thống CI để giảm thời gian xác minh tổng thể trước khi hợp nhất.
Đầu tiên, kiểm thử tích hợp được viết cho lớp mạng, cơ sở dữ liệu và dịch vụ hệ thống — thông báo, máy ảnh, định vị địa lý. Yêu cầu API đến backend và các thao tác lưu trữ cục bộ mang lại ROI cao nhất vì các thành phần này thường là nguồn gốc của các hồi quy.
Đối với một màn hình, kiểm thử đơn vị cho ViewModel và kiểm thử UI là đủ. Kiểm thử tích hợp cho một màn hình chỉ cần thiết nếu màn hình tương tác với nhiều nguồn dữ liệu — ví dụ, kết hợp phản hồi từ hai API khác nhau hoặc ghi dữ liệu đồng thời vào mạng và cơ sở dữ liệu cục bộ.
Kiểm thử tích hợp nên được chạy trong mỗi pull request trong đường ống CI và trước các bản phát hành chính. Cũng nên chạy toàn bộ kiểm thử tích hợp vào ban đêm (nightly build) để phát hiện các lỗi liên quan đến thay đổi trong phụ thuộc hoặc môi trường kiểm thử.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm