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

