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

Java版Selenium自动化框架WebDriver传递异常及正确实现咨询

问题分析与修正方案

你当前的实现存在几个关键问题,导致WebDriver传递异常,下面逐一说明并给出修正:

核心问题

  1. 内部类设计不合理:Login作为Basepage的内部类会增加耦合,且父类driver未被正确赋值
  2. 重复定义WebDriver:Basepage和Login都定义了driver,导致父类的driver始终为null,不得不额外传driver1
  3. 测试方法位置错误:@Test注解的方法不应放在Page类中,需单独放在测试类
  4. 冗余参数传递:reportStep和takeSnap完全可以直接使用父类初始化后的driver,不需要额外传入driver1

修正后的代码

1. Basepage 重构

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.OutputType;
import org.apache.commons.io.FileUtils;
import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.ExtentTest;
import java.io.File;
import java.io.IOException;

public class Basepage {
    protected WebDriver driver;
    protected ExtentTest test; // 确保已通过测试类注入ExtentTest实例

    // 构造方法初始化driver和test
    public Basepage(WebDriver driver, ExtentTest test) {
        this.driver = driver;
        this.test = test;
    }

    public void reportStep(String stepinfo, String status) {
        int snapnumber = takeSnap();
        try {
            if (status.equalsIgnoreCase("pass")) {
                test.pass(stepinfo, MediaEntityBuilder.createScreenCaptureFromPath(".././snaps/img" + snapnumber + ".png").build());
            } else if (status.equalsIgnoreCase("fail")) {
                test.fail(stepinfo, MediaEntityBuilder.createScreenCaptureFromPath(".././snaps/img" + snapnumber + ".png").build());
                throw new RuntimeException("See extend report for more details");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int takeSnap() {
        int rannumber = (int) (Math.random() * 999999 + 1000000);
        try {
            File source = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            File target = new File("./snaps/img" + rannumber + ".png");
            FileUtils.copyFile(source, target);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rannumber;
    }
}

2. Login 页面类

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import com.aventstack.extentreports.ExtentTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Login extends Basepage {
    private static final Logger logfile = LoggerFactory.getLogger(Login.class);

    @FindBy(xpath = "//input[@name='username']")
    private WebElement username;

    // 构造方法调用父类构造,初始化driver和test
    public Login(WebDriver driver, ExtentTest test) {
        super(driver, test);
        PageFactory.initElements(driver, this);
    }

    public Login enterUserName(String uName) {
        try {
            username.sendKeys(uName);
            reportStep("Username entered successfully ", "pass");
            logfile.info("Username entered: {}", uName);
        } catch (Exception e) {
            reportStep("Username not entered successfully " + e.getMessage(), "fail");
            logfile.error("Failed to enter username: {}", e.getMessage());
        }
        return this;
    }

    // 其他登录相关方法(如输入密码、点击登录)可在此扩展
}

3. 测试类(单独存放)

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.reporter.ExtentSparkReporter;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class LoginTest {
    private WebDriver driver;
    private ExtentReports extent;
    private ExtentTest test;

    @BeforeTest
    public void setup() {
        // 初始化WebDriver
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("你的登录页面URL");

        // 初始化ExtentReports
        ExtentSparkReporter sparkReporter = new ExtentSparkReporter("extent-report.html");
        extent = new ExtentReports();
        extent.attachReporter(sparkReporter);
        test = extent.createTest("OrangeHRM Login Test");
    }

    @Test
    public void LoginOrangeHrm() {
        Login lp = new Login(driver, test);
        lp.enterUserName("admin");
        // 继续调用输入密码、点击登录等方法
    }

    @AfterTest
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
        extent.flush();
    }
}

关键修正点说明

  • WebDriver传递:通过父类构造方法将driver从测试类传递到Basepage,所有子类直接继承使用,无需重复定义或额外传递
  • ExtentTest注入:将ExtentTest实例也通过构造注入Basepage,确保reportStep方法能正常使用
  • 职责分离:Page类只负责页面元素操作,测试逻辑放在单独的测试类中,符合Page Object Model(POM)设计思想
  • 移除冗余参数:reportStep和takeSnap直接使用父类的driver,避免参数传递混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:56:01