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

如何在Selenium多测试场景中复用2FA的SecretKeyReg

复用2FA密钥实现单次注册多测试用例登录

核心思路

要实现仅执行一次2FA注册并复用密钥,需要做到三点:

  • 把2FA密钥存储为类级别的共享变量,让所有测试用例都能访问。
  • 用测试框架的全局前置方法,在所有测试执行前仅调用一次registerFor2FA完成注册并保存密钥。
  • 修改enterGeneratedOTP方法,不再重复执行注册流程,直接使用已保存的密钥生成OTP。

代码重构示例

1. 调整类结构,添加共享密钥变量

在测试类中添加静态成员变量存储2FA密钥,确保跨测试用例共享:

public class Your2FATestClass {
    // 静态变量:整个测试类/套件共享的2FA密钥
    private static String secretKeyReg;
    private View view;
    private WebDriver webDriver;
    private static final String empPortalURL = "你的员工门户URL";

2. 实现全局前置注册方法

使用测试框架的注解(TestNG的@BeforeSuite/@BeforeClass,JUnit的@BeforeAll)执行一次2FA注册:

// TestNG:整个测试套件仅执行一次;如果用JUnit 5,替换为@BeforeAll且方法为static
    @BeforeSuite
    public void setup2FAOnce() {
        // 先完成网站登录等前置操作(如果registerFor2FA里没包含的话)
        // 执行2FA注册并保存密钥
        secretKeyReg = registerFor2FA();
    }

    // 修正原registerFor2FA方法,添加返回值
    public String registerFor2FA() {
        // 执行2FA注册流程(登录网站、开启2FA等逻辑)
        WebElement secretKey = view.getElement(By.xpath("你的密钥元素XPATH"));
        String secretKeyReg = secretKey.getText();
        
        // 生成初始OTP完成注册验证
        TOTP totp = new TOTP.Builder(secretKeyReg.getBytes(StandardCharsets.UTF_8))
                .withPasswordLength(6)
                .withAlgorithm(HMACAlgorithm.SHA1)
                .withPeriod(Duration.ofSeconds(30))
                .build();
        String code = totp.now();
        
        view.getElement(By.xpath("2-step-setup-code")).click();
        view.getElement(By.xpath("2-step-setup-code")).sendKeys(code);
        view.getElement(By.xpath("done-button")).click();
        
        return secretKeyReg; // 返回密钥供后续复用
    }

3. 修改enterGeneratedOTP方法,复用密钥

去掉方法内的注册调用,直接使用已保存的密钥生成OTP:

public void enterGeneratedOTP() {
        try {
            // 校验密钥是否已初始化
            if (secretKeyReg == null || secretKeyReg.trim().isEmpty()) {
                throw new IllegalStateException("2FA密钥未初始化,请先执行setup2FAOnce");
            }
            
            byte[] secret = secretKeyReg.getBytes(StandardCharsets.UTF_8);
            TOTP totp = new TOTP.Builder(secret)
                    .withPasswordLength(6)
                    .withAlgorithm(HMACAlgorithm.SHA1)
                    .withPeriod(Duration.ofSeconds(30))
                    .build();
            String code = totp.now();
            
            // 输入OTP
            view.getElement(By.xpath("authentication-code")).click();
            view.getElement(By.xpath("authentication-code")).sendKeys(code);
        } catch (Exception e) {
            System.err.println("生成/输入OTP失败: " + e.getMessage());
            throw e; // 抛出异常,确保测试失败时能定位问题
        }
    }

4. 测试用例无需修改,直接复用

原来的测试用例可以直接使用修改后的enterGeneratedOTP,不会再重复执行注册流程:

@Test
    public void loginUsing2FASuccessfulEmpPortal() {
        // 加载员工门户URL
        changeURL(webDriver, empPortalURL);
        
        // 账号密码登录
        view.getElement(By.xpath("username")).click();
        view.getElement(By.xpath("username")).sendKeys("test");
        view.sendKeys(Keys.TAB);
        view.getElement(By.xpath("password")).sendKeys("test");
        view.getElement(By.xpath("signin")).click();
        
        // 输入OTP(此时不会再执行2FA注册)
        enterGeneratedOTP();
        view.getElement(By.xpath("login")).click();
        
        sleep(5);
        // 登录成功断言
        // Assert.assertTrue(view.getElement(By.xpath("欢迎元素XPATH")).isDisplayed());
    }

    // 其他9个登录测试用例同理,直接调用enterGeneratedOTP即可
}

注意事项

  • 测试框架注解选择:如果你的测试是按类组织的,用@BeforeClass;如果是跨多个测试类的套件,用@BeforeSuite(TestNG)或@BeforeAll(JUnit,需静态方法)。
  • 状态隔离:如果每个测试用例需要从"未登录"状态开始,记得在每个测试前执行登出、清除Cookie或重启浏览器操作,避免前一个测试的登录状态干扰后续测试。
  • 代码修正:原代码中存在一些小问题(比如方法名大小写、变量名大小写、未返回值),重构时已一并修正,需注意保持代码规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:25:02