Jenkins运行Selenium测试报java.lang.ExceptionInInitializerError异常
基于Maven、TestNG框架实现的Selenium自动化测试用例,在本地IntelliJ环境、终端命令行下执行均正常,通过本地Jenkins任务调度执行时抛出java.lang.ExceptionInInitializerError: null异常。
- 操作系统:Linux Ubuntu 20.04
- Jenkins版本:2.332.3
- Java版本:11
- Jenkins任务配置:任务类型为Maven Job,根POM路径为
/pom.xml,执行Goals and options为test - Chromedriver版本:101.0.4951.41
- TestNG启动告警:检测到
general.BaseTest类下的afterMethod()、beforeTest()、afterTest()、beforeMethod()为静态方法,静态配置方法可能引发非预期行为 - Chromedriver启动正常,监听端口58950,仅允许本地连接
- 测试执行结果:共运行5个用例,失败2个,错误0个,跳过3个,总耗时61.4秒
- 失败堆栈详情:login用例的
beforeMethod执行阶段抛出java.lang.ExceptionInInitializerError,异常堆栈指向Selenium创建Chrome会话的org.openqa.selenium.remote.ProtocolHandshake.createSession调用链,最终触发位置为general.functions类静态初始化块;afterMethod执行阶段抛出java.lang.NoClassDefFoundError: Could not initialize class general.functions异常 - 构建失败提示:存在测试失败,单测结果详情可查看路径
/home/vend-sarosh/Documents/Web/Selenium/target/surefire-reports
1. 优先修复Chrome启动参数适配Jenkins运行环境
Jenkins服务默认以jenkins系统用户后台运行,没有桌面图形会话访问权限,直接启动带GUI的Chrome必然触发初始化失败,在general.functions类的Chrome初始化逻辑中添加以下参数:
ChromeOptions options = new ChromeOptions(); // 启用新版无头模式,不依赖图形桌面 options.addArguments("--headless=new"); // 关闭沙箱,服务用户/root用户启动Chrome必须配置 options.addArguments("--no-sandbox"); // 禁用/dev/shm共享内存,避免容器/服务环境下内存不足导致崩溃 options.addArguments("--disable-dev-shm-usage"); // 禁用GPU渲染,无头模式下兼容配置 options.addArguments("--disable-gpu"); // 固定窗口分辨率,避免元素定位偏移 options.addArguments("--window-size=1920,1080");
2. 修正TestNG生命周期方法的错误修饰符
TestNG的@BeforeMethod、@AfterMethod、@BeforeTest、@AfterTest注解标注的生命周期方法不能使用static修饰,静态方法会打破TestNG的实例隔离逻辑,导致类初始化时机混乱,跨用例共享静态驱动实例触发连锁报错。把这几个方法的static修饰符全部删除,WebDriver实例不要定义为静态变量,按测试生命周期单独维护实例即可。
3. 校验Chrome与Chromedriver版本一致性
Jenkins执行任务时的环境变量PATH和你本地登录用户的PATH可能不一致,不要默认认为调用的Chrome版本正确。在Jenkins任务中添加一个Shell执行步骤,运行google-chrome --version打印实际加载的Chrome版本,必须和当前101版本的Chromedriver完全匹配,版本不一致时升级/降级对应版本即可。
4. 非无头模式的特殊配置(不推荐)
如果必须使用带GUI的模式运行,需要给Jenkins用户开放当前桌面的X11访问权限:
- 本地桌面终端执行
echo $DISPLAY记录当前显示端口,一般为:0 - 执行
sudo xhost +local:jenkins给Jenkins用户授权X11访问 - 在Jenkins任务的环境变量中添加配置
DISPLAY=:0
注意该方案要求运行Jenkins的机器必须全程保持桌面登录状态,锁屏、注销都会导致用例执行失败,仅适合临时调试使用。
验证方式
修复完成后,先在终端切换到jenkins用户执行mvn test,如果该场景下用例全部跑通,再触发Jenkins任务即可正常执行。
内容的提问来源于stack exchange,提问作者NinjaPotato

