Một bản triển khai được đưa ra vào 4 giờ chiều thứ Sáu. Các bài kiểm thử đơn vị (unit test) báo xanh, container được xây dựng, quá trình triển khai hoàn tất mà không có lỗi. Sau đó, hàng đợi hỗ trợ bắt đầu đầy lên: thanh toán gặp lỗi 500. Lỗi chưa bao giờ nằm trong mã được kiểm tra. Nó nằm ở cách hai dịch vụ giao tiếp với nhau, và không có bài kiểm thử nào trong quy trình từng thực hiện cuộc trò chuyện đó.
Đó là khoảng cách mà tự động hóa kiểm thử trong DevOps được cho là phải lấp đầy, và phần mà hầu hết các nhóm đầu tư chưa đủ là lớp API. Kiểm thử đơn vị (unit test) chứng minh một chức năng hoạt động độc lập. Kiểm thử giao diện người dùng đầu cuối (end-to-end UI test) chứng minh trình duyệt có thể nhấp qua một quy trình, nhưng chậm và không ổn định. Hợp đồng giữa các dịch vụ của bạn, thứ thực sự gây lỗi trong môi trường sản phẩm, nằm ở giữa và thường không được kiểm tra. Kiểm thử API chính là nằm ở đó.
Tự động hóa kiểm thử trong DevOps thực sự có nghĩa là gì
DevOps là một vòng lặp, không phải một đường thẳng. Lập kế hoạch, mã hóa, xây dựng, kiểm thử, phát hành, triển khai, vận hành, giám sát, sau đó quay lại lập kế hoạch. Tự động hóa kiểm thử trong DevOps có nghĩa là các bài kiểm thử tự động chạy tại các điểm trong vòng lặp đó, nơi chúng phát hiện vấn đề với chi phí thấp nhất, thay vì là một cổng thủ công mà ai đó chạy một lần trước khi phát hành.

