什么是软件测试中的并发测试?

⚡ 智能摘要

并发测试能够检测出只有当多个用户同时操作同一应用程序时才会出现的缺陷,从而暴露出顺序功能检查永远无法发现的死锁、丢失更新和锁定问题。

  • 👥 也被称为: 多用户测试,因为触发条件是同时访问,而不仅仅是大量访问。
  • 🎯 目标: 多个会话可以访问共享的数据库记录、共享的模块和共享的应用程序代码。
  • 🔒 测量内容: 死锁、锁定、单线程代码和对共享资源的受限访问程度。
  • 🧭 运行原理: 识别容易出现并发问题的流程,设定并发目标,编写实际操作脚本,然后逐步增加用户数量。
  • 🐞 缺陷类别: 竞态条件、死锁、更新丢失、数据损坏和线程饥饿。
  • ⚠️ 诚实的界限: 不确定性、异步回调和信息不完整的调用堆栈使得故障难以重现。

在软件测试中,什么是并发测试,即在多个用户同时进行测试的情况下进行测试?

什么是并发测试?

并发测试 是一种用于检测应用程序在多用户登录情况下缺陷的测试技术。换句话说,它监控多个用户同时执行相同操作时的影响。

并发测试也称为 多用户测试测试并发程序比测试顺序程序更具挑战性,因为存在不确定性和同步问题:即使代码没有发生任何变化,同一个测试也可能在一次运行中通过,而在下一次运行中失败。

下图说明了这一概念——多个用户在同一时刻访问同一个应用程序资源,测试观察应用程序如何处理重叠部分。

并发测试图,显示多个用户同时访问同一应用程序资源的情况。

为什么需要并发测试

有两个问题值得我们付出努力,而且这两个问题对于单用户功能运行都是不可见的。

  • 它能识别同时访问相同数据库记录、模块或应用程序代码所产生的影响。
  • 它可以识别和衡量死锁、锁定、单线程代码的使用以及对共享资源的受限访问的程度。

某个功能对一个用户来说可能完全正确,但对于一毫秒后到达的第二个用户来说仍然会丢失数据,这就是为什么这项技术与……并存的原因。 性能测试 而不是在功能测试内部。

如何执行并发测试

并发测试遵循可重复的顺序。以下步骤从 sco 开始。ping 以解决。

  • 步骤 1)识别容易发生并发的流程。 查找共享状态:同时登录、座位或股票预订、余额更新、批量作业写入同一张表以及路径中的任何单线程组件。
  • 步骤 2)设置并发目标。 根据实际使用高峰期而非整数,确定同一时刻必须有多少用户采取行动。
  • 步骤 3)设计测试用例。测试用例 将共享资源、竞争行为和预期的最终状态配对——例如,两个会话从同一个帐户取款不能同时成功。
  • 步骤 4)编写脚本并选择工具。 需要一个能够生成可配置虚拟用户的负载生成器; JMeter 是常见的开源选择,其线程组设置直接映射到并发场景。
  • 步骤5) Ramp 逐渐地。 分阶段增加并发用户数,而不是一下子增加。ping 到达目标位置,因此可以清楚地看到争斗开始的层级。
  • 步骤 6)监测和分析。 观察锁等待、响应时间差异、错误率和数据库阻塞情况——并发缺陷通常会先表现为时间异常,然后才会表现为错误。
  • 步骤 7)解决问题并重新运行。 修复同步、索引或锁定原因,然后重复相同的运行以确认行为已改变而不是发生了变化。

常见并发缺陷

并发缺陷可以归为少数几个可识别的类别,正确命名类别通常可以直接指出修复方法。

缺陷 会发生什么 典型症状
竞争条件 结果取决于哪个会话先结束。 有些比赛的总分正确,有些比赛的总分错误。
僵局 两个会话各自持有对方所需的锁 事务挂起而不是返回错误
丢失更新 第二次写入操作会覆盖第一次写入操作,而不会读取第一次写入操作。 已保存的更改悄无声息地消失了。
数据损坏 共享结构仅部分写入 处于无法创建有效交易的状态的记录
饥饿 某个会话始终无法获得它所等待的资源。 系统运行正常时,单个用户路径超时。

