「Jenkins Pipeline」- 集成 Selenium 测试

  CREATED BY JENKINSBOT

问题描述

我们需要在 Jenkins Pipeline 中使用 Selenium 自动化测试,该笔记将记录实现 Jenkins + Selenium 自动化测试的方法。

解决方法

我们所面对的问题,以及对应的解决方案已经在 #1 中说明,以下是我们最终的解决方案(有些无奈):
1)脱离 Jenkins 而实现自己的自动化脚本,通过退出状态反映自动化测试结果;
2)在 Jenkins Pipeline 中使用 sh 执行脚本,并获取退出状态;
3)通过自动化脚本的退出状态,判断自动化测试是否成功,并执行后续的操作及任务;

代码参考(我们只记录关键步骤):

pipeline {
    agent any
    stages {
        stage('build') {
            steps {
            	script {
            		def statusCode = sh returnStatus: true, script: "groovy selenium.groovy"
            		if (statusCode != 0) {
            			// 执行失败
            		}
            	}
            }
        }
    }
}

关于 sh 的用法可以参考 Shell Command 笔记,或者官方 Pipeline: Nodes and Processes/sh 文档。

常见问题汇总

java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V

java – NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;J)V – Stack Overflow
Maven Repository: org.seleniumhq.selenium » selenium-java » 3.141.59

问题描述:

在 Jenkins Pipeline 中,使用 Selenium Java 类库,在执行自动化测试程序时,返回错误:

// 程序代码
@Grab(group='org.seleniumhq.selenium', module='selenium-java', version='3.141.59')
...
WebDriver webDriver = new RemoteWebDriver(new URL(seleniumHub), desiredCapabilities);
...

// 错误信息
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
	at com.google.common.reflect.TypeCapture.capture(TypeCapture.java:32)
	at com.google.common.reflect.TypeToken.<init>(TypeToken.java:125)
	at org.openqa.selenium.json.Json$1.<init>(Json.java:33)
	at org.openqa.selenium.json.Json.<clinit>(Json.java:33)
	at org.openqa.selenium.remote.NewSessionPayload.create(NewSessionPayload.java:100)
	at org.openqa.selenium.remote.NewSessionPayload.create(NewSessionPayload.java:94)
	at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:68)
	at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:136)
	at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
	at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:213)
	at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:131)
	at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:144)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
	at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.constructorCall(DefaultInvoker.java:25)
...

问题原因:

1)Selenium Java 3.141.59 需要使用 com.google.guava.guava 25.0-jre 类库
2)但是 Jenkins 2.241 也使用该类库,但是在 Jenkins 中该类库的版本非常旧(com.google.guava/guava/11.0.1)
3)因此导致 Selenium Java 调用旧版本的 Guava 类库,程序无法正常执行

解决办法:

# 不可行 # 最开始我们在编辑器中开发自动化测试程序(Selenium Java),现在要集成到 Jenkins 中(即代码复制到 Pipeline 中执行)才出现这个问题。我们无法强制指定 com.google.guava/guava/11.0.1 类库,因为该类库在 Jenkins 中已经加载,因此即使使用 @Grab 指定也不会成功。我们不会也不想使用那些奇技淫巧,比如改变类加载方式,这只会给以后带来麻烦。

# 不可行 # 也无法通过 Docker 节点运行,因为节点执行 Pipeline 也要载入 Jenkins 运行环境,依旧会出现同样的问题。

# 不可行 # 那在 Jenkins 中有没有 Selenium 插件呢?现有 Selenium 插件,该插件只是使 Jenkins 集群中增加 Selenium 集群,并且在 Jenkins 中增加 Selenium 管理界面。并不能解决我们的问题。

# 方案一 # 我们开始在网上寻找解决方法,很多做法大同小异,常见的做法是 maven test 执行自动化测试,本质上将就是脱离 Jenkins 而在命令行执行自动化测试脚本。最后我们也采用了这种做法:使用 Groovy 脚本,然后在 Jenkins 中执行 groovy 命令

我们只能选择# 方案一 #,因为只有# 方案一 #是 我们唯一能想到的可行的 方案。

参考文献

Integration of Jenkins with Selenium WebDriver: Step-by-Step Tutorial
Maven & Jenkins Integration with Selenium: Complete Tutorial
How to Setup and Run Selenium Tests in Jenkins Using Maven and JUnit | BlazeMeter