Nguyên tắc đằng sau đó là "shift-left": di chuyển kiểm thử sớm hơn, gần hơn với thời điểm nhà phát triển viết thay đổi. Một lỗi được phát hiện trên một pull request chỉ tốn vài phút để sửa. Cùng một lỗi đó nếu được phát hiện trong môi trường sản phẩm sẽ tốn kém cho việc khôi phục (rollback), một kênh sự cố và phân tích sau sự cố (postmortem). Tự động hóa là thứ giúp việc dịch chuyển sang trái trở nên khả thi, bởi vì con người không thể tự chạy lại bộ kiểm thử hồi quy trên mỗi commit, nhưng một quy trình tự động thì có thể.
Sai lầm là coi "tự động hóa kiểm thử" như một khái niệm duy nhất. Tháp kiểm thử chia nó thành các lớp, và mỗi lớp trả lời một câu hỏi khác nhau:
- Kiểm thử đơn vị (Unit tests) hỏi liệu một hàm đơn lẻ có trả về giá trị đúng hay không. Chúng nhanh và nhiều.
- Kiểm thử API và tích hợp (API and integration tests) hỏi liệu các dịch vụ của bạn có tạo ra phản hồi đúng và giao tiếp với nhau chính xác hay không. Số lượng ít hơn, nhưng mỗi cái bao phủ phạm vi rộng hơn.
- Kiểm thử đầu cuối (End-to-end tests) hỏi liệu toàn bộ hệ thống có hoạt động từ góc nhìn của người dùng hay không. Chậm, dễ hỏng và nên giữ ở số lượng ít.
Kiểm thử API nằm ở vị trí trung tâm hiệu quả. Chúng chạy trong vài giây, không phải vài phút. Chúng không phụ thuộc vào giao diện người dùng được hiển thị, vì vậy chúng không bị lỗi khi một nút di chuyển. Và chúng kiểm tra bề mặt mà các dịch vụ khác của bạn và khách hàng của bạn thực sự phụ thuộc vào. Đó là lý do tại sao, trong một quy trình DevOps, kiểm thử API gánh vác phần lớn tải trọng phát hiện lỗi hồi quy hơn bất kỳ lớp nào khác. Đối với các nền tảng của chính phương pháp này, tự động hóa kiểm thử API bao gồm những gì cần khẳng định và tại sao trước khi bạn lo lắng về nơi nó chạy.
Vòng đời DevOps, từng giai đoạn, và vị trí của kiểm thử API
Đây là bản đồ thực tế. Không phải mọi nhóm đều cần kiểm thử API ở mọi giai đoạn, nhưng việc biết các lựa chọn sẽ giúp bạn chọn một cách có chủ đích thay vì dồn mọi thứ vào một công việc lớn trước khi triển khai.
Trong quá trình phát triển: cục bộ và trước khi commit
Trước khi một thay đổi đến được CI, một nhà phát triển nên có thể chạy các bài kiểm thử API liên quan trên môi trường cục bộ hoặc môi trường phát triển. Đây là vòng phản hồi nhanh nhất bạn có. Phát hiện một định dạng phản hồi bị hỏng ở đây có nghĩa là mã bị lỗi thậm chí sẽ không bao giờ được đẩy lên.
Trong thực tế, đây là kịch bản tương tự mà sau này bạn sẽ chạy trong CI, chỉ cần trỏ nó đến một môi trường cục bộ. Bạn xây dựng nó một lần. Nếu bạn chưa từng tạo một cái nào, cách viết kịch bản kiểm thử với Apidog sẽ hướng dẫn bạn cách nối chuỗi các yêu cầu và lấy một giá trị từ một phản hồi để sử dụng cho yêu cầu tiếp theo.
Trên pull request: cổng hợp nhất
Đây là nơi có giá trị cao nhất cho kiểm thử API, và là nơi mà các nhóm thường bỏ qua nhất. Khi một pull request được mở, quy trình sẽ khởi động dịch vụ, chạy các kịch bản API của bạn chống lại nó, và báo cáo đạt hoặc không đạt dưới dạng kiểm tra trạng thái. Một kiểm tra không đạt sẽ chặn việc hợp nhất.
Lý do điều này quan trọng: chi phí của một lỗi tăng lên đáng kể khi nó đi xa hơn. Một khẳng định không thành công trên một PR là một lỗi có thể sửa trong năm phút đối với tác giả, người vẫn còn nhớ rõ sự thay đổi. Cùng một lỗi đó nếu được phát hiện một tuần sau trong môi trường staging là một dự án khảo cổ. Đặt kiểm thử API vào cổng PR là thay đổi duy nhất giúp dịch chuyển nhiều lỗi nhất sang trái.
Sau khi xây dựng, trước khi phát hành: kiểm tra tích hợp và hợp đồng
Sau khi artifact được xây dựng và triển khai đến môi trường staging hoặc tích hợp, hãy chạy một bộ kiểm thử rộng hơn. Đây là nơi bạn kiểm tra kết nối thực tế: dịch vụ thanh toán có còn chấp nhận nội dung yêu cầu của dịch vụ đặt hàng không, phân trang có còn trả về trường mà ứng dụng khách của bạn đọc không, một mã thông báo xác thực được cấp bởi một dịch vụ có được dịch vụ khác chấp nhận không.
Giai đoạn này cũng là nơi tư duy hợp đồng phát huy tác dụng. Một thay đổi hợp lệ cục bộ vẫn có thể làm hỏng một khách hàng ở hạ nguồn. Chạy toàn bộ bộ kịch bản trên một môi trường tích hợp sẽ phát hiện ra các lỗi giữa các dịch vụ mà kiểm thử đơn vị về cấu trúc không thể thấy. Các mẫu này được kế thừa từ thực tiễn tự động hóa kiểm thử API rộng hơn.
Tại thời điểm triển khai: kiểm thử khói
Một bản triển khai không hoàn tất khi quá trình rollout kết thúc. Nó hoàn tất khi bạn có bằng chứng rằng phiên bản mới thực sự phục vụ lưu lượng truy cập một cách chính xác. Kiểm thử khói (smoke test) là một kịch bản nhỏ, nhanh chóng, kiểm tra các đường dẫn quan trọng ngay sau khi triển khai: người dùng có thể xác thực không, họ có thể đọc dữ liệu của mình không, endpoint quan trọng về sức khỏe có trả về 200 với định dạng đúng không.
Hãy giữ bộ kiểm thử này nhỏ gọn và nhanh chóng. Nhiệm vụ của nó là tín hiệu tiếp tục hoặc dừng lại, chứ không phải độ bao phủ. Nếu nó thất bại, bạn sẽ tự động rollback. Chạy cùng một kịch bản trên môi trường sản phẩm bằng cách thay đổi một cờ môi trường duy nhất, không cần phải duy trì các bài kiểm thử trùng lặp.
Trong môi trường sản phẩm: giám sát liên tục
Sau khi triển khai, vòng lặp không dừng lại. Các kịch bản API tương tự mà bạn chạy trong CI có thể chạy theo lịch trình trên môi trường sản phẩm dưới dạng giám sát tổng hợp (synthetic monitoring), phát hiện sự suy giảm hiệu suất của một phụ thuộc bên thứ ba hoặc một chứng chỉ hết hạn trước khi khách hàng nhận ra. Ranh giới giữa một bài kiểm thử và một hệ thống giám sát chủ yếu là lịch trình mà nó chạy. Giám sát API bao gồm việc biến các bài kiểm thử thành công thành một hệ thống cảnh báo sớm trong môi trường sản phẩm.
Một quy tắc chung hữu ích qua cả năm giai đoạn: càng gần môi trường sản phẩm, bộ kiểm thử càng nhỏ và nhanh hơn. Độ bao phủ rộng trên các PR và trong tích hợp; một bộ kiểm thử khói mỏng, nghiêm ngặt tại thời điểm triển khai và trong giám sát.
Tại sao lớp API xứng đáng có vị trí trong quy trình
Điều đáng nói rõ là tại sao kiểm thử API xứng đáng có vị trí quan trọng hơn việc dồn thêm trọng lượng vào kiểm thử UI.
Chúng nhanh. Một kịch bản API giao tiếp trực tiếp bằng HTTP. Không cần khởi động trình duyệt, không cần chờ DOM, không cần headless Chrome bị lỗi do hiển thị chậm. Một kịch bản kiểm tra hàng tá endpoint hoàn tất trong vài giây, điều này cho phép bạn chạy nó trên mỗi commit mà không khiến mọi người bỏ qua một công việc kéo dài mười phút.
Chúng ổn định. Kiểm thử UI bị lỗi khi tên lớp thay đổi hoặc một phần tử hiển thị chậm hơn một khung hình. Kiểm thử API chỉ bị lỗi khi hợp đồng thực tế thay đổi, đó chính xác là lúc bạn muốn biết. Ít lỗi vặt hơn có nghĩa là mọi người tin tưởng vào một bản dựng báo lỗi, và một bản dựng được tin cậy là bản dựng duy nhất có thể chặn bất cứ điều gì.
Chúng kiểm thử những gì tích hợp. Ứng dụng di động của bạn, các tích hợp đối tác của bạn, các microservice của riêng bạn đều phụ thuộc vào hợp đồng API, chứ không phải CSS của bạn. Khi hợp đồng đó thay đổi một cách âm thầm, mọi khách hàng đều bị lỗi cùng một lúc. Kiểm thử API là lớp bắt được điều đó.
Đây là lý do tại sao câu hỏi về quy trình thực sự là một câu hỏi về API. Bạn có thể có một bộ kiểm thử đơn vị kỹ lưỡng và một bộ kiểm thử UI đẹp mắt nhưng vẫn có thể triển khai lỗi thanh toán vào chiều thứ Sáu, bởi vì không có lớp nào giám sát mối nối nơi các dịch vụ gặp nhau.
Kết nối kiểm thử API vào quy trình với Apidog CLI
Cơ chế rất quan trọng, bởi vì một bài kiểm thử tồn tại nhưng không chạy tự động sẽ không phát hiện được gì. Mẫu hình này giống nhau trong mọi hệ thống CI: cài đặt một runner, trỏ nó đến các bài kiểm thử của bạn, để mã thoát của nó quyết định bản dựng có thành công hay không.
Với Apidog, bạn không cần viết lại các bài kiểm thử của mình dưới dạng mã. Bạn xây dựng kịch bản một lần trong ứng dụng, sau đó Apidog CLI chạy kịch bản đó mà không cần giao diện (headlessly). CLI là một gói npm, vì vậy bất kỳ runner CI nào có Node.js đều có thể sử dụng nó.
npm install -g apidog-cli
Sau đó chạy một kịch bản. Bạn tạo mã thông báo truy cập và tìm ID kịch bản và môi trường bên trong tab CI/CD của kịch bản kiểm thử trong Apidog, nơi xây dựng lệnh đầy đủ để bạn sao chép:
apidog run \
--access-token $APIDOG_ACCESS_TOKEN \
-t 605067 \
-e 1629989 \
-r cli
Một vài điều đang hoạt động thực sự ở đây. Cờ -t đặt tên cho kịch bản bằng ID; thay thế nó bằng -f <folderId> để chạy toàn bộ một thư mục, hoặc --test-suite <id> để chạy một bộ kiểm thử được chọn lọc như một công việc. Cờ -e chọn môi trường, đây là cách cùng một kịch bản chặn PR chống lại staging và kiểm thử khói chống lại sản phẩm mà không bị trùng lặp. Cờ -r chọn các trình báo cáo (reporters); cli in ra nhật ký, và junit xuất ra XML mà bảng điều khiển CI của bạn có thể hiển thị dưới dạng báo cáo kiểm thử.
Phần biến nó thành một cổng là mã thoát. Khi mọi khẳng định đều thành công, apidog run thoát với mã 0. Khi bất cứ điều gì thất bại, nó thoát với mã khác 0. Hệ thống CI của bạn đọc mã đó, đánh dấu bước đó là thất bại và chặn việc hợp nhất hoặc triển khai. Bạn không cần cấu hình một cổng riêng; mã thoát chính là cổng. Chạy apidog run --help để xem toàn bộ các cờ có sẵn cho phiên bản của bạn.
Đây là giai đoạn cổng PR được kết nối vào GitHub Actions:
name: API Tests
on: [pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run API scenarios
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
run: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-r cli,junit
Mã thông báo nằm trong các bí mật của kho lưu trữ (repository secrets) và đến bước này thông qua env:, không bao giờ được mã hóa cứng. Khối tương tự có thể được đưa vào GitLab CI, Jenkins, CircleCI hoặc Azure Pipelines với cú pháp của nền tảng đó bao quanh, bởi vì phụ thuộc thực sự duy nhất là Node. Các hướng dẫn cụ thể theo nền tảng bao gồm chi tiết: tự động hóa kiểm thử API trong GitHub Actions và tích hợp kiểm thử Apidog với Jenkins.
Đối với giai đoạn kiểm thử khói tại thời điểm triển khai, lệnh hầu như không thay đổi. Bạn trỏ nó đến ID môi trường sản phẩm và giữ kịch bản nhỏ gọn:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e $PROD_ENV_ID -r cli
Một kịch bản, một lần hoán đổi môi trường, hai công việc. Đó là toàn bộ sức hấp dẫn của việc viết bài kiểm thử một lần và chạy chúng trong suốt vòng đời.
Những lỗi phổ biến làm vô hiệu hóa cổng một cách âm thầm
Một quy trình có thể trông hoàn toàn tự động nhưng vẫn không phát hiện được gì. Hãy chú ý đến những điều sau đây.
Nuốt mã thoát (exit code). Ai đó gói lệnh kiểm thử trong một pipeline shell hoặc thêm || true để “ngăn nó làm hỏng bản dựng.” Điều đó cũng ngăn nó phát hiện bất cứ điều gì. Bản dựng sẽ báo xanh mãi mãi. Đừng bao giờ che giấu việc runner thoát với mã khác không; mã thoát đó là toàn bộ ý nghĩa.
Chỉ kiểm thử luồng thành công (happy path). Một kịch bản chỉ xác nhận 200 OK và dừng lại ở đó sẽ bỏ lỡ những lỗi quan trọng. Hãy khẳng định về định dạng nội dung phản hồi, các kiểu trường, các phản hồi lỗi cho đầu vào không hợp lệ. Khẳng định API bao gồm việc xác thực nhiều hơn một mã trạng thái.
Một công việc lớn trước khi triển khai. Dồn mọi bài kiểm thử vào một giai đoạn duy nhất ngay trước khi phát hành sẽ làm mất đi ý nghĩa của "shift-left". Bạn sẽ phát hiện ra một hợp đồng bị hỏng vài phút trước khi triển khai thay vì trên PR. Hãy phân bổ bộ kiểm thử trên các giai đoạn: rộng trên các PR, mỏng ở giai đoạn triển khai.
Kiểm thử trên một môi trường dùng chung, có thể thay đổi (shared mutable environment). Khi hai quy trình cùng truy cập vào cùng một cơ sở dữ liệu, các thao tác ghi của một lần chạy sẽ làm hỏng các thao tác đọc của lần khác, và bạn sẽ gặp phải các lỗi không ổn định làm xói mòn lòng tin. Hãy sử dụng các môi trường cô lập, hoặc sử dụng mocking API để thay thế các phụ thuộc mà bạn không kiểm soát, để thời gian ngừng hoạt động của bên thứ ba không làm cho bản dựng của bạn báo lỗi.
Quên báo cáo khi thất bại. Nếu báo cáo của bạn chỉ được tải lên khi các bài kiểm thử thành công, bạn sẽ không bao giờ thấy báo cáo vào đúng lúc bạn cần nó. Hãy cấu hình việc tải lên artifact để chạy ngay cả khi thất bại.
Câu hỏi thường gặp
Kiểm thử API nên chạy ở đâu trong quy trình DevOps?
Tối thiểu, trên các pull request như một cổng hợp nhất, vì điều đó phát hiện nhiều lỗi nhất với chi phí thấp nhất. Lý tưởng nhất là sau khi bản dựng được chạy trên một môi trường tích hợp để kiểm tra hợp đồng, và như một bộ kiểm thử khói nhỏ ngay sau khi triển khai. Cùng một kịch bản Apidog chạy ở mỗi giai đoạn; bạn chỉ thay đổi cờ môi trường. Các nhóm sử dụng Apidog mà không dùng Postman cũng tuân theo các giai đoạn tương tự.
Sự khác biệt giữa tự động hóa kiểm thử API và CI/CD là gì?
CI/CD là quy trình tự động xây dựng, kiểm thử và phân phối mã của bạn. Tự động hóa kiểm thử API là một loại kiểm thử chạy bên trong quy trình đó. CI/CD là băng chuyền; các bài kiểm thử API tự động là một trạm kiểm soát chất lượng trên đó. Nếu thuật ngữ CI/CD còn mơ hồ, CI/CD là gì bao gồm các kiến thức cơ bản.
Tôi có cần viết lại các bài kiểm thử API của mình dưới dạng mã để chạy chúng trong CI không?
Không cần với Apidog. Bạn xây dựng kịch bản kiểm thử trực quan trong ứng dụng, và Apidog CLI chạy kịch bản đó mà không cần giao diện. CLI là một gói npm, vì vậy bất kỳ runner CI nào có cài đặt Node.js đều có thể thực thi nó bằng một lệnh duy nhất.
Kiểm thử API làm thất bại một bản dựng như thế nào?
Thông qua mã thoát. Khi mọi khẳng định trong một kịch bản đều thành công, runner thoát với mã 0. Khi bất kỳ khẳng định nào thất bại, nó thoát với mã khác không. Hệ thống CI đọc mã đó, đánh dấu bước đó là thất bại và chặn việc hợp nhất hoặc triển khai. Không cần cấu hình cổng riêng biệt nào.
Kiểm thử hiệu suất có nên chạy trong cùng một quy trình không?
Hãy giữ các bài kiểm thử API chức năng trên mỗi PR và chạy các bài kiểm thử tải nặng hơn cùng kiểm thử hiệu suất theo một lịch trình riêng, ví dụ như hàng đêm. Các lần chạy kiểm thử hiệu suất mất nhiều thời gian hơn và cần một môi trường ổn định, vì vậy việc gắn chúng vào mỗi commit sẽ làm chậm phản hồi mà không thêm nhiều tín hiệu cho mỗi commit.
Đặt bài kiểm thử API đầu tiên của bạn ở đâu
Tự động hóa kiểm thử trong DevOps không phải là một cổng bạn xây dựng một lần. Đó là các bài kiểm thử API được đặt một cách có chủ đích trong suốt vòng lặp: trên máy của nhà phát triển để có phản hồi nhanh, trên pull request như một cổng hợp nhất phát hiện nhiều lỗi nhất, sau khi xây dựng để kiểm tra hợp đồng, tại thời điểm triển khai như một tín hiệu khói, và trong môi trường sản phẩm như một công cụ giám sát. Lớp API chiếm vị trí quan trọng nhất trong quy trình vì nó nhanh, ổn định và kiểm thử mối nối nơi các hệ thống thực sự bị hỏng.
Nếu các bài kiểm thử API của bạn vẫn chỉ là các bước có thể nhấp mà ai đó chạy thủ công, thì khoảng cách cần lấp đầy chính là cổng hợp nhất. Tải xuống Apidog, xây dựng một kịch bản, sao chép lệnh apidog run từ tab CI/CD của nó, và dán khối GitHub Actions ở trên. Bạn sẽ có các bài kiểm thử API chặn các lần hợp nhất bị lỗi vào cuối buổi chiều, và lỗi triển khai vào thứ Sáu sẽ hiển thị màu đỏ trên một pull request thay vì trong hàng đợi hỗ trợ của bạn.