由于这些故障是间歇性的,因此每次运行都需要记录日志和时间戳;否则,无法通过以下方式令人信服地提出缺陷: 缺陷管理流程.

并发测试示例

假设一家网店库存中只剩最后一件商品。两名顾客同时打开商品页面,并同时按下购买按钮。 购买房产.

  • 场景: 两个会话读取库存 = 1,都通过了可用性检查,并且都写入库存 = 0。
  • 预期结果: 一个订单已确认,另一个订单收到缺货通知,库存永远不会变为负数。
  • 缺陷指标: 两个订单都确认,或者库存变为 -1,这表明可用性检查和减量操作不是作为一个原子步骤执行的。
  • 值得尝试的变体: 相同的两个会话编辑同一个个人资料记录,对同一个请求进行两次审批,并在用户保存时通过批量作业更新表格。

同样的模式可以推广:找到一个资源、两个写入者,但没有顺序保证。在运行场景期间 系统测试在添加负载之前,保持诊断清晰。

并发测试的优势

  • 它将并发交互的范围限制在少数几个广泛使用、经过充分测试的组件上,从而相对减少了测试应用程序所需的工作量。
  • 封装使得无需审查整个代码库即可分析程序的一部分的行为。
  • 它有助于提高并发程序的可靠性和鲁棒性。
  • 它能及早发现锁定和阻塞限制,因此容量决策取决于实际争用情况,而不是估计情况。

并发测试的缺点

测试人员在执行并发测试时通常会遇到以下缺点。

  • 该应用程序需要在多个平台上进行测试。
  • 并发场景需要比顺序场景更密集的测试。
  • 函数不会立即将结果返回给调用者;相反,结果可以稍后通过通知、代码块、回调函数或类似机制传递,这使得测试更加困难。
  • 信息或程序流未反映在调用堆栈中。
  • 由于并发系统中的进程在执行过程中会相互交互,因此系统中的执行路径数量可能非常庞大。
  • 并发程序的失败率比顺序程序高。
  • 调试并发程序很困难,因为附加调试器会改变导致故障的时序。

常见问题

序号 负载测试 衡量的是预期交易量下的行为随时间的变化。并发测试针对的是同一时刻,因此即使只有两个用户,如果他们都访问了同一条共享记录,也可能出现缺陷。

多线程部分 线程测试 两者有所重叠。线程测试考察的是某个业务路径在集成后是否仍然存在;并发测试考察的是在该路径已经正常运行的情况下,并发访问会产生什么影响。

用实际观测到的峰值使用量来计算,而不是用整数。先用两个会话来验证逻辑的有效性,然后逐渐增加会话数,直至达到测得的峰值,并在此基础上留出一定的余量。

机器学习模型根据以往缺陷记录和共享状态复杂度对模块进行排序,从而引导测试人员找到最有可能在重叠情况下出现故障的流程。然后,通过对重复运行的日志进行聚类,可以分离出每次故障发生前的交错操作。

GitHub 副驾驶 能够快速生成虚拟用户脚本、屏障和断言辅助函数。测试人员仍然需要定义哪些资源是共享的以及正确的最终状态是什么,因为生成的测试很少会强制出现真正的资源重叠。

隔离级别、锁超时、连接池大小和索引都会影响争用的表现形式。每次运行都应记录这些参数,因为在一种隔离级别下获得的结果并不能说明另一种隔离级别下的结果。

从干净的数据状态开始,多次重复相同的场景,保留带时间戳的日志,并缩小两个相互冲突的操作之间的时间间隔。附加调试器通常会通过改变时间而掩盖故障。

是的,对于数据量敏感型争用来说,小表可以让数据库将所有数据都保存在内存中,并短暂锁定,这样生产环境中出现的阻塞就不会被察觉。尽可能使行数和索引大小保持一致,只要环境允许即可。

总结一下这篇文章: