如何在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
相关产品推荐
相关产品推荐

