TestNG实现每组数据执行完整测试周期的方法咨询
解决TestNG中每组DataProvider数据依次执行多步骤测试的问题
我明白你想要的效果:每组登录数据都独立走完「填写登录信息→执行登录」的完整流程,而不是先把所有数据的填写步骤跑完再统一执行登录。咱们先看看问题出在哪,再给你两种可行的解决方案。
问题根源
你的现有代码里,FillLoginDetails关联了@DataProvider会执行3次,但doLogin没关联数据提供者,只会执行1次。而且TestNG默认的执行逻辑是按方法批量执行:先把同一个@Test方法的所有DataProvider数据跑完,再执行下一个@Test方法,所以就会出现「所有填写步骤先完成,再执行一次登录」的情况,完全不符合你的预期。
另外还有个小问题:doLogin里硬编码了"Welcome, coin",这样只有第一组数据能通过验证,得改成动态使用当前测试数据的用户名。
方案一:合并步骤为单个测试方法(最简单)
把「填写登录信息」和「执行登录」合并到同一个@Test方法里,直接关联DataProvider。这样每组数据都会完整执行这两个步骤,顺序完全符合你的要求。
@DataProvider(name = "login") public static Object[][] usernamePassword() { return new Object[][] { { "coin", "coin123", true }, { "coin", "coin", false }, { "username", "password", false } }; } @Test(description = "完整登录流程", dataProvider = "login", priority = 1) public void completeLoginFlow(String user, String pass, boolean isSuccess) throws Exception { // 步骤1:填写登录信息 try { WebElement username = driver.findElement(By.id("uid")); username.sendKeys(user); WebElement password = driver.findElement(By.id("pwd")); password.sendKeys(pass); Thread.sleep(1000); TestNGResults.put("3", new Object[] { 2d, "Fill Login form data (Username/Password)", "Login details gets filled", "Pass" }); } catch (Exception e) { TestNGResults.put("3", new Object[] { 2d, "Fill Login form data (Username/Password)", "Login form gets filled", "Fail" }); Assert.assertTrue(false); } // 步骤2:执行登录并验证结果 try { WebElement loginBtn = driver.findElement(By.id("login-button")); loginBtn.click(); Thread.sleep(1000); if (isSuccess) { // 验证登录成功的欢迎信息 WebElement onlineUser = driver.findElement(By.cssSelector("h3.paddedleft > strong.ng-binding")); AssertJUnit.assertEquals("Welcome, " + user, onlineUser.getText()); TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login success", "Pass" }); } else { // 这里添加登录失败的验证逻辑(比如检查错误提示) TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login failed as expected", "Pass" }); } } catch (Exception e) { TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login process failed", "Fail" }); Assert.assertTrue(false); } }
方案二:使用@Factory创建独立测试实例(保留分开的方法)
如果必须把两个步骤拆成独立的@Test方法,可以用@Factory为每组DataProvider数据创建一个测试类实例,每个实例里的方法会按优先级依次执行。
public class LoginTest { private String user; private String pass; private boolean isSuccess; // 工厂构造方法,接收DataProvider的每组数据 @Factory(dataProvider = "login") public LoginTest(String user, String pass, boolean isSuccess) { this.user = user; this.pass = pass; this.isSuccess = isSuccess; } @DataProvider(name = "login") public static Object[][] usernamePassword() { return new Object[][] { { "coin", "coin123", true }, { "coin", "coin", false }, { "username", "password", false } }; } @Test(description = "填写登录信息", priority = 2) public void fillLoginDetails() throws Exception { try { WebElement username = driver.findElement(By.id("uid")); username.sendKeys(user); WebElement password = driver.findElement(By.id("pwd")); password.sendKeys(pass); Thread.sleep(1000); TestNGResults.put("3", new Object[] { 2d, "Fill Login form data (Username/Password)", "Login details gets filled", "Pass" }); } catch (Exception e) { TestNGResults.put("3", new Object[] { 2d, "Fill Login form data (Username/Password)", "Login form gets filled", "Fail" }); Assert.assertTrue(false); } } @Test(description = "执行登录", priority = 3, dependsOnMethods = "fillLoginDetails", alwaysRun = true) public void doLogin() throws Exception { try { WebElement loginBtn = driver.findElement(By.id("login-button")); loginBtn.click(); Thread.sleep(1000); if (isSuccess) { WebElement onlineUser = driver.findElement(By.cssSelector("h3.paddedleft > strong.ng-binding")); AssertJUnit.assertEquals("Welcome, " + user, onlineUser.getText()); TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login success", "Pass" }); } else { // 添加登录失败的验证逻辑 TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login failed as expected", "Pass" }); } } catch (Exception e) { TestNGResults.put("4", new Object[] { 3d, "Click Login and verify welcome message", "Login process failed", "Fail" }); Assert.assertTrue(false); } } }
这个方案的关键逻辑:
@Factory会遍历DataProvider的每组数据,为每组数据创建一个LoginTest实例- 每个实例中的
fillLoginDetails(优先级2)会先执行,然后doLogin(优先级3,且依赖前者)执行 - 这样每组数据对应的实例会独立完成两个步骤,执行顺序完全符合你的需求:
数据1的填写→数据1的登录 数据2的填写→数据2的登录 数据3的填写→数据3的登录
内容的提问来源于stack exchange,提问作者Rizqi Ahmad Fauzan
相关产品推荐
相关产品推荐

