比如增加接口,一般来说重复添加都会报错。那么如果第一次添加的用例发生了失败(添加成功了,但是查询或者校验时发生了失败),第二次执行时,必定会失败(因为重复添加),这样两次发生错误的原因不同了,有时候是无法真正探知到第一次失败的原因的,因为后面全是因为重复添加报错的。
在↑这种情况下,如果在最后使用删除接口将添加的内容删除掉,那么就不会影响测试的二次进行,我有点疑惑的是
我可以使用这个接口吗,如果使用删除接口,我是否可以信任这个接口?还是说这种情况下默认这个删除接口是没有问题的。
如果要” 重复执行保持一致 “, 删除接口也要” 先添加,再删除 “,这个接口的用例测试中是否也默认添加接口是没问题的?这个过程中我感觉都不仅仅是接口 A 依赖接口 B 这么简单了,而是接口的相互依赖了,感觉自己很难去告诉自己这样设计没问题。
请大家解惑释疑 ,以及请教是否存在更好的设计用例的方法!
有点懂了,自己也试了下,确实还是每个用例 setup 阶段就会创建新数据的方式,每次产生新的数据来解决问题,之前很疑惑 @ pytest.mark.parametrize()还是会导致两次数据一致 的问题,通过查阅一些资料发现用 @ pytest.fixture 里面的 params 和 ids 可以避免这个问题,也可以提供对用例的相关描述,并且即使不在一个文件也没有问题,如以下结构:
# data.py
fake = Faker()
def init_data(fixture_value):
if fixture_value == 10:
return "case 1"
elif fixture_value == 20:
return "case 2"
elif fixture_value == 30:
return "case 3"
@pytest.fixture(params=[10, 20, 30], ids=init_data)
def init_data_by_status(request):
status = request.param
# status 标识不同的用例!
print("fixture 参数", status)
# 这里创建新数据!
uid = fake.pyint(min_value=10086, max_value=99999, step=1)
yield dict(.....)# 传入的数据
# 这里可以清理数据操作,也可以定时清理,因为我的日志还比较完整,所以排查问题并不难,我选择的是即时清理。
# test.py
def test(init_data_by_status):
# 业务流程开始
谢谢大家的指教~ 学习到了很多细节上的问题的处理方法!
添加删除都有,那假设还有个查询接口也合理吧
添加然后查询,删除了再次查询,下次还是这一套,会有什么问题吗
添加用户是一个接口,有成功响应以及各种失败响应。
"输入合法用户信息,能够成功添加用户"这是一条用例,执行前得保证构造合法数据,想避免重复用时间戳做后缀是个不错的方法。
“输入已存在用户信息,提示用户重复” 这是另一条用例,执行前得保证该信息一定已在库中。
上面两条用例都是调用添加这个接口。
至于删除相关的用例,应当有一个前置条件,前置条件可以是通过调用添加接口或其他方式来实现。
所谓测试技术还是得围绕基础理论来转啊。
添加,然后查询,但是查询出错了,此时失败重跑,第二次,添加,这时会在添加时出错,因为实际上上一次添加成功了,所以这次再依次添加,会报错” 重复添加数据 “,所以两次报错原因会不一样,其他的上面说了。
"输入合法用户信息,能够成功添加用户"这是一条用例,执行前得保证构造合法数据,想避免重复用时间戳做后缀是个不错的方法。
如果是失败重跑的话,两次应该只能是一样的数据(即使添加了时间戳,但是通过@pytest.mark.parametrize()放进来的数据是不会变的),还是说这样必须在用例的流程中造数据来避免重复,但是这样不就违背了数据和业务分离的想法了吗?
在添加用例执行前,到数据库进行操作,删除你要添加的数据。
正统做法:
1、tearDown 里做好删除(调删除接口或直接删除数据库数据)。方便重复使用。
2、每次都重新初始化完整数据库内容,保证干净
但我们是金融类系统,为了方便回溯,系统其实是没有任何硬删除的。软删除且添加时带有一些不能重复的 key,会导致二次添加直接失败。直接删数据也不容易删干净,各个系统间有比较多关联关系。
这种情况下我们的偏门解法:每次都用新数据。从用户注册开始,全部都是新的数据。
请问您是如何设计失败重跑机制的呢?
我之前看到过的失败重跑机制有:
我们用的 java 的 testng ,重跑机制和你第二个比较接近。
没太明白你说的 重跑时的数据和第一次数据肯定是一样的
是为啥?我们每个用例 setup 阶段就会创建新数据了,所以重跑用的数据不会和第一次一样的。
哈哈,没想到还有一样做法的。握个爪
我觉得偏门,主要是和自动化测试的一些原则违背了。大量的一次性数据,虽然不影响什么,但还是会有点不大舒服。
我不是在 setup 中创数据的,而是直接弄一个数据模块,然后在测试用例中导入这个模块,因为有很多用例,所以没办法直接在 setup 中实现创造所有数据,比如 a 用例是字段 1 为空,b 用例字段 2 为空,因此我是直接重新设置了一个模块。但是这样也导致,导入之后,用例的数据不会发生改变,但是第一次运行和第二次运行的数据不一样。
是否可以考虑唯一性字段使用动态变量(随机数、时间戳、UUID 等?)
teardown 吧。teardown 的时候把你排查的时候要看的东西记录下来就行。
现在做的接口项目,我把重试机制直接干掉了,感觉没啥必要。如果报错,肯定是哪里有了问题,没必要重试。(当然不同项目可能不一样)
PS:接口测试,默认稳定。
比如:
data1.py
data_of_add_interface = [
{
"input": "a",
"expected": "error"
},
{
"input": "123",
"expected": "error"
},
...
]
test_case.py
from data1.py import data_of_add_interface
@ pytest.mark.parametrize("data", data_of_add_interface)
def test_case_1(data):
response = request_interface(data["input"])
assert data["expected"] == response
main.py
pytest.main(["./tests/test_case.py", "--reruns=2", "--reruns-delay=10", "-s"])
所以执行第一条用例时,两次重跑,data 中的数据是一样的,都是输入” a“,当然,data.py 中,我是使用了每次都是新数据的,但是执行重跑时还是一样。
如 19 楼的解释,请问使用了唯一性字段使用动态变量(随机数、时间戳、UUID 等?)
之后仍然无法结合重试机制进行怎么办?
想确认下,你的 data.py 数据的更新,是在什么时候更新的?
听你意思,是在运行所有用例前?
如果是,时机改为是运行任意用例前,那是不是就可以做到不管是首次执行还是重试执行,都会使用新的数据了?
PS:我觉得你问题的核心,是先排查清楚用例不稳定的原因,针对性解决,而不是纠结怎么重跑?
有点懂了,自己也试了下,确实还是每个用例 setup 阶段就会创建新数据的方式,每次产生新的数据来解决问题,之前很疑惑 @ pytest.mark.parametrize()还是会导致两次数据一致 的问题,通过查阅一些资料发现用 @ pytest.fixture 里面的 params 和 ids 可以避免这个问题,也可以提供对用例的相关描述,并且即使不在一个文件也没有问题,如以下结构:
# data.py
fake = Faker()
def init_data(fixture_value):
if fixture_value == 10:
return "case 1"
elif fixture_value == 20:
return "case 2"
elif fixture_value == 30:
return "case 3"
@pytest.fixture(params=[10, 20, 30], ids=init_data)
def init_data_by_status(request):
status = request.param
# status 标识不同的用例!
print("fixture 参数", status)
# 这里创建新数据!
uid = fake.pyint(min_value=10086, max_value=99999, step=1)
yield dict(.....)# 传入的数据
# 这里可以清理数据操作,也可以定时清理,因为我的日志还比较完整,所以排查问题并不难,我选择的是即时清理。
# test.py
def test(init_data_by_status):
# 业务流程开始
谢谢大家的指教~ 学习到了很多细节上的问题的处理方法!
这个属于测试数据管理方面的问题了,一般来说都是通过全局和局部 fixture 组合提供测试数据,每次使用 fixture 都是新的数据处理的,这样接口之间数据依赖就会解耦。
感觉属于职责不清晰
1:添加后查询出错,就要看为什么查询出错
2:添加后再删除,是不是默认添加是正常的?是的,因为添加接口是在其它用例来保证的