你真的会写自动化测试断言吗?

在接口测试中,断言是一项非常重要的操作,它是用来校验接口返回结果是否符合预期的一种手段。一般来说,接口测试断言大致可以分为以下几类:

  1. 状态码断言:这是最基本也是最常用的一种断言方式。大部分情况下,接口返回的HTTP状态码可以用来判断接口请求是否成功。
  2. 响应体断言:基于接口的响应数据进行校验。
  3. 响应时间断言:接口响应时间是否在可接受的范围之内。
  4. 数据库断言:接口调用后,数据是否有相应的变化。

这种使用断言来进行接口测试的方法,在测试框架中的具体实现可能各不相同。

下文将以Python的requests模块来做一个简单的例子。

首先,我们需要构造一个基本的GET请求,并获取响应:

import requests

response = requests.get('http://api.example.com/data')

在得到了响应后,我们可以使用Python的assert关键字来进行断言。比如我们可以断言状态码是200:

assert response.status_code == 200

如果状态码不是200,那么这个语句会抛出AssertionError

我们也可以断言响应的JSON数据中包含了某个特定的键:

data = response.json()
assert 'key' in data

同样,如果'key'不在data中,那么这个语句也会抛出AssertionError。对于更复杂的断言,我们可能需要使用一些第三方库来帮助我们。比如我们可以使用jsonschema库来断言响应数据符合某个JSON Schema:

from jsonschema import validate

schema = {
    "type" : "object",
    "properties" : {
        "key" : {"type" : "string"},
    },
    "required": ["key"]
}

validate(data, schema)

那么,对于更复杂的断言,我们该怎么做呢?

testng接口测试excel断言_软件测试

对于JSON响应断言,主要是确认返回的JSON对象中的某个或者某些元素是否和预期的一致。这种断言的方式,最常见的就是比对键值对是否相符了。举个例子,假设我们期待的JSON响应如下

{
    "title": "foo",
    "body": "bar",
    "userId": 1
}

我们可以使用Python来做一个简单的断言操作:

expected_json = {
    "title": "foo",
    "body": "bar",
    "userId": 1
}

response_json = response.json()

assert response_json == expected_json

在上述代码中,response.json()用来从响应中获取JSON数据,然后使用assert语句来断言这个JSON数据和我们期待的JSON数据是否相同。

如果我们只关心返回结果中的某一部分,例如,我们只关心返回结果中的title字段,那么我们可以做如下断言:

assert response_json['title'] == expected_json['title']

对于更复杂的JSON响应断言,比如,JSON响应为嵌套结构,或者是JSON数组,我们可能需要进行递归或者遍历等操作来进行断言,这种情况下可以使用一些第三方的断言库来提升我们的效率。比如Python的jsonpath库,可以帮助我们快速的定位JSON中的某一段数据,并进行断言

JsonPah是一种信息检索语言,可以让你用一个类似XPath的语法快速定位JSON结构中的部分内容处理嵌套结构的JSON响应时,JsonPath提供了一种简单有效的方法。重要的是理解JsonPath的语法,比如 '$' 表示根节点,'.' 或 '[]' 用于访问子节点,'*' 用于通配等。

下面举个例子来说明如何使用JsonPath:假定我们有一个如下的复杂JSON:

response_json = {
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
}

如果我们需要取出所有书的标题(title),可以使用如下语句:

from jsonpath import jsonpath

titles = jsonpath(response_json, '$.store.book[*].title')

print(titles) #输出:['Sayings of the Century', 'Sword of Honour', 'Moby Dick', 'The Lord of the Rings']

如果我们需要取出价格大于10的书的标题,可以使用如下语句:

titles = jsonpath(response_json, "$.store.book[?(@.price > 10)].title")

print(titles) # 输出:['Sword of Honour', 'The Lord of the Rings']

JsonPath非常简洁高效,能让我们的断言操作更简单,代码更清晰,既然这么强大的话,这不得有个使用方法

不着急,下面给你列出了常用的通配符的解析说明

JsonPath表达式中的通配符通常有以下几种:

  1. *:通配符,匹配所有的对象或元素。比如 $..book[*].author 可获取所有作者的名字。
  2. ..:深度操作符,无论深度多少层,都可以匹配到路径。比如 $..author 可获取所有的作者信息。
  3. . 或 []:逐层向下遍历,. 针对于名字,[] 针对于数组下标或者名称。比如 $['store']['book'][0]['price'] 获取第一本书的价格。
  4. @:现行节点信息,常在过滤器中使用,比如 $..book[?(@.price<10)] 意思是获取所有价格小于10的书。
  5. ():表达式组,用于根据自定义表达式过滤。比如 $..book[(@.length-1)] 获取最后一本书。
  6. ?():过滤操作符,用于查找符合条件的元素。比如 $..book[?(@.isbn)] 获取所有包含ISBN的书。

以上这些通配符让我们在使用JsonPath时有更大的灵活性,可以在大型或者嵌套较深的JSON数据中准确地定位我们所需要的数据。

那么,面试会怎么问呢

举个例子:

面试官:JsonPath表达式中的深度操作符..可以匹配到多少层的路径?

YOU:在JsonPath中,深度操作符 .. 在不知道精确路径或者需要查询多层嵌套数据时非常有用。.. 不关心元素在JSON数据中的精确位置,它会「深度搜索」,也就是说,无论数据嵌套在JSON结构的多深,只要符合你的查询条件,它都能找到。

可以用任何的名字或者通配符 * 来配合深度操作符一起使用,它们的组合可以匹配到任何级别的元素。例如,假设我们有一个JSON对象:

{
    "level_1": {
        "level_2": {
            "level_3": {
                "item": "value"
            }
        }
    }
}

如果你不知道 "item" 的精确路径,但你知道它的名字,并且你想从JSON数据中找到它,你可以使用 .. 操作符加上名字进行深度搜索,如:$..item,这将返回所有名为 "item" 的元素,无论它们处在哪一层级。

总的来说,深度操作符 .. 可以匹配到无限多层的路径,这对于处理深层嵌套的数据结构非常有用。

面试官:除了深度搜索,JsonPath还有其他什么功能可以处理深层嵌套的数据结构?

YOU:除了深度搜索外,JsonPath还提供了一些其他功能来处理深层嵌套的数据结构:

  1. 数组索引:JsonPath允许你使用数组索引来访问特定位置的元素。例如,表达式$.store.book[0]将返回图书数组的第一本书。
  2. 多个索引:JsonPath还允许你在同一层级上访问多个元素。例如,$.store.book[0,1]将返回图书数组的前两本书。
  3. 切片操作:JsonPath支持Python风格的切片操作,允许你访问一个连续的元素序列,而不仅仅是单个元素。例如, $.store.book[1:3]将返回图书数组的第二和第三本书。
  4. 过滤表达式:JsonPath支持过滤表达式,允许你使用逻辑运算符和比较运算符来过滤返回的元素。例如,$.store.book[?(@.price < 10)]将返回图书数组中价格低于10的所有书。
  5. 通配符:正如我们前面讨论的,*通配符可以用来匹配任意元素,不论位置。

总的来说,断言是接口测试中的一个重要部分,合理、充分地使用断言,不仅可以提升我们的测试质量,也能帮助我们快速定位问题。同时,塑造良好的断言策略,对于维护和持续提升一个测试框架也是尤为关键的。