httprunner 3.x學習3 - jmespath 提取返回結果(extract, validate)


前言

httprunner 3.x支持 jmespath 提取器提取返回的結果內容,可以在 extract 提取變量的時候使用,也可以在 validate 校驗結果的時候使用。

extract 提取變量

with_jmespath(jmes_path:文字,var_name:文字)

  • mes_path:jmespath表達式,有關更多詳細信息,請參考JMESPath教程https://jmespath.org/tutorial.html
  • var_name:存儲提取值的變量名,可以在后續測試步驟中引用它

如果請求接口結果返回格式如下

{
    "code": 0,
    "msg": "login success!",
    "token": "234af73571da46ade79ea6a74961b1d23d609b79",
    "username": "test"
}

需要提取token和username,於是可以這樣寫,extract 提取的時候,先調用.extract()方法

    .extract()
    .with_jmespath("body.token", "token")
    .with_jmespath("body.username", "user")

with_jmespath 方法提取body對象,后面接着jmespath的提取語法

validate 校驗結果

使用jmespath提取 JSON 響應正文並使用預期值進行驗證。

  • jmes_path:jmespath 表達式,更多細節參考JMESPath 教程
  • 預期值:這里也可以使用指定的預期值、變量或函數引用
  • 消息(可選):用於指示斷言錯誤原因
assert_XXX(jmes_path: Text, expected_value: Any, message: Text = "")

校驗結果先調用.validate()方法

            .validate()
            .assert_equal("status_code", 200)
            .assert_equal("body.code", 0)
            .assert_equal("body.msg", "login success!")
            .assert_length_equal("body.token", 40)

jmespath 提取示例

訪問/api/test/demo接口,接口返回如下

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

{
    "code":0,
    "msg":"成功success!",
    "data":[
        {
            "age":20,
            "create_time":"2019-09-15",
            "id":1,
            "mail":"283340479@qq.com",
            "name":"yoyo",
            "sex":"M"
        },
        {
            "age":21,
            "create_time":"2019-09-16",
            "id":2,
            "mail":"123445@qq.com",
            "name":"yoyo111",
            "sex":"M"
        }
    ]
}

需求:

  • 1.提取code值,校驗結果為:0
  • 2.msg值,校驗結果:成功success!
  • 3.提取data數據,校驗結果長度是:2
  • 4.提取data數據中第一條數據,校驗name的值:yoyo
  • 5.提取data數據中name的值為yoyo的郵箱,並校驗結果是:283340479@qq.com
  • 6.提取data數據組中,年齡大於20的結果,並校驗結果的數量是:1

httprunner3.x 對應的 py 代碼

# NOTE: Generated By HttpRunner v3.1.4
# FROM: test_demo.yml
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase


class TestCaseTestDemo(HttpRunner):

    config = Config("test demo").base_url("http://127.0.0.1:8000")

    teststeps = [
        Step(
            RunRequest("step login")
            .get("/api/test/demo")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal("body.code", 0)
            .assert_equal("body.msg", "成功success!")
            .assert_equal("body.length(data)", 2)
            .assert_equal("body.data[0].name", "yoyo")
            .assert_equal("body.data[?name=='yoyo'].mail", ["283340479@qq.com"])
            .assert_equal("body.data[?name=='yoyo'].mail|[0]", "283340479@qq.com")
            .assert_equal("body.length(data[?age>`20`])", 1)
        ),
    ]


if __name__ == "__main__":
    TestCaseTestDemo().test_start()

pytest 運行部分日志

2021-06-15 23:36:24.233 | INFO     | httprunner.client:request:218 - status_code: 200, response_time(ms): 32.95 ms, response_length: 0 bytes
2021-06-15 23:36:24.234 | INFO     | httprunner.response:validate:246 - assert status_code equal 200(int)       ==> pass
2021-06-15 23:36:24.235 | INFO     | httprunner.response:validate:246 - assert body.code equal 0(int)   ==> pass
2021-06-15 23:36:24.236 | INFO     | httprunner.response:validate:246 - assert body.msg equal 成成功功success!(str) ==> pass
2021-06-15 23:36:24.236 | INFO     | httprunner.response:validate:246 - assert body.length(data) equal 2(int)   ==> pass
2021-06-15 23:36:24.237 | INFO     | httprunner.response:validate:246 - assert body.data[0].name equal yoyo(str)        ==> pass
2021-06-15 23:36:24.238 | INFO     | httprunner.response:validate:246 - assert body.data[?name=='yoyo'].mail equal ['283340479@qq.com'](list)   ==> pass
2021-06-15 23:36:24.239 | INFO     | httprunner.response:validate:246 - assert body.data[?name=='yoyo'].mail|[0] equal 283340479@qq.com(str)    ==> pass
2021-06-15 23:36:24.240 | INFO     | httprunner.response:validate:246 - assert body.length(data[?age>`20`]) equal 1(int)        ==> pass
2021-06-15 23:36:24.241 | INFO     | httprunner.runner:__run_step:304 - run step end: step login <<<<<<

JMESPath 簡介

JMESPath 是 JSON的查詢語言,您可以從JSON文檔中提取和轉換元素,類似於 jsonpath 的另外一個庫。
關於 JMESPath 官方文檔介紹https://jmespath.org/tutorial.html#basic-expressions
使用pip安裝jmespath,github地址https://github.com/jmespath/jmespath.py

