TestNG中多个@Test方法如何读取@BeforeTest内的Excel测试变量
问题解决说明
核心问题原因
- 变量作用域错误:你在类中已经声明了
workbook、sheet等成员变量,但在@BeforeTest方法中又重复定义了同名局部变量,导致成员变量始终未被赋值,@Test方法自然无法读取到有效值。同时你在循环中定义的userName、passWord也是局部变量,作用域仅限循环内部,外部方法完全访问不到。 - 逻辑设计错误:
@BeforeTest中的循环会重复实例化ChromeDriver,循环结束后仅会保留最后一行测试数据对应的driver实例和账号密码,前面所有行的测试数据都会被覆盖丢失。 - 语法错误:代码中存在多处类型不匹配问题,比如
getText()返回的是字符串类型,你直接赋值给WebElement变量会直接编译报错,密码输入方法中错误传入了用户名变量等。 - 依赖逻辑误区:
dependsOnMethods仅能保证被依赖方法执行成功后再运行当前测试,本身不具备跨方法传递局部变量的能力。
最优解决方案
推荐用TestNG原生的@DataProvider注解实现Excel参数化,这是TestNG处理多测试用例的标准方案,不需要手动在前置方法里循环读数据,修正后代码如下:
import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.testng.annotations.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class Login { WebDriver driver; // 封装Excel测试数据读取逻辑 @DataProvider(name = "loginTestData") public Object[][] getLoginData() throws IOException { FileInputStream file = new FileInputStream(new File("D:\\codtest.xlsx")); XSSFWorkbook workbook = new XSSFWorkbook(file); XSSFSheet sheet = workbook.getSheetAt(0); int rowCount = sheet.getLastRowNum(); Object[][] data = new Object[rowCount][2]; // 遍历所有行将数据存入二维数组返回 for (int i = 1; i <= rowCount; i++) { data[i-1][0] = sheet.getRow(i).getCell(0).getStringCellValue(); data[i-1][1] = sheet.getRow(i).getCell(1).getStringCellValue(); } workbook.close(); file.close(); return data; } // 每个测试方法执行前初始化干净的浏览器环境 @BeforeMethod public void browserSetup() { System.setProperty("webdriver.chrome.driver", "drivers\\chromedriver.exe"); driver = new ChromeDriver(); driver.get("https://opensource-demo.orangehrmlive.com/"); driver.manage().window().maximize(); } // 测试用户名校验逻辑,自动绑定DataProvider的所有测试数据 @Test(dataProvider = "loginTestData") public void userNameVerify(String userName, String passWord){ // 仅输入密码不输入用户名,触发用户名校验 driver.findElement(By.id("txtPassword")).sendKeys(passWord); driver.findElement(By.id("btnLogin")).click(); String errorMessage = driver.findElement(By.xpath("//*[@id=\"spanMessage\"]")).getText(); if(errorMessage.contains("Username cannot be empty")) { System.out.println("用户名校验通过:必填提示正常显示"); } } // 测试密码校验逻辑,自动绑定DataProvider的所有测试数据 @Test(dataProvider = "loginTestData") public void passWordVerify(String userName, String passWord){ // 仅输入用户名不输入密码,触发密码校验 driver.findElement(By.id("txtUsername")).sendKeys(userName); driver.findElement(By.id("btnLogin")).click(); String errorMessage = driver.findElement(By.xpath("//*[@id=\"spanMessage\"]")).getText(); if(errorMessage.contains("Password cannot be empty")) { System.out.println("密码校验通过:必填提示正常显示"); } } // 每个测试方法执行后关闭浏览器,避免用例互相影响 @AfterMethod public void tearDown() { driver.quit(); } }
可选调整说明
如果需要复用同一个浏览器实例测试所有用例,可以把@BeforeMethod改成@BeforeTest,@AfterMethod改成@AfterTest,注意每次执行完测试用例后要清空输入框内容即可。
内容的提问来源于stack exchange,提问作者Lakshika Maduwanthi
相关产品推荐
相关产品推荐

