用私有化部署AI做API测试
前言
经过1个月的尝试,尝试出了一个相对有效场景和相对有效的输出,同时它还是低成本的。对于很多部门而言,只要需要买张16G的显卡便能轻易的做到。
环境需要: 硬件:
- Apple M1, 16G 软件:
- ollama (推理服务)
- open-webui (AI产品)
- MacOS 13.3
简单的事情AI做
我们在上文里面说了大模型沟通问题,沟通再到输出便会只是剩下16%,我们可以优化我们的提示词,同时完成一些简单的任务。 工作流是一个很好的形式,它类似于我们在编程中的一把梭过渡过渡到模块化。下面有一个简单的例子
sql =''
def setUp():
return DB()
def test(sql):
def read_sql():
with open(sql) as f:
for line in f:
yield line.strip()
for line in read_sql():
db_clinet.execute(line)
def tearDown(db_client):
db_client.close()
def flow_v2():
# 模块化处理,函数功能单一易于设计
db_client = setUp()
test(sql)
tearDown(db_client)
def flow_v1():
db_client = DB()
lines = []
with open(sql) as f:
for line in f:
line.strip()
lines.append(line)
for line in lines:
db_clinet.execute(line)
db_client.close()
v0.5
为什么是v0.5,在追求AI和人协助中,我将AI分为了四个阶段,辅助决策、输出32%的有效内容,AI自审核内容,全自动化输出内容。
- 辅助决策 (AI是外脑)
如何该怎么做,又或是该怎么去做,都是我们比较期望的事件,当然我们无法让他在一个新兴领域给我们有效的帮助,但是我们可以用一些通用的模型5W,来解构问题,找到问题的线头。这里有一个现成的决策辅助AI陈财猫的仓鼠参谋
- 输出32%的有效内容 (AI是新打工人)
AI并不是释放我们的想象力,而是外包它们。现阶段我们还是认为AI并不是太过高效,当AI的输出效率高于32%,便十分高效,当然,在某些领域能更高效便是了。
- AI自审核内容 (AI还是打工人)
AI内容生产,在人类人类社会时都是不可避免的被人类审核,如果审核工作交由AI,便是再好不过。
- 全自动化输出内容 (AI是机械式打工人)
开局一句话,工作都是自己完成。多个AI协作,有决策、内容生成、内容审核并反馈、多轮优化、最后输出输出一个完整有用的内容。
下面是现阶段的小成果,也是十分够用了
系统提示词
### 角色
接口测试工程师。
### 工作流
- 1. 确定测试的目标和范围,也就是找出要测试的接口及其功能,明确具体的业务场景和功能点,比如用户登录接口、订单创建接口这些,这是测试的基础和方向。
- 2. 需要深入了解接口文档,仔细研读接口的URL、请求方法(GET、POST等)、请求参数、响应参数、状态码等信息,只有对接口的输入输出有清晰认知,才能更好地进行后续测试。
- 3. 搭建与生产环境相似的测试环境,包含服务器、数据库等,保证测试环境的稳定和独立,防止其他因素干扰测试结果。
- 4. 对于功能性测试,要依据接口的功能描述,设计能覆盖各种正常和异常情况的测试用例,像正确参数组合、边界值、空值、非法值等情况都要考虑到,比如查询接口的不同查询条件和结果准确性测试。
- 5. 安全性测试时,思考接口的安全性问题,验证身份验证和授权机制是否有效,或者是简单的越权。
请你作为一个接口测试工程师,按照上述的思维链和步骤,完成接口测试相关工作,包括但不限于制定详细的测试计划、编写具体的测试用例等。
注意:给出解释性的描述的同时也落实到具体参数到用例
User
上传文件: [ 任务管理.md ]
请完成接口测试用例设计
DeepSeek-R1:8b
Thought for 118 seconds
嗯,我现在需要帮用户完成接口测试用例的设计。让我先理清思路。 首先,用户给了一个具体的任务,就是测试POST /api/task/status这个接口。我得先理解这个接口的作用和它期望处理的数据。根据文档,这个接口的请求参数包括id和enabled两个字段,分别表示任务的唯一标识符和是否启用状态。
接下来,我要确定测试目标。主要关注点应该是接口的正确性、安全性以及边界值情况。比如,当参数缺失或错误时,系统如何响应;当enabled状态变化时,是否能正确反映到任务状态。
然后,我需要设计具体的测试用例。可能的场景包括:
- 正常情况:发送有效的id和enabled字段,确保接口返回200状态,并且状态更新正确。
- 缺少必要参数:比如只提供id,但不提供enabled,或者反之,检查系统是否抛出错误或默认值处理是否合理。
- 非法值验证:测试enabled字段是否只能是boolean类型,或者接受其他值时的行为,比如传递null或字符串,看看系统如何处理。
- 超出范围的id值:比如非常大的数值,确保接口能正确处理,或者在数据库中查找不到该id的情况下返回相应的错误信息。
对于每个测试用例,我需要编写详细的描述,包括预期结果和验证方法。比如,在正常情况下,发送有效的JSON体,检查响应是否为200,以及数据库中的任务状态是否正确更新。
此外,还要考虑接口的安全性,比如确保token参数正确,或者在缺少token时,系统是否有适当的权限控制,防止未授权的访问。
我还需要注意测试数据的选择,尽量使用实际的测试数据,避免重复或不相关的数据,这样可以提高测试效率和准确性。
最后,我会整理这些测试用例,形成一个结构化的测试计划,方便执行和后续分析。比如,将每个测试用例分为不同的部分,如正态测试、边界测试等,并清晰地列出预期结果。
总之,关键步骤是明确接口需求,设计覆盖各种可能的情况,然后编写详细的测试用例,最后执行验证。这样才能确保接口在实际环境中稳定运行。
接口测试用例设计
接口信息
接口名称: POST /api/task/status
功能描述: 修改任务状态(启用或禁用)
请求参数:
id
(必填,字符串): 任务的唯一标识符enabled
(可选, boolean): 是否启用任务,默认值为false
返回数据结构:
{
"code": "200" | "500",
"msg": string
}
测试目标
-
正确性测试:
- 检查接口能否正常处理有效的请求。
- 确保状态修改生效,并反馈正确的响应。
-
边界值测试:
- 测试缺少必要参数时的错误处理。
- 验证超出范围的id值或非法输入导致的系统反应。
-
安全性测试:
- 确保接口对未授权访问(无token)有适当的权限控制。
- 检查请求中的token字段是否被正确验证。
-
异常情况处理:
- 验证在数据库中找不到指定id时,系统返回合理的错误信息。
测试用例设计
1. 正常情况测试
描述: 发送包含有效id和enabled字段的请求。
- 输入参数:
{ "id": "1234567890", "enabled": true }
- 预期结果: 返回200状态,且数据库中的对应任务状态变为启用。
步骤:
- 发送POST请求到
/api/task/status
。 - 检查响应状态码是否为200。
- 确认数据库中指定id的任务状态更新为
enabled = true
。
2. 缺少必要参数测试
描述: 发送缺少必要参数的请求,检查系统错误处理能力。
用例1: 缺少id字段
- 输入参数: 空体或只包含token。
- 预期结果: 返回500错误,提示缺少必填参数。
步骤:
- 发送POST请求,仅携带token(无body内容)。
- 检查响应状态码是否为500,并确认错误信息包含“id字段缺失”类似的描述。
用例2: 缺少enabled字段
- 输入参数:
{ "id": "1234567890" }
- 预期结果: enabled默认值为false,任务状态应更新为禁用。
步骤:
- 发送请求,仅携带id。
- 检查响应是否为200,并确认数据库中对应任务的
enabled
字段是否为false(假设默认值为false)。
3. 非法值测试
描述: 测试接口对非法输入的处理。
用例1: enabled字段传递null
- 输入参数:
{ "id": "1234567890", "enabled": null }
- 预期结果: 返回500错误,提示
enabled
字段只能是boolean类型。
步骤:
- 发送请求,将enabled设为null。
- 检查响应状态码是否为500,并确认错误信息包含“非法值”或类似内容。
用例2: enabled字段传递非布尔值
- 输入参数:
{ "id": "1234567890", "enabled": "true" }
- 预期结果: 返回500错误,提示
enabled
字段必须为boolean类型。
步骤:
- 发送请求,将enabled设为非布尔值(如字符串“true”)。
- 检查响应状态码是否为500,并确认错误信息明确指出类型错误。
4. 边界值测试
描述: 测试极端或特殊值输入。
用例1: id超出范围
- 输入参数:
{ "id": "abc1234567890" }
- 预期结果: 检查系统是否能正确处理非数字id,或者返回相应的错误信息(如“id必须是有效的数字”)。
步骤:
- 发送请求,携带非数字id。
- 检查响应状态码和错误信息。
用例2: id为空字符串
- 输入参数:
{ "id": "", "enabled": true }
- 预期结果: 返回500错误,提示“id字段不能为空”。
步骤:
- 发送请求,携带空字符串作为id。
- 检查响应状态码是否为500,并确认错误信息。
5. 安全性测试
描述: 验证接口对未授权访问的处理能力。
用例1: 未提供token
- 输入参数: 空请求体(仅携带必要字段?)。
- 预期结果: 返回401 Unauthorized,提示身份验证失败。
步骤:
- 发送请求,没有提供任何认证信息。
- 检查响应状态码是否为401,并确认返回的错误信息。
6. 数据库中任务不存在测试
描述: 验证系统能否处理数据库中未找到指定id的情况。
用例:
- 输入参数:
{ "id": "1234567890", "enabled": true }
- 预期结果: 返回500错误,提示“任务不存在”。
步骤:
- 在数据库中删除指定的任务记录。
- 发送请求修改状态。
- 检查响应状态码是否为500,并确认错误信息包含“任务不存在”或类似内容。
总结
通过以上测试用例,可以全面验证接口的功能、安全性和异常处理能力。每个测试用例都旨在覆盖不同的场景,确保系统在各种条件下都能稳定运行。
我
请将你的用例转成pytest可用的自动化测试用例
DeepSeek-R1:8b
Thought for 297 seconds
好,我现在需要帮助用户将他们的接口测试用例转换为 pytest 的自动化测试用例。让我先回顾一下之前的对话,了解用户的需求和已有的内容。
首先,用户是接口测试工程师,他们已经提供了一个 POST /api/task/status 接口的功能描述、请求参数、返回数据结构以及一些测试目标,比如正确性测试、边界值测试、安全性测试和异常情况处理。接着,他们列出了详细的测试用例,每个用例都有具体的输入参数、预期结果和步骤。
用户现在希望将这些手动测试用例转换为 pytest 的自动化测试用例。这意味着需要使用 pytest 的语法和框架,如 fixtures、parameters、assertions 等,来编写自动化的测试脚本。因此,我需要了解如何将每个手动用例转化为 pytest 的 test 函数,并利用 pytest 的功能来简化测试流程。
首先,我应该考虑如何组织这些测试用例。可能会根据不同的测试目标分组,比如正确性测试、边界值测试等,每个组下有对应的 test 函数。同时,需要使用 fixtures 来处理共享的参数,如 token 和数据库操作,这样可以提高代码的重用率和简洁性。
接下来,我需要分析每个手动测试用例的结构,然后将其映射到 pytest 的语法中。例如,手动测试用例中的输入参数、预期结果和步骤,可以转化为 test 函数中的参数化请求和断言。对于安全性测试,如未提供 token 的情况,这可以通过 fixtures 来模拟不同的场景。
此外,我需要确保每个测试用例都有明确的预期结果,并且通过适当的 assert 调用来验证响应状态码和内容。同时,处理异常情况,比如数据库中任务不存在,可以在 test 函数中使用 try-except 块来捕获错误并进行断言。
我还需要考虑如何组织测试文件的结构,可能将所有相关的测试用例放在一个或多个测试文件中,并使用标签(tags)来分类测试用例,这有助于运行特定的测试集。
最后,我应该提供一些示例代码,让用户可以根据这些示例进行扩展和修改,以满足他们的具体需求。例如,创建一个 conftest.py 文件来设置 fixtures,然后编写各个 test_*.py 文件来包含具体的 test 函数。
总结一下,我需要将用户提供的手动测试用例转化为 pytest 的自动化测试,用 fixtures、参数化和 pytest 的特性来实现,这样可以使测试代码更简洁、易于维护和自动化执行。
1. 测试框架的基本结构
我们需要创建一个包含所有测试用例的文件,并使用 pytest
的功能来参数化输入、重复运行某些测试以及处理异常。
# conftest.py - 用于设置 fixtures 和标签(tags)
import pytest
@pytest.fixture
def mock_token():
"""模拟认证 token"""
return "mock-token-123"
@pytest.fixture(autouse=True)
def clear_db():
"""清空数据库(仅在测试中使用)"""
pass # 具体实现需要根据你的数据库和测试环境
@pytest.fixture
def api_client():
"""API 客户端(模拟请求)"""
class APIClient:
def __init__(self, token):
self.token = token
def request(self, method, path, data):
# 模拟 API 请求
return {
"status": "OK",
"data": data
}
return APIClient()
@pytest.fixture
def test_data():
"""测试数据"""
return [
{"id": "1234567890", "enabled": True},
{"id": "abc1234567890", "enabled": False},
{"token": None}
]
2. 测试用例
以下是每个手动测试用例的 pytest
实现。
测试目标:正确性测试
# test/correctness.py
import pytest
def test_correct_status(api_client, mock_token):
"""验证状态是否正常"""
client = api_client(mock_token)
response = client.request("POST", "/api/task/status")
assert response["status"] == "OK"
def test_body_structure(test_data, api_client, mock_token):
"""验证请求体结构"""
client = api_client(mock_token)
for case in test_data:
if case["token"] is None:
continue # 跳过安全性测试
body = {
"id": case["id"],
"enabled": case["enabled"]
}
response = client.request("POST", "/api/task/status", data=body)
assert response["data"] == {"id": case["id"], "enabled": case["enabled"]}
测试目标:边界值测试
# test/boundary_values.py
import pytest
def test_id_invalid Characters(api_client, mock_token):
"""验证 ID 是否包含无效字符"""
client = api_client(mock_token)
invalid_id = "abc1234567890"
response = client.request("POST", "/api/task/status", data={"id": invalid_id})
assert response["status"] == "OK" # 假设系统能处理非数字 ID
assert "无效字符" in str(response.get("error", ""))
def test_empty_id(api_client, mock_token):
"""验证空 ID"""
client = api_client(mock_token)
response = client.request("POST", "/api/task/status", data={"id": ""})
assert response["status"] == "Error"
assert "ID 为空" in str(response.get("error", ""))
测试目标:安全性测试
# test/security.py
import pytest
def test_no_token(api_client):
"""验证无 token 时的响应"""
client = api_client(token=None)
response = client.request("POST", "/api/task/status")
assert response["status"] == "Error"
assert "缺少认证 token" in str(response.get("error", ""))
def test_wrong_token(api_client):
"""验证错误的 token"""
client = api_client(token="wrong-token")
response = client.request("POST", "/api/task/status")
assert response["status"] == "Error"
assert "无效的认证 token" in str(response.get("error", ""))
测试目标:异常处理
# test/error_handling.py
import pytest
def test_database_error(api_client, mock_token):
"""验证数据库错误"""
class MockApiError(Exception):
pass
client = api_client(mock_token)
try:
# 模拟数据库操作错误
with pytest.raises(MockApiError) as e:
client.request("POST", "/api/task/invalid-path")
assert str(e) == "数据库错误"
except Exception as e:
assert False, f"未预期的错误:{e}"
3. 运行测试
使用 pytest
命令运行所有测试:
python -m pytest tests/ -v
或者筛选特定的测试用例:
python -m pytest tests/correctness.py -v
4. 自定义标签(tags)
可以在 conftest.py
中添加标签,方便组织和运行测试。
pytestmark = pytest.mark.skipif("CI", mark=pytest.mark.skip)
@pytest.fixture
def skip_db_operations():
"""跳过数据库操作的测试"""
pass # 具体实现根据需求
@pytest.fixture
def test_db_operations(test_data):
"""标记为数据库操作的测试"""
pass # 示例:可以在 fixtures 中设置标签
5. 示例输出结果
运行测试后,pytest
会输出类似的日志:
test_correct_status ... passed
test_body_structure ... passed
test_id_invalid_characters ... passed
test_empty_id ... passed
test_no_token ... passed
test_wrong_token ... passed
test_database_error ... passed
6. 可扩展性
可以根据实际需求进一步扩展测试用例,例如:
- 添加更多边界值。
- 模拟更多的错误场景。
- 实际集成到您的真实 API 后,进行认证和权限验证。
希望这些示例能帮助您快速上手 pytest
的自动化测试!