pip install jmespath

使用示例1,可以使用search jmespat h表達式並為其提供數據

import jmespath
path = jmespath.search('foo.bar', {'foo': {'bar': 'baz'}})
print(path)    # baz

使用示例2, 與re模塊類似,您可以使用該 compile 函數來編譯 jmespath 表達式,並使用此解析的表達式來執行重復搜索

import jmespath
expression = jmespath.compile('foo.bar')
a = expression.search({'foo': {'bar': 'baz'}})
b = expression.search({'foo': {'bar': 'other'}})
print(a)    # baz
print(b)    # other

基本表達式

字典取值,根據key名稱取到對應的值

嵌套的字典,可以一層一層取值

list可以根據下標取值

dict嵌套list可以一層一層的取值

切片

如果您曾經在python中使用過切片,那么您已經知道如何使用JMESPath slice。
您可以以最簡單的形式指定開始索引和結束索引。結束索引是您不希望包含在切片中的第一個索引。
讓我們看一些例子。首先,給定一個從0到9的整數數組,讓我們選擇該數組的前半部分:

該切片結果包含元素0、1、2、3和4。不包括索引5的元素。如果要選擇數組的后半部分,可以使用以下表達式:

上面的兩個示例可以簡化。如果開始或步驟被省略值它被假定為開始或數組的末尾。例如:

切片的一般形式是[start:stop:step]。到目前為止,我們已經研究了[start:stop]表單。缺省情況下,步驟值是1,這是指包括在由所指定的范圍中的每個元素開始和 停止值。但是,我們可以使用step值跳過元素。例如,僅從數組中選擇偶數元素。

還要注意在這個例子中,我們省略開始還有停止 值,使用該裝置0的啟動值,10為 停止值。在此示例中,表達式[:: 2]等效於 [0:10:2]。
關於切片的最后一件事是,就像索引單個值一樣,所有值都可以是負數。如果步長值為負,則以相反順序創建切片。例如:

上面的表達式創建一個切片,但順序相反。

列表取值使用 * 通配符

1.取出列表中所有的 first 對應的名稱 people[*].first

2.取出列表中前 2 個 first 對應的名稱 people[:2].first

對象取值使用 * 通配符

1.取出 ops 對象的任意屬性對應的numArgs ops.*.numArgs

子查詢使用 * 通配符

在查詢的結果中繼續使用 * 通配符,查詢的結果是列表的列表

如果我們只想要一個實例所有狀態的列表怎么辦?理想情況下,我們希望結果為[“ running”, “ stopped”, “ terminated”, “ running”]
在這種情況下,我們不在乎實例屬於哪個保留,我們只需要一個狀態列表。可以使用 [] 而不是 [*]

過濾器使用

過濾器表達式是為數組定義的,其一般形式為 [? <表達式> <比較器> <表達式>]
常用的比較表達式可以使用 ==!=<<=>> =

假設我們有一個機器列表,每個機器都有一個名稱和一個 state。我們想要所有正在運行的計算機的名稱

管道表達式

前面在匹配list里面的多個值時候,查詢的結果是一個list,如果我想取出結果里面的第一個可以使用管道符 |
取出people下所有對象的 first 屬性,從結果里面取第一個值: people[*].first | [0]

多選

到目前為止,我們已經研究了JMESPath表達式,這些表達式有助於將JSON文檔縮減為您感興趣的元素。下一個概念, 多選列表和 多選哈希允許您創建JSON元素。這使您可以創建JSON文檔中不存在的元素。多選列表創建一個列表,多選哈希創建一個JSON對象。

這是一個多選列表的示例:people[].[name, state.name]

在上面的表達式中,[name, state.name]部分是一個多選列表。它說要創建一個由兩個元素組成的列表,第一個元素是針對list元素評估名稱表達式的結果,第二個元素是對state.name評估的結果。因此,每個列表元素將創建一個兩個元素列表,並且整個表達式的最終結果是兩個元素列表的列表。

與投影不同,即使結果為null,也始終包含表達式的結果。如果將以上表達式更改為people []。[foo, bar],則每個兩個元素列表將為[null, null]。

多重選擇具有與多重選擇列表相同的基本概念,不同之處在於它會創建哈希而不是數組。使用上面的相同示例,如果我們想創建一個具有兩個鍵Name和 State的兩個元素哈希,則可以使用以下代碼:

函數的使用

JMESPath支持函數表達式,例如:length(people)

函數可用於以強大的方式轉換和過濾數據。可以在此處找到函數的完整列表,並且 函數表達式規范具有完整的詳細信息。

以下是一些功能示例。

本示例在people數組中打印最老的人的名字:

函數也可以與過濾器表達式組合。在下面的示例中,JMESPath表達式在myarray中查找包含字符串foo的所有元素。

上面示例中的@字符表示在myarray中正在評估的當前元素。如果myarray數組中的當前元素包含字符串 foo , 則包含(@,'foo')的表達式將返回 true。

盡管函數表達式規范包含所有詳細信息,但在使用函數時,需要牢記以下幾點:

函數參數具有類型。如果函數的參數類型錯誤,則會發生無效類型錯誤。有一些函數可以進行類型轉換(to_string,to_number),以幫助將參數轉換為正確的類型。
如果以錯誤的參數數量調用函數, 則將發生無效arity。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM