You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单Runner执行多Feature文件时用户认证变量实例化异常问题

多Feature文件共享认证模块时的用户隔离问题

我们最近实现了从JSON文件读取用户信息进行认证的功能,配置和Feature文件都已调整。但遇到一个问题:当所有Feature文件使用同一用户信息时认证正常,同时运行不同用户的多个Feature文件时,认证信息始终绑定单个用户,无法与对应Feature文件隔离,导致一组场景运行正常,另一组全部失败。

问题场景示例

  • 有两个测试用户:1个活跃用户、1个非活跃用户
  • 每个Feature文件的认证逻辑都调用共享的auth.js文件
  • 执行测试后,活跃用户的所有场景均通过,非活跃用户的所有场景均失败
  • 排查发现,两个Feature文件使用的认证信息完全相同

我们不确定是先执行还是后执行的认证请求覆盖了token,但目前使用的authToken变量未在不同Feature文件间做区分。现需确认两个问题:

  1. 这是否属于正常现象?是否每次只能运行单个用户对应的Feature文件,不同用户必须使用不同Runner或专属认证变量,不能共享auth.js函数?
  2. 还是说这是个bug?理论上即使调用共享资源,Feature文件的前置逻辑也应与自身绑定?

当前存在问题的执行逻辑:

活跃用户Feature -> 调用auth.js -> 全局实例化 authToken
非活跃用户Feature -> 调用auth.js -> 全局实例化 authToken

哪一次实例化的authToken会生效?先执行的?还是后执行的...

期望的执行逻辑:

活跃用户Feature -> 调用auth.js -> 在Feature(类或函数)级别实例化 active.authToken
非活跃用户Feature -> 调用auth.js -> 在Feature(类或函数)级别实例化 inactive.authToken

结论与解决方案

这不是bug,是全局变量共享导致的状态污染,属于典型的测试隔离问题。

问题根源

你的auth.js中authToken是全局变量,所有Feature文件共享同一个内存空间的变量值。不管哪个Feature先执行,后执行的认证请求都会覆盖全局的authToken,最终所有测试用的都是最后一次生成的token,导致非活跃用户的场景误用了活跃用户的token(或反过来),自然失败。

解决办法

核心是让每个Feature/场景拥有独立的认证状态,具体可按以下方式调整:

  1. 取消全局token变量,改为函数返回结果
    修改auth.js,让认证逻辑成为返回token的函数,每次调用生成独立的token:
    // auth.js 修改后
    async function authenticate(user) {
      // 从JSON读取用户信息、发起认证请求的逻辑
      const response = await fetch('/auth', {
        method: 'POST',
        body: JSON.stringify(user)
      });
      const data = await response.json();
      return data.authToken;
    }
    
  2. 在Feature上下文内保存专属token
    每个Feature在前置钩子(如Cucumber的Before)中调用认证函数,将token存在当前Feature的上下文里,而非全局:
    // 活跃用户Feature的步骤定义
    Before(async function () {
      const activeUser = require('./active-user.json');
      this.authToken = await authenticate(activeUser);
    });
    
    // 非活跃用户Feature的步骤定义
    Before(async function () {
      const inactiveUser = require('./inactive-user.json');
      this.authToken = await authenticate(inactiveUser);
    });
    
  3. 用类封装认证状态(可选)
    把认证逻辑封装成类,每个Feature实例化独立的类对象,各自管理token:
    // auth.js 改为类形式
    class AuthService {
      constructor(user) {
        this.user = user;
        this.authToken = null;
      }
    
      async login() {
        const response = await fetch('/auth', {
          method: 'POST',
          body: JSON.stringify(this.user)
        });
        const data = await response.json();
        this.authToken = data.authToken;
      }
    }
    
    // Feature中使用
    Before(async function () {
      const user = require('./active-user.json');
      this.authService = new AuthService(user);
      await this.authService.login();
    });
    

关于Runner的说明

不需要分开使用不同Runner,只要解决了状态隔离问题,同一个Runner下就能同时运行不同用户的Feature文件。


内容的提问来源于stack exchange,提问作者mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:13:31