Bạn muốn các bài kiểm thử API dễ đọc như tiếng Anh thông thường, nằm trong Git cùng với mã của bạn và chạy trong bất kỳ quy trình CI nào. Karate được xây dựng chính xác cho mục đích đó. Nó sử dụng ngôn ngữ miền cụ thể (DSL) để bạn viết các bài kiểm thử dưới dạng các bước Given / When / Then thay vì các phương thức Java. Hướng dẫn này sẽ giải thích Karate là gì, cách các tệp tính năng của nó hoạt động và một ví dụ có thể chạy được.
Karate là gì
Karate là một framework tự động hóa kiểm thử mã nguồn mở, dựa trên Java dành cho API. Bạn mô tả mỗi bài kiểm thử dưới dạng một kịch bản trong tệp .feature bằng cách sử dụng Gherkin, cùng cấu trúc Given/When/Then xuất phát từ Phát triển theo hướng hành vi. Điểm khác biệt so với các công cụ như Cucumber là bạn không cần viết mã kết nối định nghĩa bước (step-definition glue code). Karate tích hợp sẵn các bước HTTP, các khẳng định (assertions) và xử lý JSON, vì vậy một bài kiểm thử API hoạt động không cần đến Java.

Dự án này không chỉ gói gọn việc kiểm thử API. Kho lưu trữ bao gồm các module cho mock, kiểm thử hiệu suất (thông qua Gatling) và tự động hóa giao diện người dùng. Đối với hướng dẫn này, trọng tâm là nhân tố cốt lõi kiểm thử API, đây là thứ mà hầu hết các nhóm ưu tiên tìm đến đầu tiên.
Bởi vì các bài kiểm thử là các tệp văn bản thuần túy, chúng dễ dàng quản lý phiên bản. Một bản diff của pull request cho thấy chính xác khẳng định nào đã thay đổi. Điều này rất phù hợp với việc xem xét mã và một quy trình làm việc dựa trên mã, tích hợp Git.
Nếu bạn chưa quen với kiểu Given/When/Then, phần giới thiệu của chúng tôi về Phát triển theo hướng hành vi sẽ giải thích nguồn gốc và lý do các nhóm sử dụng nó.
Cách hoạt động: Tệp tính năng và karate-config.js
Một bài kiểm thử Karate bắt đầu với một tệp tính năng. Mỗi tệp có một khối Feature: và một hoặc nhiều khối Scenario:. Bên trong một kịch bản, bạn thiết lập yêu cầu bằng Given, gửi yêu cầu bằng When và xác nhận bằng Then.
Dưới đây là cấu trúc mà phần khởi động nhanh của Karate chỉ ra:
Feature: User API
Scenario: List all users
Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
When method get
Then status 200
And match response == '#[10]'
Đọc từ trên xuống dưới. url đặt địa chỉ cơ sở. path thêm tài nguyên. method get gửi yêu cầu. status 200 kiểm tra mã HTTP. Dòng cuối cùng khẳng định phản hồi là một mảng JSON với chính xác 10 mục. #[10] là một ký hiệu của Karate, không phải JavaScript. Tìm hiểu thêm về các ký hiệu này trong phần khẳng định.
Gherkin ở đây là cấu trúc Given/When/Then tiêu chuẩn. Nếu bạn muốn tìm hiểu sâu hơn về cú pháp đó, hãy xem hướng dẫn về Gherkin cho BDD và kiểm thử API của chúng tôi.
Hầu hết các dự án đều cần các giá trị cụ thể theo môi trường: URL cơ sở phát triển, mã thông báo môi trường staging, điểm cuối sản xuất. Karate xử lý điều này bằng một tệp duy nhất có tên karate-config.js. Tệp này chạy một lần trước các bài kiểm thử của bạn và trả về một đối tượng cấu hình mà mọi kịch bản đều có thể đọc.
function fn() {
var env = karate.env || 'dev';
var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};
if (env === 'qa') {
config.baseUrl = 'https://qa.example.com';
}
return config;
}
karate.env đến từ một thuộc tính hệ thống mà bạn truyền vào khi chạy. Chuyển đổi môi trường mà không cần chạm vào bất kỳ tệp tính năng nào. Trong một kịch bản, bạn sẽ viết Given url baseUrl thay vì mã hóa cứng địa chỉ.
Một kịch bản mẫu
Hãy viết một cái gì đó với phần thân yêu cầu. Kịch bản này tạo một người dùng, kiểm tra trạng thái và xác thực hình dạng của phản hồi.
Feature: Create user
Background:
* url baseUrl
Scenario: Create a new user returns 201
Given path 'users'
And request { name: 'Ada', job: 'engineer' }
When method post
Then status 201
And match response.name == 'Ada'
And match response.id == '#string'
Một vài điều cần lưu ý. Khối Background: chạy trước mỗi kịch bản trong tệp, vì vậy bạn chỉ đặt URL cơ sở một lần. * là một bước ký tự đại diện; Karate coi * giống như Given, When hoặc Then, cho phép bạn viết các bước thiết lập mà không cần lo lắng về ngữ pháp. Từ khóa request nhận trực tiếp một payload JSON. Không cần serializer, không cần POJO. Và #string là một trình khớp mờ (fuzzy matcher) khẳng định trường id tồn tại và là một chuỗi, mà không ràng buộc nó với một giá trị cụ thể.
Khẳng định và khớp JSON
Các khẳng định là nơi Karate thể hiện giá trị của nó. Từ khóa cốt lõi là match. Nó so sánh một giá trị thực tế với một giá trị mong đợi và làm cho bài kiểm thử thất bại nếu có bất kỳ sự không khớp nào.
Khớp chính xác kiểm tra sự bằng nhau:
And match response == { id: '#number', name: 'Ada', job: 'engineer' }
Các token #number, #string, #boolean và #uuid là các trình khớp mờ (fuzzy matchers). Chúng khẳng định kiểu và sự hiện diện mà không yêu cầu một giá trị cố định, giúp các bài kiểm thử ổn định khi máy chủ trả về các ID hoặc dấu thời gian được tạo.
Khi bạn chỉ quan tâm đến một tập hợp con các trường, hãy sử dụng contains:
And match response contains { name: 'Ada' }
Điều đó được thông qua miễn là name bằng Ada, ngay cả khi phản hồi có mười trường khác. Karate cũng hỗ trợ !contains, contains only, contains any và contains deep để kiểm soát tốt hơn việc khớp một phần.
Bạn cũng có thể xác thực mảng. match response == '#[10]' khẳng định một mảng có độ dài 10. Bạn có thể áp dụng một schema cho mỗi phần tử bằng each:
And match each response == { id: '#number', name: '#string' }
Dòng này kiểm tra rằng mọi đối tượng trong mảng đều có id số và name chuỗi. Loại xác thực hình dạng này sẽ cần một vòng lặp và nhiều khẳng định trong một framework kiểm thử đa năng. Nếu bạn muốn có cái nhìn tổng quan hơn về việc xác thực phản hồi, hướng dẫn thực tế về các khẳng định API của chúng tôi bao gồm các mẫu trên các công cụ.
Kiểm thử theo hướng dữ liệu và CI
Các bộ kiểm thử thực tế chạy cùng một logic với nhiều đầu vào. Karate xử lý điều này bằng Scenario Outline và một bảng Examples. Các chỗ giữ chỗ trong dấu ngoặc nhọn sẽ được điền từ mỗi hàng.
Scenario Outline: Create users from a table
Given url baseUrl
And path 'users'
And request { name: '<name>', job: '<job>' }
When method post
Then status 201
And match response.name == '<name>'
Examples:
| name | job |
| Ada | engineer |
| Grace | scientist |
| Alan | analyst |
Điều đó chạy kịch bản ba lần, mỗi lần một hàng. Bạn cũng có thể đọc các hàng từ một tệp bên ngoài thay vì một bảng nội tuyến, giúp giữ các tập dữ liệu lớn ra khỏi các tệp tính năng của bạn:
Examples:
| read('classpath:test-data/users.json') |
Karate đọc các tệp JSON và CSV theo cách này, vì vậy dữ liệu kiểm thử của bạn có thể nằm ở bất cứ đâu mà nhóm của bạn muốn quản lý.
Đối với tích hợp liên tục, bạn có hai lựa chọn. Trong một dự án Maven hoặc Gradle, Karate chạy thông qua JUnit 5. Bạn thêm phụ thuộc karate-junit5 và trỏ một trình chạy (runner) đến các tệp tính năng của mình, để mvn test thực thi chúng như bất kỳ bài kiểm thử đơn vị nào khác. Điều đó có nghĩa là bước CI hiện có của bạn không cần công cụ đặc biệt nào.
Lựa chọn thứ hai là tệp jar độc lập, không cần công cụ xây dựng. Tải xuống karate.jar từ các bản phát hành của dự án và chạy trực tiếp các tệp tính năng. Lưu ý rằng tệp jar yêu cầu phiên bản Java gần đây, vì vậy hãy kiểm tra ghi chú phát hành để biết yêu cầu tối thiểu.
java -jar karate.jar src/test/java/features
Bạn có thể lọc theo thẻ, chạy song song và chọn một thư mục đầu ra:
java -jar karate.jar --tags @smoke --threads 4 --output reports src/test/java/features
Truyền một môi trường bằng một thuộc tính hệ thống, thuộc tính này sẽ đi vào karate.env bên trong karate-config.js:
java -jar karate.jar -Dkarate.env=qa src/test/java/features
Karate ghi một báo cáo HTML vào thư mục đầu ra sau mỗi lần chạy, vì vậy các lỗi rất dễ kiểm tra trong một artifact của pipeline. Để có cái nhìn tổng quát hơn về CI, hãy xem cách tự động hóa kiểm thử API trong CI/CD.
Điểm mạnh và đánh đổi
Karate có những điểm mạnh rõ ràng. Các bài kiểm thử dễ đọc gần như tiếng Anh thông thường, giúp giảm rào cản cho những người không thạo Java. Tính năng khớp JSON tích hợp sẵn, bao gồm các trình khớp mờ và each, loại bỏ rất nhiều mã khẳng định lặp lại. Mọi thứ nằm trong các tệp văn bản dưới Git, vì vậy việc xem xét và so sánh các bài kiểm thử giống như mã nguồn. Và nó bao gồm nhiều hơn là HTTP, vì vậy một nhóm có thể thêm mock hoặc kiểm thử hiệu suất sau này mà không cần chuyển đổi công cụ.
Những đánh đổi cũng là có thật. Karate chạy trên JVM, vì vậy bạn cần cài đặt Java và có mức độ thoải mái nhất định với hệ sinh thái JVM cho bất kỳ điều gì ngoài những điều cơ bản. DSL là một thứ riêng biệt để học; cú pháp dễ đọc nhưng việc viết các trình khớp chính xác và các mẫu tái sử dụng cần thực hành. Logic có thể tái sử dụng, các hàm hỗ trợ tùy chỉnh và thiết lập phức tạp thường kéo bạn trở lại với các hàm JavaScript hoặc tương tác với Java. Và bởi vì các bài kiểm thử là mã, những người không phải là nhà phát triển trong nhóm thường không thể tạo hoặc chỉnh sửa chúng mà không có sự trợ giúp.
Không có điều nào trong số đó là một sự chỉ trích. Đó là hồ sơ của một framework ưu tiên mã. Vấn đề là liệu hồ sơ đó có phù hợp với cách nhóm của bạn muốn làm việc hay không.
Karate so với cách tiếp cận không mã (Apidog)
Karate dựa trên mã và tích hợp Git. Bạn viết các tệp tính năng, commit chúng và chạy chúng từ một công cụ xây dựng hoặc tệp jar. Điều này phù hợp với các kỹ sư muốn các bài kiểm thử trong kiểm soát phiên bản bên cạnh ứng dụng và những người thoải mái với JVM.
Apidog đi theo con đường trực quan, không mã để đạt được mục tiêu tương tự. Bạn xây dựng các kịch bản kiểm thử trong giao diện người dùng, nối chuỗi các yêu cầu và thêm các khẳng định bằng cách nhấp chuột thay vì viết DSL. Bởi vì toàn bộ vòng đời API (thiết kế, gỡ lỗi, mock, tài liệu) nằm ở một nơi, các bài kiểm thử có thể tái sử dụng các điểm cuối và schema bạn đã định nghĩa. Điều này làm giảm rào cản cho các kỹ sư QA và những người làm sản phẩm không muốn quản lý một dự án Java.

