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

如何在Cucumber中实现基于Actor的数据驱动动态登录账号

实现Cucumber+Serenity/JS动态凭据登录(数据驱动)

我来帮你搞定这个动态获取用户名密码的需求,核心思路是把用户的登录凭据存在JSON配置文件里,然后在登录任务中根据Feature文件传入的Actor名称,动态读取对应的账号信息。下面是具体实现步骤:

1. 创建用户凭据配置文件

首先新建一个user-credentials.json文件,把不同用户的登录信息存在这里:

{
  "Bruno": {
    "email": "bruno@test.com",
    "password": "bruno123"
  },
  "Alice": {
    "email": "alice@test.com",
    "password": "alice456"
  },
  "Admin": {
    "email": "admin@shop.com",
    "password": "adminPass123"
  }
}

以后要新增或修改用户信息,直接改这个文件就行,不用动测试代码。

2. 修改LoginUser任务,动态读取凭据

更新你的login-user.ts,让它能读取JSON文件,并根据传入的Actor名称获取对应的邮箱和密码:

import { Task, step, PerformsTasks } from "serenity-js/lib/screenplay";
import { Click, Enter } from "serenity-js/lib/screenplay-protractor";
import { homePageElementsMap } from "../interactions/html-elements/pages-elements-maps/home-page-elements-maps";
import { loginPageElementsMap } from "../interactions/html-elements/pages-elements-maps/login-page-elements-map";
// 导入模块读取JSON文件
import * as fs from 'fs';
import * as path from 'path';

export class LoginUser implements Task {
  static called(name: string): LoginUser {
    return new LoginUser(name);
  }

  @step('{0} logs in with their credentials')
  performAs(actor: PerformsTasks): PromiseLike<void> {
    // 读取JSON文件,路径根据你的项目结构调整
    const credentialsPath = path.resolve(__dirname, '../../user-credentials.json');
    const credentials = JSON.parse(fs.readFileSync(credentialsPath, 'utf8'));
    // 根据传入的name获取对应用户的信息
    const user = credentials[this.name];

    if (!user) {
      throw new Error(`No credentials found for user: ${this.name}`);
    }

    return actor.attemptsTo(
      Click.on(homePageElementsMap.lnk_login),
      Enter.theValue(user.email).into(loginPageElementsMap.txt_login_email),
      Enter.theValue(user.password).into(loginPageElementsMap.txt_login_pwd),
      Click.on(loginPageElementsMap.btn_login)
    );
  }

  constructor(private name: string) { }
}

这里做了几个关键优化:

  • 引入fs和path模块读取本地JSON配置
  • 根据Actor名称匹配对应的用户凭据
  • 增加错误处理,找不到对应用户时抛出明确提示

3. 调整Steps文件,传递Actor名称到登录任务

更新example.steps.ts里的Given步骤,确保把Feature里的name参数传递给LoginUser任务:

import { Actor } from "serenity-js/lib/screenplay";
import { BrowseTheWeb } from "serenity-js/lib/screenplay-protractor";
import { protractor } from "protractor";
import { Start, AddItemsToShoppingBag } from "../website-model/src/index";
import { Authenticate } from '../website-model/src/ability/authenticate';
// 导入修改后的LoginUser任务
import { LoginUser } from './login-user';

protractor.browser.ignoreSynchronization = true;

export = function selectItemSteps() {
 let actor: Actor;

 this.Given(/^that "([^"]*)" is logged in to his "([^"]*)" account$/, function (name: string, pageUrl: string) {
  // 用Feature传入的name初始化Actor,不再硬编码
  actor = Actor.named(name).whoCan(BrowseTheWeb.using(protractor.browser));
  return actor.attemptsTo(
    Start.LaunchUrl(pageUrl), // 先打开指定页面
    LoginUser.called(name)    // 调用动态登录任务
  );
 });

 this.When(/^he searches and adds an item from "([^"]*)" section to his shopping bag$/, function (gender:string) {
  return actor.attemptsTo(
    AddItemsToShoppingBag.called(gender)
  );
 });

 this.Then(/^he can place the order$/, function () {
  return actor.attemptsTo(
    // 补充你的下单逻辑
  );
 });
}

这里的核心修改:

  • 把Actor的初始化移到Given步骤,用Feature传入的名称动态创建
  • 明确调用LoginUser.called(name)执行动态登录逻辑

验证效果

现在你可以在Feature文件里替换不同的Actor名称,比如把"Bruno"改成"Alice",测试代码就会自动读取Alice的凭据完成登录,完全实现了数据驱动的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:05:41