3分鐘閱讀
介紹在本文中,我們將學習如何自動化REST API的驗收測試。該API提供了端點來註冊和驗證使用者(註冊/登入)。此外,還提供了一個安全的端點來獲取使用者資料。該服務將保留並獲取mongo資料庫中的資料。
下面的流程圖表示該服務的工作方式。
> API Flow diagram
先決條件克隆包含以下內容的Git儲存庫
git clone [email protected]:ivancorrales/orion-test-api.git
此外,您應該在計算機上安裝Docker和Orion。
Orion-test-api我們將瀏覽儲存庫中的不同檔案和資料夾。
> repository content
docker-compose.yml服務和mongo資料庫的規範。
version: '3'services: app: image: ivancorrales/demo-api-mongo:0.0.1 environment: MONGODB_URI: mongodb://root:secret@mongodb:27017/admin ports: - 3000:3000 mongodb: image: mongo:latest environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: secret ports: - 27017:27017 volumes: - mongodb_data_container:/data/dbvolumes: mongodb_data_container:
讓我們執行docker-compose來啟動服務和mongo容器。
.env它包含要傳遞給Orion的環境變數。
.includes資料夾include / *中的api.hcl和database.hcl檔案包含可重用的函式來處理API和資料庫。
main.hcl該檔案將用作執行所有方案的入口點。
happyPath.hcl涵蓋幸福道路的場景。
signIn-failures.hcl / signUp-failures.hcl / showProfile-failures.一組場景,涵蓋了不愉快的道路。
我們開始做吧!首先,我們使用docker-compose up命令啟動docker-compose。服務API在localhost:3000上執行,而mongo在localhost:27017上執行。請記住,連線到mongo(root / secret)需要身份驗證。
驗收測試可以使用以下命令執行:
orion run --input main.hcl --vars env/local.hcl
但…。讓我們深入研究Orion檔案!
包括/ api.hcl它包含使用API端點的函式。這些功能是從方案中呼叫的。
實際上,閱讀功能非常簡單。您將意識到showProfile函式需要傳遞標頭x-access-token,因為這是一個安全的端點。
瞭解有關var,輸入引數,函式和操作的更多資訊http
vars { mediaJson = "application/json"}func signUp { input { arg baseApi { description = "URL base of the API" } arg user { description = "entity with attributes fullName, username & password" } } body { http post { request { baseUrl = baseApi path = "/account" headers { Content-Type = mediaJson } payload json { data = user } } response { httpResponse = { statusCode = _.http.statusCode body = json(_.http.body) } } } } return { value = httpResponse }}func signIn { input { arg baseApi { description = "URL base of the API" } arg credentials { description = "entity with attributes username & password" } } body { http post { request { baseUrl = baseApi path = "/session" headers { Content-Type = mediaJson } payload json { data = credentials } } response { httpResponse = { statusCode = _.http.statusCode body = json(_.http.body) } } } } return { value = httpResponse }}func showProfile { input { arg baseApi { description = "URL base of the API" } arg token { description = "a valid JWT" } } body { http get { request { baseUrl = baseApi path = "/me" headers { x-access-token = token } } response { httpResponse = { statusCode = _.http.statusCode body = json(_.http.body) } } } } return { value = httpResponse }}
包括/database.hcl它包含一個函式,該函式將在執行方案之前從方案中使用以清理資料庫。我們為資料庫和集合輸入引數定義預設值。
func dropCollection { input { arg mongoUri { description = "mongo uri" } arg database { description = "Name of the database" default = "admin" } arg collection { description = "Name of the collection" default = "users" } arg credentials { description = "A object with two attributes: username & password" } } body { mongo drop { connection { uri = mongoUri auth scram-sha-1{ username = credentials.username password = credentials.password } } query { database = database collection = collection } } }}
瞭解有關var,函式和action mongo的更多資訊
happyPath.hcl滿意路徑必須驗證使用者已註冊,透過身份驗證,然後他/他才能獲取她/他的個人資料詳細資訊。
您將意識到,當我們在include / api.hcl中呼叫函式時,不會傳遞引數baseApi。這是由於baseApi將成為main.hcl中的全域性變數。
scenario "happy path" { given "my user details" { set user { value = { fullName = "John Smith" username = "[email protected]" password = "secret" } } } when "I sign up" { call signUp{ # block with can be omitted since variable user is already in the scope with { user = user } as = "response" } } then "I am registered successfully" { assert { assertion = response.statusCode == 200 } } when "do login" { call signIn { with { credentials = { username = user.username password = user.password } } as = "response" } } then "I am authenticated successfully" { assert { assertion = response.statusCode == 200 } } when "I fetch my profile details" { call showProfile{ with { token = response.body.accessToken } as = "response" } } then "the returned data are ok" { assert { assertion = ( response.statusCode == 200 && response.body.fullName == user.fullName ) } }}
瞭解有關場景以及操作呼叫和斷言的更多資訊。
main.hcl該檔案用作執行所有方案的入口點。負責新增其他hcl檔案。除此之外,我們使用此檔案來定義全域性掛鉤並定義輸入引數。
description = <<EOF This feature verify that API works as expectedEOFincludes = [ "includes/database.hcl", "includes/api.hcl", "happyPath.hcl", "signUp-failures.hcl", "signIn-failures.hcl", "showProfile-failures.hcl"]input { arg baseApi { description = "URL base of the API" default = "http://localhost:3000/api" } arg mongoConn { description = "a map with connection details { uri='', username='', password=''}" }}before each { call dropCollection{ with { mongoUri = mongoConn.uri credentials = { username = mongoConn.username password = mongoConn.password } } }}
瞭解有關鉤子定義,輸入引數和包含的更多資訊
signUp-failures.hcl我們寫了兩種情況:“由於輸入資料無效,所以無法註冊使用者”或“此電子郵件已經有一個使用者”。
scenario "a user registration fails because required fields are not provcided" { examples = [ { fullName ="", username = "", password =""}, { fullName ="Jane Doe", username = "", password =""}, { fullName ="Jane Doe", username = "[email protected]", password =""}, { fullName ="Jane Doe", username = "", password ="secret"}, ] when "register the user" { call signUp { with { user = { fullName = fullName username = username password = password } } as = "createUserResponse" } } then "the server returns with a bad request error" { assert { assertion = createUserResponse.statusCode==400 } }}scenario "user registration fails when email is already in use" { given "a user with valid email & password" { set user { value = { username = "[email protected]", password = "secret"} } } when "tries to register the user" { # omit block `with` because both user and basiApi are in the scope call signUp { as = "response" } } then "the server returns with a success status code" { assert { assertion = response.statusCode==200 } } when "tries to register the same user" { # omit block `with` because both user and basiApi are in the scope call signUp { as = "response" } } then "the server returns with an error" { assert { assertion = ( response.statusCode==400 && response.body.message=="Failed! Username is already in use!" ) } }}
為了表示第一個請求不好的場景,我們將利用帶有示例的場景。
signIn-failures.hcl / showProfile.hcl這些檔案是空的。我鼓勵您嘗試自己實施方案。練習是我知道學習知識的唯一途徑……當然,如果您需要任何幫助,請告訴我!