Các bộ kiểm thử trực quan không bị giới hạn trong giao diện người dùng. Apidog chạy chúng không giao diện (headless) trong CI thông qua Apidog CLI, vì vậy một bộ kiểm thử không mã vẫn phù hợp với một pipeline tự động. Bạn cài đặt nó bằng Node:
npm install -g apidog-cli
Sau đó kích hoạt một kịch bản hoặc bộ kiểm thử đã lưu bằng ID, trỏ đến một môi trường và chọn định dạng báo cáo:
apidog run --access-token "$APIDOG_ACCESS_TOKEN" -t <scenarioOrSuiteId> -e <environmentId> -r cli,html,junit
Cờ -t nhắm mục tiêu đến một kịch bản, thư mục hoặc bộ kiểm thử; -e chọn môi trường; -r chọn một hoặc nhiều trình tạo báo cáo (cli, html, json, junit). Đối với các lần chạy dựa trên dữ liệu, -d (hoặc --iteration-data) nhận đường dẫn tệp dữ liệu hoặc ID dữ liệu kiểm thử. CLI là không giao diện và chạy trên bất kỳ bước CI nào có thể chạy Node. Nó chạy các kịch bản Apidog đã lưu của bạn; nó không phải là một công cụ gửi yêu cầu tương tác hay một trình tạo tải. Xem hướng dẫn đầy đủ trong Apidog CLI cho CI/CD, và so sánh song song với một trình chạy khác trong Apidog CLI so với Newman.
Cả hai cách tiếp cận đều tạo ra các bài kiểm thử API tự động chạy không giao diện trong CI. Điểm khác biệt là phong cách soạn thảo: Karate muốn bạn viết DSL trong Git; Apidog muốn bạn nhấp chuột trong một giao diện người dùng mà cũng có thể xuất ra pipeline.
Cách lựa chọn
Chọn Karate khi nhóm của bạn có nhiều nhà phát triển, thoải mái với JVM và muốn các bài kiểm thử được quản lý phiên bản dưới dạng mã ngay bên cạnh ứng dụng. Các tệp tính năng văn bản thuần túy và tính năng khớp JSON tích hợp sẵn sẽ mang lại lợi ích khi các kỹ sư sở hữu bộ kiểm thử từ đầu đến cuối.
Chọn một công cụ không mã như Apidog khi những người viết bao gồm QA và những người làm sản phẩm, khi bạn muốn các bài kiểm thử được gắn liền với một quy trình thiết kế và tài liệu hiện có, hoặc khi bạn không muốn duy trì một bản dựng Java để chạy kiểm tra API. Bạn vẫn có được phạm vi CI thông qua CLI.
Một số nhóm chạy cả hai: Karate cho các bộ kiểm thử hồi quy sâu, do mã sở hữu và một công cụ trực quan cho phạm vi phủ sóng rộng, nhanh chóng mà những người không phải nhà phát triển có thể mở rộng. Nếu bạn vẫn đang cân nhắc các lựa chọn, tổng quan của chúng tôi về cách chọn một framework kiểm thử tự động hóa API sẽ trình bày các tiêu chí quyết định.
Câu hỏi thường gặp
Tôi có cần biết Java để sử dụng Karate không? Không, không cần cho việc viết các bài kiểm thử API cơ bản. Các tệp tính năng sử dụng Gherkin DSL, và Karate cung cấp sẵn các bước HTTP và khẳng định. Bạn sẽ cần cài đặt Java để chạy các bài kiểm thử, và một chút kiến thức về Java hoặc JavaScript sẽ hữu ích khi bạn cần các hàm hỗ trợ tùy chỉnh hoặc thiết lập phức tạp.
Karate khác với Cucumber như thế nào? Cả hai đều sử dụng cú pháp Given/When/Then của Gherkin. Với Cucumber, bạn viết mã định nghĩa bước để hỗ trợ mỗi bước. Karate cung cấp các bước kiểm thử API cho bạn, vì vậy không có mã kết nối nào để duy trì cho các bài kiểm thử HTTP tiêu chuẩn.
Karate có thể chạy mà không cần Maven hoặc Gradle không? Có. Tải xuống tệp karate.jar độc lập từ các bản phát hành của dự án và chạy các tệp tính năng bằng java -jar karate.jar <path>. Nó hỗ trợ các thẻ, chạy song song và thư mục đầu ra tùy chỉnh mà không cần bất kỳ công cụ xây dựng nào.
Cú pháp #string hoặc #[10] có nghĩa là gì? Đó là các trình khớp mờ (fuzzy matchers) của Karate. #string khẳng định một trường là một chuỗi với bất kỳ giá trị nào, #number là một số, và #[10] khẳng định một mảng JSON có độ dài 10. Chúng cho phép bạn xác thực hình dạng phản hồi mà không cần mã hóa cứng các giá trị được tạo.
Các bài kiểm thử API không mã có thể vẫn chạy trong CI không? Có. Một công cụ trực quan như Apidog xuất các kịch bản đã lưu ra Apidog CLI, công cụ này là không giao diện và chạy trên bất kỳ bước CI nào có Node. Vì vậy, bạn viết các bài kiểm thử trong giao diện người dùng và vẫn có được các lần chạy pipeline tự động.
